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
70518a46
Commit
70518a46
authored
Dec 05, 2013
by
polesye
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
BLD-506: Update behavior of start/end time fields.
parent
bc625ab5
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
155 additions
and
55 deletions
+155
-55
CHANGELOG.rst
+2
-0
cms/djangoapps/contentstore/features/transcripts.py
+12
-2
cms/static/coffee/spec/main.coffee
+0
-5
cms/static/coffee/spec/views/metadata_edit_spec.coffee
+87
-0
cms/static/js/views/metadata.js
+52
-33
cms/static/js_test.yml
+0
-1
cms/templates/base.html
+0
-5
common/lib/xmodule/xmodule/video_module.py
+2
-2
common/static/js/vendor/jquery.maskedinput.min.js
+0
-7
No files found.
CHANGELOG.rst
View file @
70518a46
...
...
@@ -5,6 +5,8 @@ These are notable changes in edx-platform. This is a rolling list of changes,
in roughly chronological order, most recent first. Add your entries at or near
the top. Include a label indicating the component affected.
Blades: Update behavior of start/end time fields. BLD-506.
Blades: Make LTI module not send grade_back_url if has_score=False. BLD-561.
Blades: Show answer for imageresponse. BLD-21.
...
...
cms/djangoapps/contentstore/features/transcripts.py
View file @
70518a46
...
...
@@ -230,8 +230,18 @@ def open_tab(_step, tab_name):
@step
(
'I set value "([^"]*)" to the field "([^"]*)"$'
)
def
set_value_transcripts_field
(
_step
,
value
,
field_name
):
field_id
=
'#'
+
world
.
browser
.
find_by_xpath
(
'//label[text()="
%
s"]'
%
field_name
.
strip
())[
0
][
'for'
]
world
.
css_fill
(
field_id
,
value
.
strip
())
XPATH
=
'//label[text()="{name}"]'
.
format
(
name
=
field_name
)
SELECTOR
=
'#'
+
world
.
browser
.
find_by_xpath
(
XPATH
)[
0
][
'for'
]
element
=
world
.
css_find
(
SELECTOR
)
.
first
if
element
[
'type'
]
==
'text'
:
SCRIPT
=
'$("{selector}").val("{value}").change()'
.
format
(
selector
=
SELECTOR
,
value
=
value
)
world
.
browser
.
execute_script
(
SCRIPT
)
assert
world
.
css_has_value
(
SELECTOR
,
value
)
else
:
assert
False
,
'Incorrect element type.'
;
world
.
wait_for_ajax_complete
()
...
...
cms/static/coffee/spec/main.coffee
View file @
70518a46
...
...
@@ -18,7 +18,6 @@ requirejs.config({
"jquery.iframe-transport"
:
"xmodule_js/common_static/js/vendor/jQuery-File-Upload/js/jquery.iframe-transport"
,
"jquery.inputnumber"
:
"xmodule_js/common_static/js/vendor/html5-input-polyfills/number-polyfill"
,
"jquery.immediateDescendents"
:
"xmodule_js/common_static/coffee/src/jquery.immediateDescendents"
,
"jquery.maskedinput"
:
"xmodule_js/common_static/js/vendor/jquery.maskedinput.min"
,
"datepair"
:
"xmodule_js/common_static/js/vendor/timepicker/datepair"
,
"date"
:
"xmodule_js/common_static/js/vendor/date"
,
"underscore"
:
"xmodule_js/common_static/js/vendor/underscore-min"
,
...
...
@@ -98,10 +97,6 @@ requirejs.config({
deps
:
[
"jquery"
],
exports
:
"jQuery.fn.inputNumber"
},
"jquery.maskedinput"
:
{
deps
:
[
"jquery"
],
exports
:
"jQuery.fn.mask"
},
"jquery.tinymce"
:
{
deps
:
[
"jquery"
,
"tinymce"
],
exports
:
"jQuery.fn.tinymce"
...
...
cms/static/coffee/spec/views/metadata_edit_spec.coffee
View file @
70518a46
...
...
@@ -391,8 +391,95 @@ define ["js/models/metadata", "js/collections/metadata", "js/views/metadata", "c
it
"returns the intial value upon initialization"
,
->
assertValueInView
(
@
view
,
'12:12:12'
)
it
"value is converted correctly"
,
->
view
=
@
view
cases
=
[
{
input
:
'23:100:0'
output
:
'23:59:59'
},
{
input
:
'100000000000000000'
output
:
'23:59:59'
},
{
input
:
'80000'
output
:
'22:13:20'
},
{
input
:
'-100'
output
:
'00:00:00'
},
{
input
:
'-100:-10'
output
:
'00:00:00'
},
{
input
:
'99:99'
output
:
'01:40:39'
},
{
input
:
'2'
output
:
'00:00:02'
},
{
input
:
'1:2'
output
:
'00:01:02'
},
{
input
:
'1:25'
output
:
'00:01:25'
},
{
input
:
'3:1:25'
output
:
'03:01:25'
},
{
input
:
' 2 3 : 5 9 : 5 9 '
output
:
'23:59:59'
},
{
input
:
'9:1:25'
output
:
'09:01:25'
},
{
input
:
'77:72:77'
output
:
'23:59:59'
},
{
input
:
'22:100:100'
output
:
'23:41:40'
},
# negative value
{
input
:
'-22:22:22'
output
:
'00:22:22'
},
# simple string
{
input
:
'simple text'
output
:
'00:00:00'
},
{
input
:
'a10a:a10a:a10a'
output
:
'00:00:00'
},
# empty string
{
input
:
''
output
:
'00:00:00'
}
]
$
.
each
cases
,
(
index
,
data
)
->
expect
(
view
.
parseRelativeTime
(
data
.
input
)).
toBe
(
data
.
output
)
it
"can update its value in the view"
,
->
assertCanUpdateView
(
@
view
,
"23:59:59"
)
@
view
.
setValueInEditor
(
"33:59:59"
)
@
view
.
updateModel
()
assertValueInView
(
@
view
,
"23:59:59"
)
it
"has a clear method to revert to the model default"
,
->
assertClear
(
@
view
,
'00:00:00'
)
...
...
cms/static/js/views/metadata.js
View file @
70518a46
define
(
[
"backbone"
,
"underscore"
,
"js/models/metadata"
,
"js/views/abstract_editor"
,
"js/views/transcripts/metadata_videolist"
,
"jquery.maskedinput"
"js/views/transcripts/metadata_videolist"
],
function
(
Backbone
,
_
,
MetadataModel
,
AbstractEditor
,
VideoList
)
{
var
Metadata
=
{};
...
...
@@ -301,6 +301,11 @@ function(Backbone, _, MetadataModel, AbstractEditor, VideoList) {
Metadata
.
RelativeTime
=
AbstractEditor
.
extend
({
defaultValue
:
'00:00:00'
,
// By default max value of RelativeTime field on Backend is 23:59:59,
// that is 86399 seconds.
maxTimeInSeconds
:
86399
,
events
:
{
"change input"
:
"updateModel"
,
"keypress .setting-input"
:
"showClearButton"
,
...
...
@@ -309,46 +314,60 @@ function(Backbone, _, MetadataModel, AbstractEditor, VideoList) {
templateName
:
"metadata-string-entry"
,
initialize
:
function
()
{
AbstractEditor
.
prototype
.
initialize
.
apply
(
this
);
// This list of definitions is used for creating appropriate
// time format mask;
//
// For example, mask 'hH:mM:sS':
// min value: 00:00:00
// max value: 23:59:59
//
// With this mask user cannot set following values:
// 93:23:23, 23:60:60, 77:77:77, etc.
var
definitions
=
{
h
:
'[0-2]'
,
H
:
'[0-3]'
,
m
:
'[0-5]'
,
s
:
'[0-5]'
,
M
:
'[0-9]'
,
S
:
'[0-9]'
};
$
.
each
(
definitions
,
function
(
key
,
value
)
{
$
.
mask
.
definitions
[
key
]
=
value
;
});
getValueFromEditor
:
function
()
{
var
$input
=
this
.
$el
.
find
(
'#'
+
this
.
uniqueId
);
this
.
$el
.
find
(
'#'
+
this
.
uniqueId
)
.
mask
(
'hH:mM:sS'
,
{
placeholder
:
'0'
});
return
$input
.
val
();
},
getValueFromEditor
:
function
()
{
var
$input
=
this
.
$el
.
find
(
'#'
+
this
.
uniqueId
),
value
=
$input
.
val
();
updateModel
:
function
()
{
var
value
=
this
.
getValueFromEditor
(),
time
=
this
.
parseRelativeTime
(
value
);
this
.
model
.
setValue
(
time
);
// Sometimes, `parseRelativeTime` method returns the same value for
// the different inputs. In this case, model will not be
// updated (it already has the same value) and we should
// call `render` method manually.
// Examples:
// value => 23:59:59; parseRelativeTime => 23:59:59
// value => 44:59:59; parseRelativeTime => 23:59:59
if
(
value
!==
time
&&
!
this
.
model
.
hasChanged
(
'value'
))
{
this
.
render
();
}
},
return
value
;
parseRelativeTime
:
function
(
value
)
{
// This function ensure you have two-digits
var
pad
=
function
(
number
)
{
return
(
number
<
10
)
?
"0"
+
number
:
number
;
},
// Removes all white-spaces and splits by `:`.
list
=
value
.
replace
(
/
\s
+/g
,
''
).
split
(
':'
),
seconds
,
date
;
list
=
_
.
map
(
list
,
function
(
num
)
{
return
Math
.
max
(
0
,
parseInt
(
num
,
10
)
||
0
);
}).
reverse
();
seconds
=
_
.
reduce
(
list
,
function
(
memo
,
num
,
index
)
{
return
memo
+
num
*
Math
.
pow
(
60
,
index
);
},
0
);
// multiply by 1000 because Date() requires milliseconds
date
=
new
Date
(
Math
.
min
(
seconds
,
this
.
maxTimeInSeconds
)
*
1000
);
return
[
pad
(
date
.
getUTCHours
()),
pad
(
date
.
getUTCMinutes
()),
pad
(
date
.
getUTCSeconds
())
].
join
(
':'
);
},
setValueInEditor
:
function
(
value
)
{
if
(
!
value
)
{
value
=
'00:00:00'
;
value
=
this
.
defaultValue
;
}
this
.
$el
.
find
(
'input'
).
val
(
value
);
...
...
cms/static/js_test.yml
View file @
70518a46
...
...
@@ -49,7 +49,6 @@ lib_paths:
-
xmodule_js/common_static/js/vendor/jasmine-stealth.js
-
xmodule_js/common_static/js/vendor/jasmine-imagediff.js
-
xmodule_js/common_static/js/vendor/jasmine.async.js
-
xmodule_js/common_static/js/vendor/jquery.maskedinput.min.js
-
xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js
-
xmodule_js/src/xmodule.js
-
xmodule_js/common_static/js/test/i18n.js
...
...
cms/templates/base.html
View file @
70518a46
...
...
@@ -58,7 +58,6 @@
"jquery.qtip"
:
"js/vendor/jquery.qtip.min"
,
"jquery.scrollTo"
:
"js/vendor/jquery.scrollTo-1.4.2-min"
,
"jquery.flot"
:
"js/vendor/flot/jquery.flot.min"
,
"jquery.maskedinput"
:
"js/vendor/jquery.maskedinput.min"
,
"jquery.fileupload"
:
"js/vendor/jQuery-File-Upload/js/jquery.fileupload"
,
"jquery.iframe-transport"
:
"js/vendor/jQuery-File-Upload/js/jquery.iframe-transport"
,
"jquery.inputnumber"
:
"js/vendor/html5-input-polyfills/number-polyfill"
,
...
...
@@ -138,10 +137,6 @@
deps
:
[
"jquery"
],
exports
:
"jQuery.fn.plot"
},
"jquery.maskedinput"
:
{
deps
:
[
"jquery"
],
exports
:
"jQuery.fn.mask"
},
"jquery.fileupload"
:
{
deps
:
[
"jquery.iframe-transport"
],
exports
:
"jQuery.fn.fileupload"
...
...
common/lib/xmodule/xmodule/video_module.py
View file @
70518a46
...
...
@@ -81,13 +81,13 @@ class VideoFields(object):
default
=
""
)
start_time
=
RelativeTime
(
# datetime.timedelta object
help
=
"Start time for the video (HH:MM:SS)."
,
help
=
"Start time for the video (HH:MM:SS).
Max value is 23:59:59.
"
,
display_name
=
"Start Time"
,
scope
=
Scope
.
settings
,
default
=
datetime
.
timedelta
(
seconds
=
0
)
)
end_time
=
RelativeTime
(
# datetime.timedelta object
help
=
"End time for the video (HH:MM:SS)."
,
help
=
"End time for the video (HH:MM:SS).
Max value is 23:59:59.
"
,
display_name
=
"End Time"
,
scope
=
Scope
.
settings
,
default
=
datetime
.
timedelta
(
seconds
=
0
)
...
...
common/static/js/vendor/jquery.maskedinput.min.js
deleted
100644 → 0
View file @
bc625ab5
/*
Masked Input plugin for jQuery
Copyright (c) 2007-2013 Josh Bush (digitalbush.com)
Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
Version: 1.3.1
*/
(
function
(
e
){
function
t
(){
var
e
=
document
.
createElement
(
"input"
),
t
=
"onpaste"
;
return
e
.
setAttribute
(
t
,
""
),
"function"
==
typeof
e
[
t
]?
"paste"
:
"input"
}
var
n
,
a
=
t
()
+
".mask"
,
r
=
navigator
.
userAgent
,
i
=
/iphone/i
.
test
(
r
),
o
=
/android/i
.
test
(
r
);
e
.
mask
=
{
definitions
:{
9
:
"[0-9]"
,
a
:
"[A-Za-z]"
,
"*"
:
"[A-Za-z0-9]"
},
dataName
:
"rawMaskFn"
,
placeholder
:
"_"
},
e
.
fn
.
extend
({
caret
:
function
(
e
,
t
){
var
n
;
if
(
0
!==
this
.
length
&&!
this
.
is
(
":hidden"
))
return
"number"
==
typeof
e
?(
t
=
"number"
==
typeof
t
?
t
:
e
,
this
.
each
(
function
(){
this
.
setSelectionRange
?
this
.
setSelectionRange
(
e
,
t
):
this
.
createTextRange
&&
(
n
=
this
.
createTextRange
(),
n
.
collapse
(
!
0
),
n
.
moveEnd
(
"character"
,
t
),
n
.
moveStart
(
"character"
,
e
),
n
.
select
())})):(
this
[
0
].
setSelectionRange
?(
e
=
this
[
0
].
selectionStart
,
t
=
this
[
0
].
selectionEnd
):
document
.
selection
&&
document
.
selection
.
createRange
&&
(
n
=
document
.
selection
.
createRange
(),
e
=
0
-
n
.
duplicate
().
moveStart
(
"character"
,
-
1
e5
),
t
=
e
+
n
.
text
.
length
),{
begin
:
e
,
end
:
t
})},
unmask
:
function
(){
return
this
.
trigger
(
"unmask"
)},
mask
:
function
(
t
,
r
){
var
c
,
l
,
s
,
u
,
f
,
h
;
return
!
t
&&
this
.
length
>
0
?(
c
=
e
(
this
[
0
]),
c
.
data
(
e
.
mask
.
dataName
)()):(
r
=
e
.
extend
({
placeholder
:
e
.
mask
.
placeholder
,
completed
:
null
},
r
),
l
=
e
.
mask
.
definitions
,
s
=
[],
u
=
h
=
t
.
length
,
f
=
null
,
e
.
each
(
t
.
split
(
""
),
function
(
e
,
t
){
"?"
==
t
?(
h
--
,
u
=
e
):
l
[
t
]?(
s
.
push
(
RegExp
(
l
[
t
])),
null
===
f
&&
(
f
=
s
.
length
-
1
)):
s
.
push
(
null
)}),
this
.
trigger
(
"unmask"
).
each
(
function
(){
function
c
(
e
){
for
(;
h
>++
e
&&!
s
[
e
];);
return
e
}
function
d
(
e
){
for
(;
--
e
>=
0
&&!
s
[
e
];);
return
e
}
function
m
(
e
,
t
){
var
n
,
a
;
if
(
!
(
0
>
e
)){
for
(
n
=
e
,
a
=
c
(
t
);
h
>
n
;
n
++
)
if
(
s
[
n
]){
if
(
!
(
h
>
a
&&
s
[
n
].
test
(
R
[
a
])))
break
;
R
[
n
]
=
R
[
a
],
R
[
a
]
=
r
.
placeholder
,
a
=
c
(
a
)}
b
(),
x
.
caret
(
Math
.
max
(
f
,
e
))}}
function
p
(
e
){
var
t
,
n
,
a
,
i
;
for
(
t
=
e
,
n
=
r
.
placeholder
;
h
>
t
;
t
++
)
if
(
s
[
t
]){
if
(
a
=
c
(
t
),
i
=
R
[
t
],
R
[
t
]
=
n
,
!
(
h
>
a
&&
s
[
a
].
test
(
i
)))
break
;
n
=
i
}}
function
g
(
e
){
var
t
,
n
,
a
,
r
=
e
.
which
;
8
===
r
||
46
===
r
||
i
&&
127
===
r
?(
t
=
x
.
caret
(),
n
=
t
.
begin
,
a
=
t
.
end
,
0
===
a
-
n
&&
(
n
=
46
!==
r
?
d
(
n
):
a
=
c
(
n
-
1
),
a
=
46
===
r
?
c
(
a
):
a
),
k
(
n
,
a
),
m
(
n
,
a
-
1
),
e
.
preventDefault
()):
27
==
r
&&
(
x
.
val
(
S
),
x
.
caret
(
0
,
y
()),
e
.
preventDefault
())}
function
v
(
t
){
var
n
,
a
,
i
,
l
=
t
.
which
,
u
=
x
.
caret
();
t
.
ctrlKey
||
t
.
altKey
||
t
.
metaKey
||
32
>
l
||
l
&&
(
0
!==
u
.
end
-
u
.
begin
&&
(
k
(
u
.
begin
,
u
.
end
),
m
(
u
.
begin
,
u
.
end
-
1
)),
n
=
c
(
u
.
begin
-
1
),
h
>
n
&&
(
a
=
String
.
fromCharCode
(
l
),
s
[
n
].
test
(
a
)
&&
(
p
(
n
),
R
[
n
]
=
a
,
b
(),
i
=
c
(
n
),
o
?
setTimeout
(
e
.
proxy
(
e
.
fn
.
caret
,
x
,
i
),
0
):
x
.
caret
(
i
),
r
.
completed
&&
i
>=
h
&&
r
.
completed
.
call
(
x
))),
t
.
preventDefault
())}
function
k
(
e
,
t
){
var
n
;
for
(
n
=
e
;
t
>
n
&&
h
>
n
;
n
++
)
s
[
n
]
&&
(
R
[
n
]
=
r
.
placeholder
)}
function
b
(){
x
.
val
(
R
.
join
(
""
))}
function
y
(
e
){
var
t
,
n
,
a
=
x
.
val
(),
i
=-
1
;
for
(
t
=
0
,
pos
=
0
;
h
>
t
;
t
++
)
if
(
s
[
t
]){
for
(
R
[
t
]
=
r
.
placeholder
;
pos
++<
a
.
length
;)
if
(
n
=
a
.
charAt
(
pos
-
1
),
s
[
t
].
test
(
n
)){
R
[
t
]
=
n
,
i
=
t
;
break
}
if
(
pos
>
a
.
length
)
break
}
else
R
[
t
]
===
a
.
charAt
(
pos
)
&&
t
!==
u
&&
(
pos
++
,
i
=
t
);
return
e
?
b
():
u
>
i
+
1
?(
x
.
val
(
""
),
k
(
0
,
h
)):(
b
(),
x
.
val
(
x
.
val
().
substring
(
0
,
i
+
1
))),
u
?
t
:
f
}
var
x
=
e
(
this
),
R
=
e
.
map
(
t
.
split
(
""
),
function
(
e
){
return
"?"
!=
e
?
l
[
e
]?
r
.
placeholder
:
e
:
void
0
}),
S
=
x
.
val
();
x
.
data
(
e
.
mask
.
dataName
,
function
(){
return
e
.
map
(
R
,
function
(
e
,
t
){
return
s
[
t
]
&&
e
!=
r
.
placeholder
?
e
:
null
}).
join
(
""
)}),
x
.
attr
(
"readonly"
)
||
x
.
one
(
"unmask"
,
function
(){
x
.
unbind
(
".mask"
).
removeData
(
e
.
mask
.
dataName
)}).
bind
(
"focus.mask"
,
function
(){
clearTimeout
(
n
);
var
e
;
S
=
x
.
val
(),
e
=
y
(),
n
=
setTimeout
(
function
(){
b
(),
e
==
t
.
length
?
x
.
caret
(
0
,
e
):
x
.
caret
(
e
)},
10
)}).
bind
(
"blur.mask"
,
function
(){
y
(),
x
.
val
()
!=
S
&&
x
.
change
()}).
bind
(
"keydown.mask"
,
g
).
bind
(
"keypress.mask"
,
v
).
bind
(
a
,
function
(){
setTimeout
(
function
(){
var
e
=
y
(
!
0
);
x
.
caret
(
e
),
r
.
completed
&&
e
==
x
.
val
().
length
&&
r
.
completed
.
call
(
x
)},
0
)}),
y
()}))}})})(
jQuery
);
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