Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit c5ea33a

Browse files
committed
updated activecode.py to bring back support for the textfield directive
1 parent 3a6ebad commit c5ea33a

File tree

2 files changed

+104
-270
lines changed

2 files changed

+104
-270
lines changed

runestone/activecode/activecode.py

Lines changed: 49 additions & 270 deletions
Original file line numberDiff line numberDiff line change
@@ -14,239 +14,87 @@
1414
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1515
#
1616

17-
__author__ = 'bmiller'
17+
__author__ = 'isaiahmayerchak'
1818

1919
from docutils import nodes
2020
from docutils.parsers.rst import directives
2121
from docutils.parsers.rst import Directive
22+
from .textfield import *
2223

2324

2425
def setup(app):
2526
app.add_directive('activecode', ActiveCode)
26-
app.add_directive('actex', ActiveExercise)
27-
app.add_stylesheet('codemirror.css')
2827
app.add_stylesheet('activecode.css')
2928

30-
app.add_javascript('jquery.highlight.js')
31-
app.add_javascript('bookfuncs.js')
29+
app.add_javascript('skulpt.min.js')
30+
app.add_javascript('skulpt-stdlib.js')
3231
app.add_javascript('codemirror.js')
33-
app.add_javascript('xml.js')
34-
app.add_javascript('css.js')
35-
app.add_javascript('htmlmixed.js')
3632
app.add_javascript('python.js')
37-
app.add_javascript('javascript.js')
3833
app.add_javascript('activecode.js')
39-
app.add_javascript('skulpt.min.js')
40-
app.add_javascript('skulpt-stdlib.js')
34+
35+
app.add_role('textfield', textfield_role)
4136

4237
app.add_node(ActivcodeNode, html=(visit_ac_node, depart_ac_node))
4338

4439
app.connect('doctree-resolved', process_activcode_nodes)
4540
app.connect('env-purge-doc', purge_activecodes)
4641

4742

48-
START = '''
49-
<div id="cont"></div>
50-
<div id="%(divid)s" lang="%(language)s" time="%(timelimit)s" class="ac_section alert alert-warning" >
51-
'''
52-
53-
EDIT1 = '''
54-
</div>
55-
<br/>
56-
<div id="%(divid)s_code_div" style="display: %(hidecode)s" class="ac_code_div">
57-
<textarea cols="50" rows="12" id="%(divid)s_code" class="active_code" prefixcode="%(include)s" lang="%(language)s">
58-
%(initialcode)s
59-
</textarea>
60-
</div>
61-
'''
62-
63-
CAPTION = '''
64-
<div class="clearfix"></div>
65-
<p class="ac_caption"><span class="ac_caption_text">%(caption)s (%(divid)s)</span> </p>
66-
'''
67-
68-
UNHIDE = '''
69-
<span class="ac_sep"></span>
70-
<button class='btn btn-default' id="%(divid)s_showb" onclick="$('#%(divid)s_code_div').toggle();cm_editors['%(divid)s_code'].refresh();$('#%(divid)s_saveb').toggle();$('#%(divid)s_loadb').toggle()">Show/Hide Code</button>
71-
'''
72-
73-
GRADES = '''
74-
<span class="ac_sep"></span>
75-
<input type="button" class='btn btn-default ' id="gradeb" name="Show Feedback" value="Show Feedback" onclick="createGradeSummary('%(divid)s')"/>
76-
'''
77-
78-
AUDIO = '''
79-
<span class="ac_sep"></span>
80-
<input type="button" class='btn btn-default ' id="audiob" name="Play Audio" value="Start Audio Tour" onclick="createAudioTourHTML('%(divid)s','%(argu)s','%(no_of_buttons)s','%(ctext)s')"/>
81-
'''
82-
83-
EDIT2 = '''
84-
<div class="ac_actions">
85-
<button class='btn btn-success' id="%(divid)s_runb">Run</button>
86-
<button class="ac_opt btn btn-default" style="display: inline-block" id="%(divid)s_saveb" onclick="saveEditor('%(divid)s');">Save</button>
87-
<button class="ac_opt btn btn-default" style="display: inline-block" id="%(divid)s_loadb" onclick="requestCode('%(divid)s');">Load</button>
88-
'''
89-
90-
VIZB = '''<button class='btn btn-default' id="%(divid)s_vizb" onclick="injectCodelens(this,'%(divid)s');">Show in Codelens</button>
91-
'''
92-
93-
COACHB = '''<button class='ac_opt btn btn-default' id="%(divid)s_coach_b" onclick="injectCodeCoach('%(divid)s');">Code Coach</button>
94-
'''
95-
96-
SCRIPT = '''
97-
<script>
98-
if ('%(hidecode)s' == 'none') {
99-
// a hack to preserve the inline-block display style. Toggle() will use display: block
100-
// (instead of inline-block) if the previous display style was 'none'
101-
$('#%(divid)s_saveb').toggle();
102-
$('#%(divid)s_loadb').toggle();
103-
}
104-
if ($("#%(divid)s").attr("lang") !== "html" && $("#%(divid)s_code_div").parents(".admonition").length == 0 && $("#%(divid)s_code_div").parents("#exercises").length == 0){
105-
if ($(window).width() > 975){
106-
$("#%(divid)s_code_div").offset({
107-
left: $("#%(divid)s .clearfix").offset().left
108-
});
109-
}
110-
$("#%(divid)s_runb").one("click", function(){
111-
$({})
112-
.queue(function (next) {
113-
if ($(window).width() > 975){
114-
$("#%(divid)s_code_div").animate({
115-
left: 40
116-
}, 500, next);
117-
if (! Sk.TurtleGraphics ) {
118-
Sk.TurtleGraphics = {};
119-
}
120-
Sk.TurtleGraphics.height = 320;
121-
Sk.TurtleGraphics.width = 320;
122-
}
123-
else{
124-
next();
125-
}
126-
})
127-
.queue(function (next) {
128-
$("#%(divid)s_runb").parent().siblings(".ac_output").show();
129-
runit('%(divid)s',this, %(include)s);
130-
$("#%(divid)s_runb").on("click", function(){
131-
runit('%(divid)s',this, %(include)s);
132-
});
133-
})
134-
135-
});
136-
}
137-
else{
138-
$("#%(divid)s_code_div").css({float : "none", marginLeft : "auto", marginRight : "auto"});
139-
$("#%(divid)s_runb").parent().siblings(".ac_output").show().css({float : "none", right : "0px"});
140-
$("#%(divid)s_runb").on("click", function(){
141-
runit('%(divid)s',this, %(include)s);
142-
});
143-
}
144-
</script>
145-
'''
146-
OUTPUT_START = '''
147-
<div class="ac_output">'''
148-
149-
CANVAS = '''
150-
<div style="text-align: center">
151-
<div id="%(divid)s_canvas" class="ac-canvas" style="border-style: solid; text-align: center"></div>
152-
</div>
153-
'''
154-
155-
SUFF = '''<pre id="%(divid)s_suffix" style="display:none">%(suffix)s</pre>'''
156-
157-
PRE = '''<pre id="%(divid)s_pre" class="active_out"></pre>
158-
'''
159-
OUTPUT_END = '''
160-
</div> <!-- end output -->'''
161-
162-
VIZ = '''<div id="%(divid)s_codelens_div" style="display:none"></div>'''
163-
164-
# <iframe id="%(divid)s_codelens" width="800" height="500" style="display:block"src="#">
165-
# </iframe>
166-
167-
COACH = '''<div id="%(divid)s_coach_div" style="display:none;"></div>'''
168-
169-
HTMLOUT = '''<div id="%(divid)s_htmlout" style="display:none;" class="ac_htmlout"></div>'''
170-
171-
END = '''
172-
</div>
173-
174-
'''
175-
176-
AUTO = '''
177-
<script type="text/javascript">
178-
$(document).ready(function() {
179-
$(window).load(function() {
180-
var runb = document.getElementById("%(divid)s_runb");
181-
runit('%(divid)s',runb, %(include)s);
182-
});
183-
});
184-
</script>
185-
'''
186-
43+
TEMPLATE = """
44+
<pre data-component="activecode" id=%(divid)s data-lang="%(language)s" %(autorun)s %(hidecode)s %(include)s %(timelimit)s %(coach)s %(codelens)s>
45+
%(initialcode)s
46+
</pre>
47+
"""
18748

18849
class ActivcodeNode(nodes.General, nodes.Element):
18950
def __init__(self, content):
19051
"""
191-
19252
Arguments:
19353
- `self`:
19454
- `content`:
19555
"""
19656
super(ActivcodeNode, self).__init__()
197-
self.ac_components = content
57+
self.ac_options = content
19858

199-
200-
# self for these functions is an instance of the writer class. For example
201-
# in html, self is sphinx.writers.html.SmartyPantsHTMLTranslator
202-
# The node that is passed as a parameter is an instance of our node class.
20359
def visit_ac_node(self, node):
20460
# print self.settings.env.activecodecounter
205-
res = START
206-
if 'above' in node.ac_components:
207-
res += CANVAS
208-
if 'tour_1' not in node.ac_components:
209-
res += EDIT2
61+
res = ""
62+
63+
if 'language' not in node.ac_options:
64+
node.ac_options['language'] = 'python'
65+
66+
if 'autorun' in node.ac_options:
67+
node.ac_options['autorun'] = 'data-autorun'
68+
else:
69+
node.ac_options['autorun'] = ''
70+
71+
if 'hidecode' in node.ac_options:
72+
node.ac_options['hidecode'] = 'data-hidecode'
73+
else:
74+
node.ac_options['hidecode'] = ''
75+
76+
if 'include' in node.ac_options:
77+
node.ac_options['include'] = 'data-include=' + str(node.ac_options['include'])
21078
else:
211-
res += EDIT2 + AUDIO
212-
if node.ac_components['codelens']:
213-
res += VIZB
214-
215-
if 'coach' in node.ac_components:
216-
res += COACHB
217-
218-
if 'hidecode' not in node.ac_components:
219-
node.ac_components['hidecode'] = 'block'
220-
if node.ac_components['hidecode'] == 'none':
221-
res += UNHIDE
222-
if 'gradebutton' in node.ac_components:
223-
res += GRADES
224-
res += EDIT1
225-
res += OUTPUT_START
226-
if 'above' not in node.ac_components:
227-
if 'nocanvas' not in node.ac_components:
228-
res += CANVAS
229-
if 'suffix' in node.ac_components:
230-
res += SUFF
231-
if 'nopre' not in node.ac_components:
232-
res += PRE
233-
if 'autorun' in node.ac_components:
234-
res += AUTO
235-
res += OUTPUT_END
236-
res += CAPTION
237-
238-
if node.ac_components['codelens']:
239-
res += VIZ
240-
241-
if 'coach' in node.ac_components:
242-
res += COACH
243-
244-
if node.ac_components['language'] == 'html':
245-
res += HTMLOUT
246-
247-
res += SCRIPT
248-
res += END
249-
res = res % node.ac_components
79+
node.ac_options['include'] = ''
80+
81+
if 'timelimit' in node.ac_options:
82+
node.ac_options['timelimit'] = 'data-timelimit=' + str(node.ac_options['timelimit'])
83+
else:
84+
node.ac_options['timelimit'] = ''
85+
86+
if 'coach' in node.ac_options:
87+
node.ac_options['coach'] = 'data-coach'
88+
else:
89+
node.ac_options['coach'] = ''
90+
91+
if 'codelens' in node.ac_options:
92+
node.ac_options['codelens'] = 'data-codelens'
93+
else:
94+
node.ac_options['codelens'] = ''
95+
96+
res += TEMPLATE % node.ac_options
97+
25098
res = res.replace("u'", "'") # hack: there must be a better way to include the list and avoid unicode strings
25199

252100
self.body.append(res)
@@ -300,80 +148,11 @@ def run(self):
300148

301149
self.options['divid'] = self.arguments[0]
302150

303-
if self.content:
304-
if '====' in self.content:
305-
idx = self.content.index('====')
306-
source = "\n".join(self.content[:idx])
307-
suffix = "\n".join(self.content[idx + 1:])
308-
else:
309-
source = "\n".join(self.content)
310-
suffix = "\n"
311-
else:
312-
source = '\n'
313-
suffix = '\n'
314-
151+
source = "\n".join(self.content)
315152
self.options['initialcode'] = source
316-
self.options['suffix'] = suffix
317-
str = source.replace("\n", "*nline*")
318-
str0 = str.replace("\"", "*doubleq*")
319-
str1 = str0.replace("(", "*open*")
320-
str2 = str1.replace(")", "*close*")
321-
str3 = str2.replace("'", "*singleq*")
322-
self.options['argu'] = str3
323-
324-
complete = ""
325-
no_of_buttons = 0
326-
okeys = list(self.options.keys())
327-
for k in okeys:
328-
if '_' in k:
329-
x, label = k.split('_')
330-
no_of_buttons = no_of_buttons + 1
331-
complete = complete + self.options[k] + "*atype*"
332-
333-
newcomplete = complete.replace("\"", "*doubleq*")
334-
self.options['ctext'] = newcomplete
335-
self.options['no_of_buttons'] = no_of_buttons
336-
337-
if 'caption' not in self.options:
338-
self.options['caption'] = ''
339-
340-
if 'include' not in self.options:
341-
self.options['include'] = 'undefined'
342-
else:
343-
lst = self.options['include'].split(',')
344-
lst = [x.strip() for x in lst]
345-
self.options['include'] = lst
346-
347-
if 'hidecode' in self.options:
348-
self.options['hidecode'] = 'none'
349-
else:
350-
self.options['hidecode'] = 'block'
351-
352-
if 'language' not in self.options:
353-
self.options['language'] = 'python'
354-
355-
if 'nocodelens' in self.options or self.options['language'] != 'python':
356-
self.options['codelens'] = False
357-
else:
358-
self.options['codelens'] = True
359-
360-
if 'timelimit' not in self.options:
361-
self.options['timelimit'] = ''
362153

363154
return [ActivcodeNode(self.options)]
364155

365156

366-
class ActiveExercise(ActiveCode):
367-
required_arguments = 1
368-
optional_arguments = 0
369-
has_content = True
370-
371-
def run(self):
372-
self.options['hidecode'] = True
373-
self.options['gradebutton'] = True
374-
self.options['coach'] = True
375-
return super(ActiveExercise, self).run()
376-
377-
378157
if __name__ == '__main__':
379158
a = ActiveCode()

0 commit comments

Comments
 (0)