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
108b0fc3
Commit
108b0fc3
authored
Dec 27, 2012
by
Valera Rozuvan
Committed by
Alexander Kryklia
Jan 21, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactoring and code documentation.
parent
f2e930a3
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
149 additions
and
150 deletions
+149
-150
common/static/js/capa/drag_and_drop/base_image.js
+3
-31
common/static/js/capa/drag_and_drop/config_parser.js
+2
-2
common/static/js/capa/drag_and_drop/draggables.js
+90
-66
common/static/js/capa/drag_and_drop/main.js
+8
-5
common/static/js/capa/drag_and_drop/scroller.js
+25
-0
common/static/js/capa/drag_and_drop/state.js
+2
-0
common/static/js/capa/drag_and_drop/targets.js
+16
-36
common/static/js/capa/drag_and_drop/update_input.js
+3
-10
No files found.
common/static/js/capa/drag_and_drop/base_image.js
View file @
108b0fc3
...
...
@@ -8,53 +8,25 @@ define(['logme'], function (logme) {
return
BaseImage
;
function
BaseImage
(
state
)
{
var
targetImgSrc
,
baseImageElContainer
,
mouseMoveDiv
;
targetImgSrc
=
state
.
config
.
imageDir
+
'/'
+
state
.
config
.
base_image
;
var
baseImageElContainer
;
baseImageElContainer
=
$
(
'<div '
+
'class="base_image_container" '
+
'style=" '
+
'position: relative; '
+
'margin-bottom: 25px; '
+
'" '
+
'></div>'
);
state
.
baseImageEl
=
$
(
'<img '
+
'src="'
+
targetImgSrc
+
'" '
+
'src="'
+
state
.
config
.
imageDir
+
'/'
+
state
.
config
.
base_image
+
'" '
+
'/>'
);
state
.
baseImageEl
.
appendTo
(
baseImageElContainer
);
state
.
baseImageElWidth
=
null
;
$
(
'<img/>'
)
// Make in memory copy of image to avoid css issues.
.
attr
(
'src'
,
state
.
baseImageEl
.
attr
(
'src'
))
.
load
(
function
()
{
state
.
baseImageElWidth
=
this
.
width
;
});
// state.baseImageEl.mousemove(
// function (event) {
// mouseMoveDiv.html(
// '[' + event.offsetX + ', ' + event.offsetY + ']'
// );
// }
// );
mouseMoveDiv
=
$
(
'<div '
+
'style=" '
+
'clear: both; '
+
'width: auto; '
+
'height: 25px; '
+
'text-align: center; '
+
'" '
+
'></div>'
);
mouseMoveDiv
.
appendTo
(
baseImageElContainer
);
baseImageElContainer
.
appendTo
(
state
.
containerEl
);
}
});
...
...
common/static/js/capa/drag_and_drop/config_parser.js
View file @
108b0fc3
...
...
@@ -78,9 +78,9 @@ define(['logme'], function (logme) {
if
(
typeof
config
.
target_outline
===
'string'
)
{
if
(
config
.
target_outline
.
toLowerCase
()
===
'true'
)
{
state
.
config
.
target
_o
utline
=
true
;
state
.
config
.
target
O
utline
=
true
;
}
else
if
(
config
.
target_outline
.
toLowerCase
()
===
'false'
)
{
state
.
config
.
target
_o
utline
=
false
;
state
.
config
.
target
O
utline
=
false
;
}
else
{
logme
(
'ERROR: Property config.target_outline can either be "true", or "false".'
);
returnStatus
=
false
;
...
...
common/static/js/capa/drag_and_drop/draggables.js
View file @
108b0fc3
...
...
@@ -8,22 +8,13 @@ define(['logme', 'update_input'], function (logme, updateInput) {
return
Draggables
;
function
Draggables
(
state
)
{
var
_draggables
,
numDraggables
;
var
c1
;
numDraggables
=
state
.
config
.
draggables
.
length
;
_draggables
=
[];
state
.
draggables
=
[];
(
function
(
i
)
{
while
(
i
<
numDraggables
)
{
processDraggable
(
state
.
config
.
draggables
[
i
],
i
+
1
);
i
+=
1
;
}
if
(
state
.
individualTargets
===
false
)
{
updateInput
(
state
,
true
);
}
}(
0
));
for
(
c1
=
0
;
c1
<
state
.
config
.
draggables
.
length
;
c1
+=
1
)
{
processDraggable
(
state
.
config
.
draggables
[
c1
],
c1
+
1
);
}
state
.
currentMovingDraggable
=
null
;
...
...
@@ -39,8 +30,8 @@ define(['logme', 'update_input'], function (logme, updateInput) {
return
;
function
processDraggable
(
obj
,
objIndex
)
{
var
draggableContainerEl
,
i
mgEl
,
inContainer
,
ousePressed
,
onTarget
,
draggableObj
,
marginCss
;
var
draggableContainerEl
,
i
nContainer
,
mousePressed
,
onTarget
,
draggableObj
,
marginCss
;
draggableContainerEl
=
$
(
'<div '
+
...
...
@@ -51,20 +42,16 @@ define(['logme', 'update_input'], function (logme, updateInput) {
'float: left; '
+
'overflow: hidden; '
+
'z-index: '
+
objIndex
+
'; '
+
'border: 1px solid
gray
; '
+
'border: 1px solid
#CCC
; '
+
'" '
+
'data-draggable-position-index="'
+
objIndex
+
'" '
+
'></div>'
);
if
(
obj
.
icon
.
length
>
0
)
{
imgEl
=
$
(
'<img '
+
'src="'
+
state
.
config
.
imageDir
+
'/'
+
obj
.
icon
+
'" '
+
'/>'
draggableContainerEl
.
append
(
$
(
'<img src="'
+
state
.
config
.
imageDir
+
'/'
+
obj
.
icon
+
'" />'
)
);
draggableContainerEl
.
append
(
imgEl
);
}
if
(
obj
.
label
.
length
>
0
)
{
...
...
@@ -80,7 +67,6 @@ define(['logme', 'update_input'], function (logme, updateInput) {
}
draggableContainerEl
.
appendTo
(
state
.
sliderEl
);
_draggables
.
push
(
draggableContainerEl
);
inContainer
=
true
;
mousePressed
=
false
;
...
...
@@ -102,12 +88,6 @@ define(['logme', 'update_input'], function (logme, updateInput) {
draggableContainerEl
.
mouseup
(
mouseUp
);
draggableContainerEl
.
mousemove
(
mouseMove
);
if
(
objIndex
+
1
===
numDraggables
)
{
state
.
draggablesLoaded
=
true
;
state
.
updateArrowOpacity
();
}
return
;
function
mouseDown
(
event
)
{
...
...
@@ -134,10 +114,9 @@ define(['logme', 'update_input'], function (logme, updateInput) {
}
}
function
mouseUp
(
event
)
{
function
mouseUp
()
{
if
(
mousePressed
===
true
)
{
state
.
currentMovingDraggable
=
null
;
normalizeEvent
(
event
);
checkLandingElement
(
event
);
}
...
...
@@ -150,14 +129,30 @@ define(['logme', 'update_input'], function (logme, updateInput) {
}
}
function
checkLandingElement
(
event
)
{
// At this point the mouse was realeased, and we need to check
// where the draggable eneded up. Based on several things, we
// will either move the draggable back to the slider, or update
// the input with the user's answer (X-Y position of the draggable,
// or the ID of the target where it landed.
function
checkLandingElement
()
{
var
offsetDE
,
indexes
,
DEindex
,
targetFound
;
mousePressed
=
false
;
offsetDE
=
draggableContainerEl
.
position
();
if
(
state
.
individualTargets
===
false
)
{
if
(
state
.
individualTargets
===
true
)
{
targetFound
=
false
;
checkIfOnTarget
();
if
(
targetFound
===
true
)
{
correctZIndexes
();
}
else
{
moveBackToSlider
();
removeObjIdFromTarget
();
}
}
else
{
if
(
(
offsetDE
.
left
<
0
)
||
(
offsetDE
.
left
+
100
>
state
.
baseImageEl
.
width
())
||
...
...
@@ -174,21 +169,9 @@ define(['logme', 'update_input'], function (logme, updateInput) {
draggableObj
.
x
=
offsetDE
.
left
+
50
;
draggableObj
.
y
=
offsetDE
.
top
+
50
;
}
}
else
if
(
state
.
individualTargets
===
true
)
{
targetFound
=
false
;
checkIfOnTarget
();
if
(
targetFound
===
true
)
{
correctZIndexes
();
}
else
{
moveBackToSlider
();
removeObjIdFromTarget
();
}
}
state
.
updateArrowOpacity
();
updateInput
(
state
);
return
;
...
...
@@ -197,25 +180,26 @@ define(['logme', 'update_input'], function (logme, updateInput) {
var
c1
;
if
(
onTarget
!==
null
)
{
c1
=
0
;
while
(
c1
<
onTarget
.
draggable
.
length
)
{
for
(
c1
=
0
;
c1
<
onTarget
.
draggable
.
length
;
c1
+=
1
)
{
if
(
onTarget
.
draggable
[
c1
]
===
obj
.
id
)
{
onTarget
.
draggable
.
splice
(
c1
,
1
);
break
;
}
c1
+=
1
;
}
onTarget
=
null
;
}
}
// Determine if a draggable, after it was relased, ends up on a
// target. We do this by iterating over all of the targets, and
// for each one we check whether the draggable's center is
// within the target's dimensions.
function
checkIfOnTarget
()
{
var
c1
,
target
;
for
(
c1
=
0
;
c1
<
state
.
targets
.
length
;
c1
++
)
{
for
(
c1
=
0
;
c1
<
state
.
targets
.
length
;
c1
+=
1
)
{
target
=
state
.
targets
[
c1
];
if
(
offsetDE
.
top
+
50
<
target
.
offset
.
top
)
{
...
...
@@ -241,10 +225,21 @@ define(['logme', 'update_input'], function (logme, updateInput) {
targetFound
=
true
;
removeObjIdFromTarget
();
onTarget
=
target
;
// If the draggable was moved from one target to
// another, then we need to remove it's ID from the
// previous target's draggables list, and add it to the
// new target's draggables list.
if
((
onTarget
!==
null
)
&&
(
onTarget
.
id
!==
target
.
id
))
{
removeObjIdFromTarget
();
onTarget
=
target
;
target
.
draggable
.
push
(
obj
.
id
);
}
else
if
(
onTarget
===
null
)
{
onTarget
=
target
;
target
.
draggable
.
push
(
obj
.
id
);
}
target
.
draggable
.
push
(
obj
.
id
);
// Reposition the draggable so that it's center
// coincides with the center of the target.
snapToTarget
(
target
);
break
;
...
...
@@ -256,30 +251,47 @@ define(['logme', 'update_input'], function (logme, updateInput) {
draggableContainerEl
.
css
(
'top'
,
target
.
offset
.
top
+
0.5
*
target
.
h
-
50
);
}
// Go through all of the draggables subtract 1 from the z-index
// of all whose z-index is higher than the old z-index of the
// current element. After, set the z-index of the current
// element to 1 + N (where N is the number of draggables - i.e.
// the highest z-index possible).
//
// This will make sure that after releasing a draggable, it
// will be on top of all of the other draggables. Also, the
// ordering of the visibility (z-index) of the other draggables
// will not change.
function
correctZIndexes
()
{
var
c1
;
c1
=
0
;
while
(
c1
<
_draggables
.
length
)
{
if
(
parseInt
(
draggableContainerEl
.
attr
(
'data-old-z-index'
),
10
)
<
parseInt
(
_draggables
[
c1
].
css
(
'z-index'
),
10
))
{
_draggables
[
c1
].
css
(
'z-index'
,
parseInt
(
_draggables
[
c1
].
css
(
'z-index'
),
10
)
-
1
);
for
(
c1
=
0
;
c1
<
state
.
draggables
.
length
;
c1
++
)
{
if
(
parseInt
(
draggableContainerEl
.
attr
(
'data-old-z-index'
),
10
)
<
parseInt
(
state
.
draggables
[
c1
].
el
.
css
(
'z-index'
),
10
)
)
{
state
.
draggables
[
c1
].
el
.
css
(
'z-index'
,
parseInt
(
state
.
draggables
[
c1
].
el
.
css
(
'z-index'
),
10
)
-
1
);
}
c1
+=
1
;
}
draggableContainerEl
.
css
(
'z-index'
,
c1
);
}
// If a draggable was released in a wrong positione, we will
// move it back to the slider, placing it in the same position
// that it was dragged out of.
function
moveBackToSlider
()
{
var
c1
;
draggableContainerEl
.
detach
();
draggableContainerEl
.
css
(
'position'
,
'static'
);
// Get the position indexes of all draggables that are
// currently in the slider, along with the corresponding
// jQuery element.
indexes
=
[];
DEindex
=
parseInt
(
draggableContainerEl
.
attr
(
'data-draggable-position-index'
),
10
);
state
.
sliderEl
.
children
().
each
(
function
(
index
,
value
)
{
indexes
.
push
({
'index'
:
parseInt
(
$
(
value
).
attr
(
'data-draggable-position-index'
),
10
),
...
...
@@ -287,27 +299,39 @@ define(['logme', 'update_input'], function (logme, updateInput) {
});
});
c1
=
0
;
// Get the position index of the element that we are
// inserting back into the slider.
DEindex
=
parseInt
(
draggableContainerEl
.
attr
(
'data-draggable-position-index'
),
10
);
while
(
c1
<
indexes
.
length
)
{
// Starting from the first position index that we
// retrieved, and going up, if we find a position index
// that is more than 'DEindex', we know that we must insert
// the current element before the element with the greater
// position index.
for
(
c1
=
0
;
c1
<
indexes
.
length
;
c1
+=
1
)
{
if
((
inContainer
===
false
)
&&
(
indexes
[
c1
].
index
>
DEindex
))
{
indexes
[
c1
].
el
.
before
(
draggableContainerEl
);
inContainer
=
true
;
}
c1
+=
1
;
}
// If we did not find a greater postion index, then either
// there are no elements in the slider, or all of them
// have a lesser position index. In both cases we add the
// current draggable to the end.
if
(
inContainer
===
false
)
{
draggableContainerEl
.
appendTo
(
state
.
sliderEl
);
inContainer
=
true
;
}
inContainer
=
true
;
draggableContainerEl
.
css
(
'border'
,
'1px solid gray'
);
}
}
}
// In firefox the event does not have a proper pageX and pageY
// coordinates.
function
normalizeEvent
(
event
)
{
if
(
!
event
.
offsetX
)
{
event
.
offsetX
=
(
event
.
pageX
-
$
(
event
.
target
).
offset
().
left
);
...
...
common/static/js/capa/drag_and_drop/main.js
View file @
108b0fc3
...
...
@@ -5,8 +5,10 @@
(
function
(
requirejs
,
require
,
define
)
{
define
(
[
'logme'
,
'state'
,
'config_parser'
,
'container'
,
'base_image'
,
'scroller'
,
'draggables'
,
'targets'
],
function
(
logme
,
State
,
configParser
,
Container
,
BaseImage
,
Scroller
,
Draggables
,
Targets
)
{
[
'logme'
,
'state'
,
'config_parser'
,
'container'
,
'base_image'
,
'scroller'
,
'draggables'
,
'targets'
,
'update_input'
],
function
(
logme
,
State
,
configParser
,
Container
,
BaseImage
,
Scroller
,
Draggables
,
Targets
,
updateInput
)
{
return
Main
;
function
Main
()
{
...
...
@@ -58,12 +60,13 @@ define(
Container
(
state
);
BaseImage
(
state
);
Targets
(
state
);
Scroller
(
state
);
Draggables
(
state
);
Targets
(
state
);
logme
(
'config'
,
config
);
logme
(
'state'
,
state
);
// Update the input element, checking first that it is not filled with
// an answer from the server.
updateInput
(
state
,
true
);
}
});
...
...
common/static/js/capa/drag_and_drop/scroller.js
View file @
108b0fc3
...
...
@@ -61,14 +61,20 @@ define(['logme'], function (logme) {
moveLeftEl
.
mousemove
(
function
(
event
)
{
event
.
preventDefault
();
});
moveLeftEl
.
mousedown
(
function
(
event
)
{
event
.
preventDefault
();
});
// This event will be responsible for moving the scroller left.
// Hidden draggables will be shown.
moveLeftEl
.
mouseup
(
function
(
event
)
{
event
.
preventDefault
();
// When there are no more hidden draggables, prevent from
// scrolling infinitely.
if
(
showElLeftMargin
>
-
102
)
{
return
;
}
showElLeftMargin
+=
102
;
// We scroll by changing the 'margin-left' CSS property smoothly.
state
.
sliderEl
.
animate
({
'margin-left'
:
showElLeftMargin
+
'px'
},
100
,
function
()
{
...
...
@@ -91,6 +97,10 @@ define(['logme'], function (logme) {
showElLeftMargin
=
0
;
// Element where the draggables will be contained. It is very long
// so that any SANE number of draggables will fit in a single row. It
// will be contained in a parent element whose 'overflow' CSS value
// will be hidden, preventing the long row from fully being visible.
state
.
sliderEl
=
$
(
'<div '
+
'style=" '
+
...
...
@@ -141,15 +151,20 @@ define(['logme'], function (logme) {
moveRightEl
.
mousemove
(
function
(
event
)
{
event
.
preventDefault
();
});
moveRightEl
.
mousedown
(
function
(
event
)
{
event
.
preventDefault
();
});
// This event will be responsible for moving the scroller right.
// Hidden draggables will be shown.
moveRightEl
.
mouseup
(
function
(
event
)
{
event
.
preventDefault
();
// When there are no more hidden draggables, prevent from
// scrolling infinitely.
if
(
showElLeftMargin
<
-
102
*
(
state
.
sliderEl
.
children
().
length
-
6
))
{
return
;
}
showElLeftMargin
-=
102
;
// We scroll by changing the 'margin-left' CSS property smoothly.
state
.
sliderEl
.
animate
({
'margin-left'
:
showElLeftMargin
+
'px'
},
100
,
function
()
{
...
...
@@ -159,6 +174,16 @@ define(['logme'], function (logme) {
parentEl
.
appendTo
(
state
.
containerEl
);
// Make the function available throughout the application. We need to
// call it in several places:
//
// 1.) When initially reading answer from server, if draggables will be
// positioned on the base image, the scroller's right and left arrows
// opacity must be updated.
//
// 2.) When creating draggable elements, the scroller's right and left
// arrows opacity must be updated according to the number of
// draggables.
state
.
updateArrowOpacity
=
updateArrowOpacity
;
return
;
...
...
common/static/js/capa/drag_and_drop/state.js
View file @
108b0fc3
...
...
@@ -11,6 +11,8 @@ define([], function () {
return
{
'problemId'
:
problemId
,
// Will indicate when all targetsand draggables have been loaded,
// processed, and postioned intially.
'targetsLoaded'
:
false
,
'draggablesLoaded'
:
false
};
...
...
common/static/js/capa/drag_and_drop/targets.js
View file @
108b0fc3
...
...
@@ -4,48 +4,29 @@
// See https://edx-wiki.atlassian.net/wiki/display/LMS/Integration+of+Require+JS+into+the+system
(
function
(
requirejs
,
require
,
define
)
{
define
([
'logme'
,
'update_input'
],
function
(
logme
,
updateInput
)
{
define
([
'logme'
],
function
(
logme
)
{
return
Targets
;
function
Targets
(
state
)
{
var
numTargets
;
var
c1
;
numTargets
=
state
.
config
.
targets
.
length
;
state
.
targets
=
[];
(
function
(
c1
)
{
while
(
c1
<
numTargets
)
{
processTarget
(
state
.
config
.
targets
[
c1
],
c1
);
c1
+=
1
;
}
if
(
state
.
individualTargets
===
true
)
{
updateInput
(
state
,
true
);
}
}(
0
));
for
(
c1
=
0
;
c1
<
state
.
config
.
targets
.
length
;
c1
++
)
{
processTarget
(
state
.
config
.
targets
[
c1
]);
}
return
;
function
processTarget
(
obj
,
objIndex
)
{
var
baseImageElOffset
,
tEl
,
left
,
borderCss
;
// if (state.baseImageElWidth === null) {
// window.setTimeout(function () {
// processTarget(obj);
// }, 50);
//
// return;
// }
// left = obj.x + 0.5 * (state.baseImageEl.parent().width() - state.baseImageElWidth);
left
=
obj
.
x
;
function
processTarget
(
obj
)
{
var
targetEl
,
borderCss
;
borderCss
=
''
;
if
(
state
.
config
.
target
_o
utline
===
true
)
{
if
(
state
.
config
.
target
O
utline
===
true
)
{
borderCss
=
'border: 1px dashed gray; '
;
}
tEl
=
$
(
t
arget
El
=
$
(
'<div '
+
'style=" '
+
'display: block; '
+
...
...
@@ -53,27 +34,26 @@ define(['logme', 'update_input'], function (logme, updateInput) {
'width: '
+
obj
.
w
+
'px; '
+
'height: '
+
obj
.
h
+
'px; '
+
'top: '
+
obj
.
y
+
'px; '
+
'left: '
+
left
+
'px; '
+
'left: '
+
obj
.
x
+
'px; '
+
borderCss
+
'" '
+
'data-target-id="'
+
obj
.
id
+
'" '
+
'></div>'
);
tEl
.
appendTo
(
state
.
baseImageEl
.
parent
());
t
arget
El
.
appendTo
(
state
.
baseImageEl
.
parent
());
state
.
targets
.
push
({
'id'
:
obj
.
id
,
'offset'
:
tEl
.
position
(),
'w'
:
obj
.
w
,
'h'
:
obj
.
h
,
'el'
:
tEl
,
'el'
:
targetEl
,
'offset'
:
targetEl
.
position
(),
'draggable'
:
[]
});
if
(
objIndex
+
1
===
numTargets
)
{
state
.
targetsLoaded
=
true
;
}
}
}
});
...
...
common/static/js/capa/drag_and_drop/update_input.js
View file @
108b0fc3
...
...
@@ -54,6 +54,8 @@ define(['logme'], function (logme) {
inputEl
=
$
(
'#input_'
+
state
.
problemId
);
inputEl
.
val
(
stateStr
);
logme
(
inputEl
.
val
());
return
;
// Check if input has an answer from server. If yes, then position
...
...
@@ -75,16 +77,7 @@ define(['logme'], function (logme) {
var
draggableId
,
draggable
,
targetId
,
target
,
draggablePosition
,
c1
;
if
(
((
state
.
individualTargets
===
true
)
&&
(
state
.
targetsLoaded
===
false
))
||
(
state
.
draggablesLoaded
===
false
)
)
{
window
.
setTimeout
(
function
()
{
repositionDraggables
(
answer
);
},
50
);
return
;
}
logme
(
answer
);
if
(
((
typeof
answer
.
use_targets
===
'boolean'
)
&&
(
answer
.
use_targets
===
true
))
||
...
...
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