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

Commit 3a6ebad

Browse files
committed
Merge pull request #23 from RunestoneInteractive/master
getting latest
2 parents 38a41eb + 344030c commit 3a6ebad

File tree

5 files changed

+624
-0
lines changed

5 files changed

+624
-0
lines changed

runestone/dragndrop/README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<h2>Drag n Drop</h2>
2+
3+
```html
4+
<ul data-component="dragndrop" id="dd1">
5+
<span data-component="question">The Question goes here.</span>
6+
<span data-component="feedback">This is feedback that is displayed when this is answered incorrectly.</span>
7+
8+
<li data-component="draggable" id="dd1_drag1">Drag to Answer A</li>
9+
<li data-component="dropzone" for="dd1_drag1">Answer A</li>
10+
11+
<li data-component="draggable" id="dd1_drag2">Drag to Answer B</li>
12+
<li data-component="dropzone" for="dd1_drag2">Answer B</li>
13+
14+
<li data-component="draggable" id="dd1_drag3">Drag to Answer C</li>
15+
<li data-component="dropzone" for="dd1_drag3">Answer C</li>
16+
17+
18+
</ul>
19+
```
20+
21+
Here the <code>ul</code> tag represents the entire Drag n Drop component to be rendered.
22+
After declaring the data-component, the author has the option to specify a question and feedback for incorrect answers.
23+
Each <code>li</code> pair of "draggable" and "dropzone" components represents a draggable element and its respective area to be dropped in. The order that these
24+
are declared doesn't matter, as the order is randomized on page load--the author just has to be sure the <code>id</code> and <code>for</code> attributes match.
25+
26+
Option spec:
27+
28+
<ul>
29+
<li><code>data-component="dragndrop"</code> Identifies this as a drag n drop component</li>
30+
<li><code>id</code> Must be unique in the document</li>
31+
<li><code>data-component="question"</code> Optional--Identifies a <code>span</code> that contains the question</li>
32+
<li><code>data-component="feedback"</code> Optional--Identifies a <code>span</code> that contains the feedback for incorrect answers</li>
33+
</ul>
34+
35+
Option spec for the <code>li</code> tags:
36+
37+
<ul>
38+
<li><code>data-component="draggable"</code> Identifies a draggable element that will be dropped into a dropzone block</li>
39+
<li><code>id</code> For the draggable elements--must be unique in the component
40+
<li><code>data-component="dropzone"</code> Identifies a dropzone component that will receive a draggable element</li>
41+
<li><code>for</code> For the dropzone components--identifies the correct draggable element (via <code>id</code>) that when dropped into this dropzone, will be registered as correct</li>
42+
</ul>

runestone/dragndrop/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .dragndrop import *
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
.draggable {
2+
margin-left: 2%;
3+
margin-top: 5px;
4+
display:inline-block;
5+
text-align: left;
6+
vertical-align: top;
7+
background-color: #efefff;
8+
font-family: monospace;
9+
font-size: 120%;
10+
padding-bottom: 10px;
11+
min-width: 48%;
12+
max-width: 48%;
13+
border: 1px solid #efefff;;
14+
box-sizing: border-box;
15+
}
16+
.drag-button {
17+
display: inline-block;
18+
}
19+
.drag-reset {
20+
background-color: #474949;
21+
color: white;
22+
}
23+
.drag-reset:hover {
24+
background-color: black;
25+
color: white;
26+
}
27+
.drag-reset:enabled {
28+
background-color: #474949;
29+
color: white;
30+
}
31+
.draggable-drag {
32+
-moz-border-radius:10px;
33+
-webkit-border-radius:10px;
34+
border-radius: 10px;
35+
display: block;
36+
background-color:#EFEFEF;
37+
border:1px solid lightgray;
38+
padding:10px;
39+
margin-top: 5px;
40+
cursor: move;
41+
}
42+
43+
.draggable-feedback {
44+
text-align: left !important;
45+
}
46+
47+
.draggable-drop {
48+
-moz-border-radius:10px;
49+
-webkit-border-radius:10px;
50+
border-radius: 10px;
51+
display: block;
52+
background-color:#DDDDDD;
53+
border:1px solid lightgray;
54+
padding:10px;
55+
margin-top: 5px;
56+
}
57+
.draggable-container {
58+
text-align:center;
59+
}
60+
61+
.possibleDrop {
62+
border-color: #000000;
63+
background-color: #CCCCCC;
64+
}

runestone/dragndrop/dragndrop.py

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Copyright (C) 2011 Bradley N. Miller
2+
#
3+
# This program is free software: you can redistribute it and/or modify
4+
# it under the terms of the GNU General Public License as published by
5+
# the Free Software Foundation, either version 3 of the License, or
6+
# (at your option) any later version.
7+
#
8+
# This program is distributed in the hope that it will be useful,
9+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
# GNU General Public License for more details.
12+
#
13+
# You should have received a copy of the GNU General Public License
14+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
#
16+
17+
__author__ = 'isaiahmayerchak'
18+
19+
from docutils import nodes
20+
from docutils.parsers.rst import directives
21+
from docutils.parsers.rst import Directive
22+
23+
def setup(app):
24+
app.add_directive('dragndrop',DragNDrop)
25+
app.add_javascript('dragndrop.js')
26+
app.add_stylesheet('dragndrop.css')
27+
28+
app.add_node(DragNDropNode, html=(visit_dnd_node, depart_dnd_node))
29+
30+
31+
TEMPLATE_START = """<ul data-component="dragndrop" id="%(divid)s">
32+
<span data-component="question">%(question)s</span>
33+
%(feedback)s
34+
"""
35+
36+
TEMPLATE_OPTION = """
37+
<li data-component="draggable" id="%(divid)s_drag%(dnd_label)s">%(dragText)s</li>
38+
<li data-component="dropzone" for="%(divid)s_drag%(dnd_label)s">%(dropText)s</li>
39+
"""
40+
TEMPLATE_END = """</ul>"""
41+
42+
43+
class DragNDropNode(nodes.General, nodes.Element):
44+
def __init__(self,content):
45+
"""
46+
Arguments:
47+
- `self`:
48+
- `content`:
49+
"""
50+
super(DragNDropNode,self).__init__()
51+
self.dnd_options = content
52+
53+
# self for these functions is an instance of the writer class. For example
54+
# in html, self is sphinx.writers.html.SmartyPantsHTMLTranslator
55+
# The node that is passed as a parameter is an instance of our node class.
56+
def visit_dnd_node(self,node):
57+
res = TEMPLATE_START
58+
59+
if "feedback" in node.dnd_options:
60+
node.dnd_options["feedback"] = "<span data-component=feedback>" + node.dnd_options["feedback"] + "</span>"
61+
else:
62+
node.dnd_options["feedback"] = ""
63+
64+
res = res % node.dnd_options
65+
66+
self.body.append(res)
67+
68+
def depart_dnd_node(self,node):
69+
res = ""
70+
# Add all of the possible answers
71+
okeys = list(node.dnd_options.keys())
72+
okeys.sort()
73+
print(okeys)
74+
for k in okeys:
75+
if 'match' in k:
76+
x,label = k.split('_')
77+
node.dnd_options['dnd_label'] = label
78+
dragE, dropE = node.dnd_options[k].split("|||")
79+
node.dnd_options["dragText"] = dragE
80+
node.dnd_options['dropText'] = dropE
81+
res += node.template_option % node.dnd_options
82+
res += node.template_end % node.dnd_options
83+
self.body.append(res)
84+
85+
86+
class DragNDrop(Directive):
87+
required_arguments = 1
88+
optional_arguments = 0
89+
has_content = True
90+
option_spec = {"feedback":directives.unchanged,
91+
"match_1":directives.unchanged,
92+
"match_2":directives.unchanged,
93+
"match_3":directives.unchanged,
94+
"match_4":directives.unchanged,
95+
"match_5":directives.unchanged,
96+
"match_6":directives.unchanged,
97+
"match_7":directives.unchanged,
98+
"match_8":directives.unchanged,
99+
"match_9":directives.unchanged,
100+
"match_10":directives.unchanged,
101+
"match_11":directives.unchanged,
102+
"match_12":directives.unchanged,
103+
"match_13":directives.unchanged,
104+
"match_14":directives.unchanged,
105+
"match_15":directives.unchanged,
106+
"match_16":directives.unchanged,
107+
"match_17":directives.unchanged,
108+
"match_18":directives.unchanged,
109+
"match_19":directives.unchanged,
110+
"match_20":directives.unchanged,
111+
112+
}
113+
114+
def run(self):
115+
"""
116+
process the multiplechoice directive and generate html for output.
117+
:param self:
118+
:return:
119+
.. dragndrop:: identifier
120+
:feedback: Feedback that is displayed if things are incorrectly matched--is optional
121+
:match_1: Draggable element text|||Dropzone to be matched with text
122+
:match_2: Drag to Answer B|||Answer B
123+
:match_3: Draggable text|||Text of dropzone
124+
...etc...(up to 20 matches)
125+
126+
The question goes here.
127+
"""
128+
self.options['divid'] = self.arguments[0]
129+
130+
if self.content:
131+
source = "\n".join(self.content)
132+
else:
133+
source = '\n'
134+
135+
self.options['question'] = source
136+
137+
138+
dndNode = DragNDropNode(self.options)
139+
dndNode.template_start = TEMPLATE_START
140+
dndNode.template_option = TEMPLATE_OPTION
141+
dndNode.template_end = TEMPLATE_END
142+
143+
return [dndNode]

0 commit comments

Comments
 (0)