Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
fd6abc88
Commit
fd6abc88
authored
Jul 08, 2013
by
Julian Arni
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Incorporate review comments
parent
7fbd1a72
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
112 additions
and
134 deletions
+112
-134
common/lib/capa/capa/inputtypes.py
+1
-1
common/static/js/capa/spec/jsinput/jsinput.js
+30
-31
common/static/js/capa/spec/jsinput/mainfixture.html
+40
-25
common/static/js/capa/src/jsinput.js
+41
-77
No files found.
common/lib/capa/capa/inputtypes.py
View file @
fd6abc88
...
@@ -504,7 +504,7 @@ class JSInput(InputTypeBase):
...
@@ -504,7 +504,7 @@ class JSInput(InputTypeBase):
def
_extra_context
(
self
):
def
_extra_context
(
self
):
context
=
{
context
=
{
'applet_loader'
:
'/static/js/capa/jsinput.js'
,
'applet_loader'
:
'/static/js/capa/
src/
jsinput.js'
,
'saved_state'
:
self
.
value
'saved_state'
:
self
.
value
}
}
...
...
common/static/js/capa/spec/jsinput/jsinput.js
View file @
fd6abc88
...
@@ -11,38 +11,15 @@ describe("A jsinput has:", function () {
...
@@ -11,38 +11,15 @@ describe("A jsinput has:", function () {
});
});
});
});
describe
(
"The ctxCall function"
,
function
()
{
it
(
"Evaluatates nested-object functions"
,
function
()
{
var
ctxTest
=
{
ctxFn
:
function
()
{
return
this
.
name
;
}
};
var
fnString
=
"nest.ctxFn"
;
var
holder
=
{};
holder
.
nest
=
ctxTest
;
var
fn
=
_ctxCall
(
holder
,
fnString
);
expect
(
fnString
).
toBe
(
holder
.
nest
.
ctxFn
());
});
it
(
"Throws an exception when the object does not exits"
,
function
()
{
var
notObj
=
_ctxCall
(
"twas"
,
"brilling"
);
expect
(
notObj
).
toThrow
();
});
it
(
"Throws an exception when the function does not exist"
,
function
()
{
var
anobj
=
{};
var
notFn
=
_ctxCall
(
"anobj"
,
"brillig"
);
expect
(
notFn
).
toThrow
();
});
describe
(
"The jsinput constructor"
,
function
(){
})
;
var
iframe1
=
$
(
document
).
find
(
'iframe'
)[
0
]
;
describe
(
"The jsinput constructor"
,
function
(){
var
testJsElem
=
jsinputConstructor
({
var
testJsElem
=
jsinputConstructor
({
id
:
378
1
,
id
:
1
,
elem
:
"<div id='abc'> a div </div>"
,
elem
:
iframe1
,
passive
:
false
passive
:
false
});
});
...
@@ -51,7 +28,7 @@ describe("A jsinput has:", function () {
...
@@ -51,7 +28,7 @@ describe("A jsinput has:", function () {
});
});
it
(
"Adds the object to the jsinput array"
,
function
()
{
it
(
"Adds the object to the jsinput array"
,
function
()
{
expect
(
jsinput
.
jsinputarr
.
exists
(
378
1
)).
toBe
(
true
);
expect
(
jsinput
.
exists
(
1
)).
toBe
(
true
);
});
});
describe
(
"The returned object"
,
function
()
{
describe
(
"The returned object"
,
function
()
{
...
@@ -60,12 +37,34 @@ describe("A jsinput has:", function () {
...
@@ -60,12 +37,34 @@ describe("A jsinput has:", function () {
expect
(
testJsElem
.
update
).
toBeDefined
();
expect
(
testJsElem
.
update
).
toBeDefined
();
});
});
it
(
"Returns an 'update' that is idempotent"
,
function
(){
var
orig
=
testJsElem
.
update
();
for
(
var
i
=
0
;
i
++
;
i
<
5
)
{
expect
(
testJsElem
.
update
()).
toEqual
(
orig
);
}
});
it
(
"Changes the parent's inputfield"
,
function
()
{
it
(
"Changes the parent's inputfield"
,
function
()
{
testJsElem
.
update
();
});
});
});
})
describe
(
"The walkDOM functions"
,
function
()
{
walkDOM
();
it
(
"Creates (at least) one object per iframe"
,
function
()
{
jsinput
.
arr
.
length
>=
2
;
});
});
it
(
"Does not create multiple objects with the same id"
,
function
()
{
while
(
jsinput
.
arr
.
length
>
0
)
{
var
elem
=
jsinput
.
arr
.
pop
();
expect
(
jsinput
.
exists
(
elem
.
id
)).
toBe
(
false
);
}
});
});
});
}
})
)
common/static/js/capa/spec/jsinput/mainfixture.html
View file @
fd6abc88
...
@@ -2,32 +2,45 @@
...
@@ -2,32 +2,45 @@
<head>
<head>
<title>
JSinput jasmine test
</title>
<title>
JSinput jasmine test
</title>
</head>
</head>
<body>
<body>
<section
id=
"inputtype_1"
data=
"gradefn"
class=
"jsinput"
>
<section
id=
"inputtype_1"
data=
"gradefn"
data-setstate=
"setinput"
class=
"jsinput"
>
<div
class=
"script_placeholder"
data-src=
"${applet_loader}"
/>
<div
class=
"script_placeholder"
/>
<iframe
name=
"iframe_1"
<iframe
name=
"iframe_1"
sandbox=
"allow-scripts allow-popups allow-same-origin allow-forms allow-pointer-lock"
sandbox=
"allow-scripts
allow-popups
allow-same-origin
allow-forms
allow-pointer-lock"
seamless=
"seamless"
seamless=
"seamless"
height=
"500"
height=
"500"
width=
"500"
>
width=
"500"
>
<html>
<html>
<head>
<head>
<title>
<title>
JS input test
JS input test 1
</title>
</title>
<script
type=
"text/javascript"
>
<script
type=
"text/javascript"
>
function
gradefn
()
{
function
gradefn
()
{
var
ans
=
document
.
getElementById
(
"one"
).
value
;
var
ans
=
document
.
getElementById
(
"one"
).
value
;
console
.
log
(
"I've been called!"
);
console
.
log
(
"I've been called!"
);
return
ans
return
ans
}
}
function
setinput
(
val
)
{
document
.
getElementById
(
"one"
).
value
(
val
);
return
;
}
</script>
</script>
</head>
</head>
<body>
<body>
<p>
Simple js input test. Defines a js function that returns the value in the
<p>
Simple js input test. Defines a js function that returns the value in
input field below when called.
</p>
the
input field below when called.
</p>
<form>
<form>
<input
id=
'one'
type=
"TEXT"
/>
<input
id=
'one'
type=
"TEXT"
/>
...
@@ -47,15 +60,18 @@
...
@@ -47,15 +60,18 @@
</p>
</p>
<br/>
<br/>
<br/>
<br/>
<div
class=
"error_message"
style=
"padding: 5px 5px 5px 5px; background-color:#FA6666; height:60px;width:400px; display: none"
></div>
<div
class=
"error_message"
></div>
</div>
</section>
</section>
<section
id=
"inputtype_2"
data=
"gradefn"
class=
"jsinput"
>
<section
id=
"inputtype_2"
data=
"gradefn"
class=
"jsinput"
>
<div
class=
"script_placeholder"
data-src=
"${applet_loader}"
/>
<div
class=
"script_placeholder"
/>
<iframe
name=
"iframe_2"
<iframe
name=
"iframe_2"
sandbox=
"allow-scripts allow-popups allow-same-origin allow-forms allow-pointer-lock"
sandbox=
"allow-scripts
allow-popups
allow-same-origin
allow-forms
allow-pointer-lock"
seamless=
"seamless"
seamless=
"seamless"
height=
"500"
height=
"500"
width=
"500"
>
width=
"500"
>
...
@@ -65,20 +81,20 @@
...
@@ -65,20 +81,20 @@
JS input test
JS input test
</title>
</title>
<script
type=
"text/javascript"
>
<script
type=
"text/javascript"
>
function
gradefn
()
{
function
gradefn
()
{
var
ans
=
document
.
getElementById
(
"one"
).
value
;
var
ans
=
document
.
getElementById
(
"one"
).
value
;
console
.
log
(
"I've been called!"
);
console
.
log
(
"I've been called!"
);
return
ans
return
ans
}
}
</script>
</script>
</head>
</head>
<body>
<body>
<p>
Simple js input test. Defines a js function that returns the value in the
<p>
Simple js input test. Defines a js function that returns the value in
input field below when called.
</p>
the
input field below when called.
</p>
<form>
<form>
<input
id=
'one
'
type=
"TEXT"
/>
<input
id=
'two
'
type=
"TEXT"
/>
</form>
</form>
</body>
</body>
...
@@ -95,9 +111,8 @@
...
@@ -95,9 +111,8 @@
</p>
</p>
<br/>
<br/>
<br/>
<br/>
<div
class=
"error_message"
style=
"padding: 5px 5px 5px 5px; background-color:#FA6666; height:60px;width:400px; display: non
e"
></div>
<div
class=
"error_messag
e"
></div>
</div>
</section>
</section>
</body>
</body>
</html>
</html>
common/static/js/capa/jsinput.js
→
common/static/js/capa/
src/
jsinput.js
View file @
fd6abc88
...
@@ -12,7 +12,6 @@
...
@@ -12,7 +12,6 @@
// submitted), the constructor is called again.
// submitted), the constructor is called again.
if
(
!
jsinput
)
{
if
(
!
jsinput
)
{
console
.
log
(
"hi"
);
jsinput
=
{
jsinput
=
{
runs
:
1
,
runs
:
1
,
arr
:
[],
arr
:
[],
...
@@ -27,29 +26,9 @@
...
@@ -27,29 +26,9 @@
jsinput
.
runs
++
;
jsinput
.
runs
++
;
if
(
$
(
document
).
find
(
'section[class="jsinput"]'
).
length
>
jsinput
.
runs
)
{
return
;
}
/* Utils */
/* Utils */
jsinput
.
_DEBUG
=
jsinput
.
_DEBUG
||
true
;
var
debuglog
=
function
(
text
)
{
if
(
jsinput
.
_DEBUG
)
{
console
.
log
(
text
);}};
var
eqTimeout
=
function
(
fn
,
pred
,
time
,
max
)
{
var
i
=
0
;
while
(
pred
(
fn
)
&&
i
<
max
)
{
setTimeout
(
fn
,
time
);
}
return
fn
;
};
var
isUndef
=
function
(
e
)
{
return
(
typeof
(
e
)
===
'undefined'
);
};
// Take a string and find the nested object that corresponds to it. E.g.:
// Take a string and find the nested object that corresponds to it. E.g.:
// deepKey(obj, "an.example") -> obj["an"]["example"]
// deepKey(obj, "an.example") -> obj["an"]["example"]
var
_deepKey
=
function
(
obj
,
path
){
var
_deepKey
=
function
(
obj
,
path
){
...
@@ -76,65 +55,51 @@
...
@@ -76,65 +55,51 @@
/* Private methods */
/* Private methods */
var
sect
=
$
(
spec
.
elem
).
parent
().
find
(
'section[class="jsinput"]'
);
var
sect
=
$
(
spec
.
elem
).
parent
().
find
(
'section[class="jsinput"]'
);
var
sect
a
ttr
=
function
(
e
)
{
return
$
(
sect
).
attr
(
e
);
};
var
sect
A
ttr
=
function
(
e
)
{
return
$
(
sect
).
attr
(
e
);
};
var
thisIFrame
=
$
(
spec
.
elem
).
var
thisIFrame
=
$
(
spec
.
elem
).
find
(
'iframe[name^="iframe_"]'
).
find
(
'iframe[name^="iframe_"]'
).
get
(
0
);
get
(
0
);
var
cWindow
=
thisIFrame
.
contentWindow
;
var
cWindow
=
thisIFrame
.
contentWindow
;
// Get the hidden input field to pass to customresponse
// Get the hidden input field to pass to customresponse
function
_input
f
ield
()
{
function
_input
F
ield
()
{
var
parent
=
$
(
spec
.
elem
).
parent
();
var
parent
=
$
(
spec
.
elem
).
parent
();
return
parent
.
find
(
'input[id^="input_"]'
);
return
parent
.
find
(
'input[id^="input_"]'
);
}
}
var
input
field
=
_inputf
ield
();
var
input
Field
=
_inputF
ield
();
// Get the grade function name
// Get the grade function name
var
get
gradefn
=
secta
ttr
(
"data"
);
var
get
GradeFn
=
sectA
ttr
(
"data"
);
// Get state getter
// Get state getter
var
get
getstate
=
secta
ttr
(
"data-getstate"
);
var
get
StateGetter
=
sectA
ttr
(
"data-getstate"
);
// Get state setter
// Get state setter
var
get
setstate
=
secta
ttr
(
"data-setstate"
);
var
get
StateSetter
=
sectA
ttr
(
"data-setstate"
);
// Get stored state
// Get stored state
var
getstoredstate
=
sectattr
(
"data-stored"
);
var
getStoredState
=
sectAttr
(
"data-stored"
);
// Put the return value of gradefn in the hidden inputfield.
// If passed an argument, does not call gradefn, and instead directly
// updates the inputfield with the passed value.
var
update
=
function
(
answer
)
{
// Put the return value of gradeFn in the hidden inputField.
var
update
=
function
()
{
var
ans
;
var
ans
;
ans
=
_deepKey
(
cWindow
,
gradefn
);
ans
=
_deepKey
(
cWindow
,
gradeFn
)();
// setstate presumes getstate, so don't getstate unless setstate is
// setstate presumes getstate, so don't getstate unless setstate is
// defined.
// defined.
if
(
get
getstate
&&
getsetstate
)
{
if
(
get
StateGetter
&&
getStateSetter
)
{
var
state
,
store
;
var
state
,
store
;
state
=
_deepKey
(
cWindow
,
getgetstate
);
state
=
unescape
(
_deepKey
(
cWindow
,
getStateGetter
)()
);
store
=
{
store
=
{
answer
:
ans
,
answer
:
ans
,
state
:
state
state
:
state
};
};
inputField
.
val
(
JSON
.
stringify
(
store
));
debuglog
(
"Store: "
+
store
);
inputfield
.
val
(
JSON
.
stringify
(
store
));
}
else
{
}
else
{
inputfield
.
val
(
ans
);
inputField
.
val
(
ans
);
debuglog
(
"Answer: "
+
ans
);
}
}
return
;
return
;
};
};
// Find the update button, and bind the update function to its click
// event.
function
bindUpdate
()
{
var
updatebutton
=
$
(
spec
.
elem
).
find
(
'button[class="update"]'
).
get
(
0
);
$
(
updatebutton
).
click
(
update
);
}
/* Public methods */
/* Public methods */
that
.
update
=
update
;
that
.
update
=
update
;
...
@@ -145,53 +110,53 @@
...
@@ -145,53 +110,53 @@
jsinput
.
arr
.
push
(
that
);
jsinput
.
arr
.
push
(
that
);
// Put the update function as the value of the input
f
ield's "waitfor"
// Put the update function as the value of the input
F
ield's "waitfor"
// attribute so that it is called when the check button is clicked.
// attribute so that it is called when the check button is clicked.
function
bindCheck
()
{
function
bindCheck
()
{
debuglog
(
"Update function: "
+
that
.
update
);
inputField
.
data
(
'waitfor'
,
that
.
update
);
inputfield
.
data
(
'waitfor'
,
that
.
update
);
return
;
return
;
}
}
var
gradefn
=
getgradefn
;
var
gradeFn
=
getGradeFn
;
debuglog
(
"Gradefn: "
+
gradefn
);
if
(
spec
.
passive
===
false
)
{
// If there is a separate "Update" button, bind update to it.
bindUpdate
();
}
else
{
// Otherwise, bind update to the check button.
bindCheck
();
}
bindCheck
();
bindCheck
();
// Check whether application takes in state and there is a saved
// Check whether application takes in state and there is a saved
// state to give it. If get
setstate
is specified but calling it
// state to give it. If get
StateSetter
is specified but calling it
// fails, wait and try again, since the iframe might still be
// fails, wait and try again, since the iframe might still be
// loading.
// loading.
if
(
getsetstate
&&
getstoredstate
)
{
if
(
getStateSetter
&&
getStoredState
)
{
var
sval
;
var
sval
,
jsonVal
;
if
(
typeof
(
getstoredstate
)
===
"object"
)
{
sval
=
getstoredstate
[
"state"
];
try
{
jsonVal
=
JSON
.
parse
(
getStoredState
);
}
catch
(
err
)
{
jsonVal
=
getStoredState
;
}
if
(
typeof
(
jsonVal
)
===
"object"
)
{
sval
=
jsonVal
[
"state"
];
}
else
{
}
else
{
sval
=
getstoredstate
;
sval
=
jsonVal
;
}
}
debuglog
(
"Stored state: "
+
sval
);
debuglog
(
"Set_statefn: "
+
getsetstate
);
// Try calling setstate every 200ms while it throws an exception,
// up to five times; give up after that.
// (Functions in the iframe may not be ready when we first try
// calling it, but might just need more time. Give the functions
// more time.)
function
whileloop
(
n
)
{
function
whileloop
(
n
)
{
if
(
n
<
10
){
if
(
n
<
5
){
try
{
try
{
_deepKey
(
cWindow
,
get
setstate
)(
sval
);
_deepKey
(
cWindow
,
get
StateSetter
)(
sval
);
}
catch
(
err
)
{
}
catch
(
err
)
{
setTimeout
(
whileloop
(
n
+
1
),
200
);
setTimeout
(
whileloop
(
n
+
1
),
200
);
}
}
}
}
else
{
else
{
debuglog
(
"Error: could not set state"
);
console
.
debug
(
"Error: could not set state"
);
_deepKey
(
cWindow
,
getsetstate
)(
sval
);
}
}
}
}
whileloop
(
0
);
whileloop
(
0
);
...
@@ -218,7 +183,6 @@
...
@@ -218,7 +183,6 @@
var
newJsElem
=
jsinputConstructor
({
var
newJsElem
=
jsinputConstructor
({
id
:
newid
,
id
:
newid
,
elem
:
value
,
elem
:
value
,
passive
:
true
});
});
}
}
});
});
...
@@ -227,9 +191,9 @@
...
@@ -227,9 +191,9 @@
// This is ugly, but without a timeout pages with multiple/heavy jsinputs
// This is ugly, but without a timeout pages with multiple/heavy jsinputs
// don't load properly.
// don't load properly.
if
(
$
.
isReady
)
{
if
(
$
.
isReady
)
{
setTimeout
(
walkDOM
,
10
00
);
setTimeout
(
walkDOM
,
3
00
);
}
else
{
}
else
{
$
(
document
).
ready
(
setTimeout
(
walkDOM
,
10
00
));
$
(
document
).
ready
(
setTimeout
(
walkDOM
,
3
00
));
}
}
})(
window
.
jsinput
=
window
.
jsinput
||
false
);
})(
window
.
jsinput
=
window
.
jsinput
||
false
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment