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
650bdc2f
Commit
650bdc2f
authored
Jul 22, 2014
by
cahrens
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Drag and drop support on the course outline page.
parent
e8ae3d1b
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
161 additions
and
91 deletions
+161
-91
cms/djangoapps/contentstore/features/course-outline.py
+0
-11
cms/static/js/spec/utils/drag_and_drop_spec.js
+37
-11
cms/static/js/spec/views/pages/course_outline_spec.js
+3
-3
cms/static/js/utils/drag_and_drop.js
+59
-33
cms/static/js/views/course_outline.js
+38
-3
cms/static/js/views/overview.js
+3
-24
cms/static/sass/elements/_controls.scss
+3
-0
cms/static/sass/views/_outline.scss
+4
-0
cms/templates/js/course-outline.underscore
+14
-1
cms/templates/js/xblock-outline.underscore
+0
-5
No files found.
cms/djangoapps/contentstore/features/course-outline.py
View file @
650bdc2f
...
@@ -131,14 +131,3 @@ def all_sections_are_collapsed_or_expanded(step, text):
...
@@ -131,14 +131,3 @@ def all_sections_are_collapsed_or_expanded(step, text):
def
change_grading_status
(
step
):
def
change_grading_status
(
step
):
world
.
css_find
(
'a.menu-toggle'
)
.
click
()
world
.
css_find
(
'a.menu-toggle'
)
.
click
()
world
.
css_find
(
'.menu li'
)
.
first
.
click
()
world
.
css_find
(
'.menu li'
)
.
first
.
click
()
@step
(
u'I reorder subsections'
)
def
reorder_subsections
(
_step
):
draggable_css
=
'.subsection-drag-handle'
ele
=
world
.
css_find
(
draggable_css
)
.
first
ele
.
action_chains
.
drag_and_drop_by_offset
(
ele
.
_element
,
0
,
25
)
.
perform
()
cms/static/js/spec/utils/drag_and_drop_spec.js
View file @
650bdc2f
define
([
"js/utils/drag_and_drop"
,
"js/views/feedback_notification"
,
"js/spec_helpers/create_sinon"
,
"jquery"
],
define
([
"js/utils/drag_and_drop"
,
"js/views/feedback_notification"
,
"js/spec_helpers/create_sinon"
,
"jquery"
,
"underscore"
],
function
(
ContentDragger
,
Notification
,
create_sinon
,
$
)
{
function
(
ContentDragger
,
Notification
,
create_sinon
,
$
,
_
)
{
describe
(
"Overview drag and drop functionality"
,
function
()
{
describe
(
"Overview drag and drop functionality"
,
function
()
{
beforeEach
(
function
()
{
beforeEach
(
function
()
{
setFixtures
(
readFixtures
(
'mock/mock-outline.underscore'
));
setFixtures
(
readFixtures
(
'mock/mock-outline.underscore'
));
ContentDragger
.
makeDraggable
(
'.unit'
,
'.unit-drag-handle'
,
'ol.sortable-unit-list'
,
'li.courseware-subsection, article.subsection-body'
);
_
.
each
(
ContentDragger
.
makeDraggable
(
'.courseware-subsection'
,
'.subsection-drag-handle'
,
'.sortable-subsection-list'
,
'section'
);
$
(
'.unit'
),
function
(
element
)
{
ContentDragger
.
makeDraggable
(
element
,
{
type
:
'.unit'
,
handleClass
:
'.unit-drag-handle'
,
droppableClass
:
'ol.sortable-unit-list'
,
parentLocationSelector
:
'li.courseware-subsection'
,
refresh
:
jasmine
.
createSpy
(
'Spy on Unit'
)
});
}
);
_
.
each
(
$
(
'.courseware-subsection'
),
function
(
element
)
{
ContentDragger
.
makeDraggable
(
element
,
{
type
:
'.courseware-subsection'
,
handleClass
:
'.subsection-drag-handle'
,
droppableClass
:
'.sortable-subsection-list'
,
parentLocationSelector
:
'section'
,
refresh
:
jasmine
.
createSpy
(
'Spy on Subsection'
)
});
}
);
});
});
describe
(
"findDestination"
,
function
()
{
describe
(
"findDestination"
,
function
()
{
...
@@ -115,7 +137,7 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel
...
@@ -115,7 +137,7 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel
});
});
it
(
"can drag into a collapsed list"
,
function
()
{
it
(
"can drag into a collapsed list"
,
function
()
{
var
$ele
,
destination
;
var
$ele
,
destination
;
$
(
'#subsection-2'
).
addClass
(
'collapsed'
);
$
(
'#subsection-2'
).
addClass
(
'
is-
collapsed'
);
$ele
=
$
(
'#unit-2'
);
$ele
=
$
(
'#unit-2'
);
$ele
.
offset
({
$ele
.
offset
({
top
:
$
(
'#subsection-2'
).
offset
().
top
+
3
,
top
:
$
(
'#subsection-2'
).
offset
().
top
+
3
,
...
@@ -142,11 +164,11 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel
...
@@ -142,11 +164,11 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel
});
});
});
});
it
(
"collapses expanded elements"
,
function
()
{
it
(
"collapses expanded elements"
,
function
()
{
expect
(
$
(
'#subsection-1'
)).
not
.
toHaveClass
(
'collapsed'
);
expect
(
$
(
'#subsection-1'
)).
not
.
toHaveClass
(
'
is-
collapsed'
);
ContentDragger
.
onDragStart
({
ContentDragger
.
onDragStart
({
element
:
$
(
'#subsection-1'
)
element
:
$
(
'#subsection-1'
)
},
null
,
null
);
},
null
,
null
);
expect
(
$
(
'#subsection-1'
)).
toHaveClass
(
'collapsed'
);
expect
(
$
(
'#subsection-1'
)).
toHaveClass
(
'
is-
collapsed'
);
expect
(
$
(
'#subsection-1'
)).
toHaveClass
(
'expand-on-drop'
);
expect
(
$
(
'#subsection-1'
)).
toHaveClass
(
'expand-on-drop'
);
});
});
});
});
...
@@ -246,16 +268,16 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel
...
@@ -246,16 +268,16 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel
expect
([
'0px'
,
'auto'
]).
toContain
(
$
(
'#unit-1'
).
css
(
'left'
));
expect
([
'0px'
,
'auto'
]).
toContain
(
$
(
'#unit-1'
).
css
(
'left'
));
});
});
it
(
"expands an element if it was collapsed on drag start"
,
function
()
{
it
(
"expands an element if it was collapsed on drag start"
,
function
()
{
$
(
'#subsection-1'
).
addClass
(
'collapsed'
);
$
(
'#subsection-1'
).
addClass
(
'
is-
collapsed'
);
$
(
'#subsection-1'
).
addClass
(
'expand-on-drop'
);
$
(
'#subsection-1'
).
addClass
(
'expand-on-drop'
);
ContentDragger
.
onDragEnd
({
ContentDragger
.
onDragEnd
({
element
:
$
(
'#subsection-1'
)
element
:
$
(
'#subsection-1'
)
},
null
,
null
);
},
null
,
null
);
expect
(
$
(
'#subsection-1'
)).
not
.
toHaveClass
(
'collapsed'
);
expect
(
$
(
'#subsection-1'
)).
not
.
toHaveClass
(
'
is-
collapsed'
);
expect
(
$
(
'#subsection-1'
)).
not
.
toHaveClass
(
'expand-on-drop'
);
expect
(
$
(
'#subsection-1'
)).
not
.
toHaveClass
(
'expand-on-drop'
);
});
});
it
(
"expands a collapsed element when something is dropped in it"
,
function
()
{
it
(
"expands a collapsed element when something is dropped in it"
,
function
()
{
$
(
'#subsection-2'
).
addClass
(
'collapsed'
);
$
(
'#subsection-2'
).
addClass
(
'
is-
collapsed'
);
ContentDragger
.
dragState
.
dropDestination
=
$
(
'#list-2'
);
ContentDragger
.
dragState
.
dropDestination
=
$
(
'#list-2'
);
ContentDragger
.
dragState
.
attachMethod
=
"prepend"
;
ContentDragger
.
dragState
.
attachMethod
=
"prepend"
;
ContentDragger
.
dragState
.
parentList
=
$
(
'#subsection-2'
);
ContentDragger
.
dragState
.
parentList
=
$
(
'#subsection-2'
);
...
@@ -264,7 +286,7 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel
...
@@ -264,7 +286,7 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel
},
null
,
{
},
null
,
{
clientX
:
$
(
'#unit-1'
).
offset
().
left
clientX
:
$
(
'#unit-1'
).
offset
().
left
});
});
expect
(
$
(
'#subsection-2'
)).
not
.
toHaveClass
(
'collapsed'
);
expect
(
$
(
'#subsection-2'
)).
not
.
toHaveClass
(
'
is-
collapsed'
);
});
});
});
});
describe
(
"AJAX"
,
function
()
{
describe
(
"AJAX"
,
function
()
{
...
@@ -306,6 +328,10 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel
...
@@ -306,6 +328,10 @@ define(["js/utils/drag_and_drop", "js/views/feedback_notification", "js/spec_hel
expect
(
this
.
savingSpies
.
hide
).
toHaveBeenCalled
();
expect
(
this
.
savingSpies
.
hide
).
toHaveBeenCalled
();
this
.
clock
.
tick
(
1001
);
this
.
clock
.
tick
(
1001
);
expect
(
$
(
'#unit-1'
)).
not
.
toHaveClass
(
'was-dropped'
);
expect
(
$
(
'#unit-1'
)).
not
.
toHaveClass
(
'was-dropped'
);
// source
expect
(
$
(
'#subsection-1'
).
data
(
'refresh'
)).
toHaveBeenCalled
();
// target
expect
(
$
(
'#subsection-2'
).
data
(
'refresh'
)).
toHaveBeenCalled
();
});
});
});
});
});
});
...
...
cms/static/js/spec/views/pages/course_outline_spec.js
View file @
650bdc2f
...
@@ -179,7 +179,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
...
@@ -179,7 +179,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
create_sinon
.
expectJsonRequest
(
requests
,
'GET'
,
'/xblock/outline/mock-course'
);
create_sinon
.
expectJsonRequest
(
requests
,
'GET'
,
'/xblock/outline/mock-course'
);
create_sinon
.
respondWithJson
(
requests
,
mockSingleSectionCourseJSON
);
create_sinon
.
respondWithJson
(
requests
,
mockSingleSectionCourseJSON
);
expect
(
outlinePage
.
$
(
'.no-content'
)).
not
.
toExist
();
expect
(
outlinePage
.
$
(
'.no-content'
)).
not
.
toExist
();
expect
(
outlinePage
.
$
(
'.list-sections li'
).
data
(
'locator'
)).
toEqual
(
'mock-section'
);
expect
(
outlinePage
.
$
(
'.list-sections li
.outline-section
'
).
data
(
'locator'
)).
toEqual
(
'mock-section'
);
});
});
it
(
'can add a second section'
,
function
()
{
it
(
'can add a second section'
,
function
()
{
...
@@ -237,7 +237,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
...
@@ -237,7 +237,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
create_sinon
.
expectJsonRequest
(
requests
,
'GET'
,
'/xblock/outline/mock-course'
);
create_sinon
.
expectJsonRequest
(
requests
,
'GET'
,
'/xblock/outline/mock-course'
);
create_sinon
.
respondWithJson
(
requests
,
mockSingleSectionCourseJSON
);
create_sinon
.
respondWithJson
(
requests
,
mockSingleSectionCourseJSON
);
expect
(
outlinePage
.
$
(
'.no-content'
)).
not
.
toExist
();
expect
(
outlinePage
.
$
(
'.no-content'
)).
not
.
toExist
();
expect
(
outlinePage
.
$
(
'.list-sections li'
).
data
(
'locator'
)).
toEqual
(
'mock-section'
);
expect
(
outlinePage
.
$
(
'.list-sections li
.outline-section
'
).
data
(
'locator'
)).
toEqual
(
'mock-section'
);
});
});
it
(
'remains empty if an add fails'
,
function
()
{
it
(
'remains empty if an add fails'
,
function
()
{
...
@@ -303,7 +303,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
...
@@ -303,7 +303,7 @@ define(["jquery", "js/spec_helpers/create_sinon", "js/spec_helpers/view_helpers"
requestCount
=
requests
.
length
;
requestCount
=
requests
.
length
;
create_sinon
.
respondWithError
(
requests
);
create_sinon
.
respondWithError
(
requests
);
expect
(
requests
.
length
).
toBe
(
requestCount
);
// No additional requests should be made
expect
(
requests
.
length
).
toBe
(
requestCount
);
// No additional requests should be made
expect
(
outlinePage
.
$
(
'.list-sections li'
).
data
(
'locator'
)).
toEqual
(
'mock-section'
);
expect
(
outlinePage
.
$
(
'.list-sections li
.outline-section
'
).
data
(
'locator'
)).
toEqual
(
'mock-section'
);
});
});
it
(
'can add a subsection'
,
function
()
{
it
(
'can add a subsection'
,
function
()
{
...
...
cms/static/js/utils/drag_and_drop.js
View file @
650bdc2f
...
@@ -6,6 +6,7 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
...
@@ -6,6 +6,7 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
droppableClasses
:
'drop-target drop-target-prepend drop-target-before drop-target-after'
,
droppableClasses
:
'drop-target drop-target-prepend drop-target-before drop-target-after'
,
validDropClass
:
"valid-drop"
,
validDropClass
:
"valid-drop"
,
expandOnDropClass
:
"expand-on-drop"
,
expandOnDropClass
:
"expand-on-drop"
,
collapsedClass
:
"is-collapsed"
,
/*
/*
* Determine information about where to drop the currently dragged
* Determine information about where to drop the currently dragged
...
@@ -14,7 +15,7 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
...
@@ -14,7 +15,7 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
*/
*/
findDestination
:
function
(
ele
,
yChange
)
{
findDestination
:
function
(
ele
,
yChange
)
{
var
eleY
=
ele
.
offset
().
top
;
var
eleY
=
ele
.
offset
().
top
;
var
eleYEnd
=
eleY
+
ele
.
h
eight
();
var
eleYEnd
=
eleY
+
ele
.
outerH
eight
();
var
containers
=
$
(
ele
.
data
(
'droppable-class'
));
var
containers
=
$
(
ele
.
data
(
'droppable-class'
));
for
(
var
i
=
0
;
i
<
containers
.
length
;
i
++
)
{
for
(
var
i
=
0
;
i
<
containers
.
length
;
i
++
)
{
...
@@ -28,7 +29,7 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
...
@@ -28,7 +29,7 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
// element is on top of its parent list -- don't check the
// element is on top of its parent list -- don't check the
// position of the container
// position of the container
var
parentList
=
container
.
parents
(
ele
.
data
(
'parent-location-selector'
)).
first
();
var
parentList
=
container
.
parents
(
ele
.
data
(
'parent-location-selector'
)).
first
();
if
(
parentList
.
hasClass
(
'collapsed'
))
{
if
(
parentList
.
hasClass
(
this
.
collapsedClass
))
{
var
parentListTop
=
parentList
.
offset
().
top
;
var
parentListTop
=
parentList
.
offset
().
top
;
// To make it easier to drop subsections into collapsed sections (which have
// To make it easier to drop subsections into collapsed sections (which have
// a lot of visual padding around them), allow a fudge factor around the
// a lot of visual padding around them), allow a fudge factor around the
...
@@ -36,7 +37,7 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
...
@@ -36,7 +37,7 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
var
collapseFudge
=
10
;
var
collapseFudge
=
10
;
if
(
Math
.
abs
(
eleY
-
parentListTop
)
<
collapseFudge
||
if
(
Math
.
abs
(
eleY
-
parentListTop
)
<
collapseFudge
||
(
eleY
>
parentListTop
&&
(
eleY
>
parentListTop
&&
eleYEnd
-
collapseFudge
<=
parentListTop
+
parentList
.
h
eight
())
eleYEnd
-
collapseFudge
<=
parentListTop
+
parentList
.
outerH
eight
())
)
{
)
{
return
{
return
{
ele
:
container
,
ele
:
container
,
...
@@ -65,7 +66,7 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
...
@@ -65,7 +66,7 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
for
(
var
j
=
0
;
j
<
siblings
.
length
;
j
++
)
{
for
(
var
j
=
0
;
j
<
siblings
.
length
;
j
++
)
{
var
$sibling
=
$
(
siblings
[
j
]);
var
$sibling
=
$
(
siblings
[
j
]);
var
siblingY
=
$sibling
.
offset
().
top
;
var
siblingY
=
$sibling
.
offset
().
top
;
var
siblingHeight
=
$sibling
.
h
eight
();
var
siblingHeight
=
$sibling
.
outerH
eight
();
var
siblingYEnd
=
siblingY
+
siblingHeight
;
var
siblingYEnd
=
siblingY
+
siblingHeight
;
// Facilitate dropping into the beginning or end of a list
// Facilitate dropping into the beginning or end of a list
...
@@ -158,12 +159,16 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
...
@@ -158,12 +159,16 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
// The direction the drag is moving in (negative means up, positive down).
// The direction the drag is moving in (negative means up, positive down).
dragDirection
:
0
dragDirection
:
0
};
};
if
(
!
ele
.
hasClass
(
'collapsed'
))
{
if
(
!
ele
.
hasClass
(
this
.
collapsedClass
))
{
ele
.
addClass
(
'collapsed'
);
ele
.
addClass
(
this
.
collapsedClass
);
ele
.
find
(
'.expand-collapse'
).
first
().
addClass
(
'expand'
).
removeClass
(
'collapse'
);
ele
.
find
(
'.expand-collapse'
).
first
().
addClass
(
'expand'
).
removeClass
(
'collapse'
);
// onDragStart gets called again after the collapse, so we can't just store a variable in the dragState.
// onDragStart gets called again after the collapse, so we can't just store a variable in the dragState.
ele
.
addClass
(
this
.
expandOnDropClass
);
ele
.
addClass
(
this
.
expandOnDropClass
);
}
}
// We should remove this class name before start dragging to
// avoid performance issues.
ele
.
removeClass
(
'was-dragging'
);
},
},
onDragMove
:
function
(
draggie
,
event
,
pointer
)
{
onDragMove
:
function
(
draggie
,
event
,
pointer
)
{
...
@@ -251,41 +256,46 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
...
@@ -251,41 +256,46 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
},
},
pointerInBounds
:
function
(
pointer
,
ele
)
{
pointerInBounds
:
function
(
pointer
,
ele
)
{
return
pointer
.
clientX
>=
ele
.
offset
().
left
&&
pointer
.
clientX
<
ele
.
offset
().
left
+
ele
.
w
idth
();
return
pointer
.
clientX
>=
ele
.
offset
().
left
&&
pointer
.
clientX
<
ele
.
offset
().
left
+
ele
.
outerW
idth
();
},
},
expandElement
:
function
(
ele
)
{
expandElement
:
function
(
ele
)
{
ele
.
removeClass
(
'collapsed'
);
ele
.
removeClass
(
this
.
collapsedClass
);
ele
.
find
(
'.expand-collapse'
).
first
().
removeClass
(
'expand'
).
addClass
(
'collapse'
);
ele
.
find
(
'.expand-collapse'
).
first
().
removeClass
(
'expand'
).
addClass
(
'collapse'
);
},
},
/*
/*
* Find all parent-child changes and save them.
* Find all parent-child changes and save them.
*/
*/
handleReorder
:
function
(
ele
)
{
handleReorder
:
function
(
element
)
{
var
parentSelector
=
ele
.
data
(
'parent-location-selector'
);
var
parentSelector
=
element
.
data
(
'parent-location-selector'
),
var
childrenSelector
=
ele
.
data
(
'child-selector'
);
childrenSelector
=
element
.
data
(
'child-selector'
),
var
newParentEle
=
ele
.
parents
(
parentSelector
).
first
();
newParentEle
=
element
.
parents
(
parentSelector
).
first
(),
var
newParentLocator
=
newParentEle
.
data
(
'locator'
);
newParentLocator
=
newParentEle
.
data
(
'locator'
),
var
oldParentLocator
=
ele
.
data
(
'parent'
);
oldParentLocator
=
element
.
data
(
'parent'
),
oldParentEle
,
saving
;
// If the parent has changed, update the children of the old parent.
// If the parent has changed, update the children of the old parent.
if
(
newParentLocator
!==
oldParentLocator
)
{
if
(
newParentLocator
!==
oldParentLocator
)
{
// Find the old parent element.
// Find the old parent element.
var
oldParentEle
=
$
(
parentSelector
).
filter
(
function
()
{
oldParentEle
=
$
(
parentSelector
).
filter
(
function
()
{
return
$
(
this
).
data
(
'locator'
)
===
oldParentLocator
;
return
$
(
this
).
data
(
'locator'
)
===
oldParentLocator
;
});
});
this
.
saveItem
(
oldParentEle
,
childrenSelector
,
function
()
{
this
.
saveItem
(
oldParentEle
,
childrenSelector
,
function
()
{
ele
.
data
(
'parent'
,
newParentLocator
);
element
.
data
(
'parent'
,
newParentLocator
);
_
.
each
([
oldParentEle
,
newParentEle
],
function
(
element
)
{
var
refresh
=
element
.
data
(
'refresh'
);
if
(
_
.
isFunction
(
refresh
))
{
refresh
();
}
});
});
});
}
}
var
saving
=
new
NotificationView
.
Mini
({
saving
=
new
NotificationView
.
Mini
({
title
:
gettext
(
'Saving…'
)
title
:
gettext
(
'Saving…'
)
});
});
saving
.
show
();
saving
.
show
();
ele
.
addClass
(
'was-dropped'
);
ele
ment
.
addClass
(
'was-dropped'
);
// Timeout interval has to match what is in the CSS.
// Timeout interval has to match what is in the CSS.
setTimeout
(
function
()
{
setTimeout
(
function
()
{
ele
.
removeClass
(
'was-dropped'
);
ele
ment
.
removeClass
(
'was-dropped'
);
},
1000
);
},
1000
);
this
.
saveItem
(
newParentEle
,
childrenSelector
,
function
()
{
this
.
saveItem
(
newParentEle
,
childrenSelector
,
function
()
{
saving
.
hide
();
saving
.
hide
();
...
@@ -318,27 +328,43 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
...
@@ -318,27 +328,43 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
},
},
/*
/*
* Make `type` draggable using `handleClass`, able to be dropped
* Make DOM element with class `type` draggable using `handleClass`, able to be dropped
* into `droppableClass`, and with parent type
* into `droppableClass`, and with parent type `parentLocationSelector`.
* `parentLocationSelector`.
* @param {DOM element, jQuery element} element
* @param {Object} options The list of options. Possible options:
* `type` - class name of the element.
* `handleClass` - specifies on what element the drag interaction starts.
* `droppableClass` - specifies on what elements draggable element can be dropped.
* `parentLocationSelector` - class name of a parent element with data-locator.
* `refresh` - method that will be called after dragging to refresh
* views of the target and source xblocks.
*/
*/
makeDraggable
:
function
(
type
,
handleClass
,
droppableClass
,
parentLocationSelector
)
{
makeDraggable
:
function
(
element
,
options
)
{
_
.
each
(
var
draggable
;
$
(
type
),
options
=
_
.
defaults
({
function
(
ele
)
{
type
:
null
,
// Remember data necessary to reconstruct the parent-child relationships
handleClass
:
null
,
$
(
ele
).
data
(
'droppable-class'
,
droppableClass
);
droppableClass
:
null
,
$
(
ele
).
data
(
'parent-location-selector'
,
parentLocationSelector
);
parentLocationSelector
:
null
,
$
(
ele
).
data
(
'child-selector'
,
type
);
refresh
:
null
var
draggable
=
new
Draggabilly
(
ele
,
{
},
options
);
handle
:
handleClass
,
if
(
$
(
element
).
data
(
'droppable-class'
)
!==
options
.
droppableClass
)
{
$
(
element
).
data
({
'droppable-class'
:
options
.
droppableClass
,
'parent-location-selector'
:
options
.
parentLocationSelector
,
'child-selector'
:
options
.
type
,
'refresh'
:
options
.
refresh
});
draggable
=
new
Draggabilly
(
element
,
{
handle
:
options
.
handleClass
,
containment
:
'.wrapper-dnd'
containment
:
'.wrapper-dnd'
});
});
draggable
.
on
(
'dragStart'
,
_
.
bind
(
contentDragger
.
onDragStart
,
contentDragger
));
draggable
.
on
(
'dragStart'
,
_
.
bind
(
contentDragger
.
onDragStart
,
contentDragger
));
draggable
.
on
(
'dragMove'
,
_
.
bind
(
contentDragger
.
onDragMove
,
contentDragger
));
draggable
.
on
(
'dragMove'
,
_
.
bind
(
contentDragger
.
onDragMove
,
contentDragger
));
draggable
.
on
(
'dragEnd'
,
_
.
bind
(
contentDragger
.
onDragEnd
,
contentDragger
));
draggable
.
on
(
'dragEnd'
,
_
.
bind
(
contentDragger
.
onDragEnd
,
contentDragger
));
}
}
);
}
}
};
};
...
...
cms/static/js/views/course_outline.js
View file @
650bdc2f
...
@@ -9,15 +9,20 @@
...
@@ -9,15 +9,20 @@
* - adding units will automatically redirect to the unit page rather than showing them inline
* - adding units will automatically redirect to the unit page rather than showing them inline
*/
*/
define
([
"jquery"
,
"underscore"
,
"js/views/xblock_outline"
,
"js/views/utils/view_utils"
,
define
([
"jquery"
,
"underscore"
,
"js/views/xblock_outline"
,
"js/views/utils/view_utils"
,
"js/models/xblock_outline_info"
,
"js/models/xblock_outline_info"
,
"js/views/modals/edit_outline_item"
,
"js/utils/drag_and_drop"
],
"js/views/modals/edit_outline_item"
],
function
(
$
,
_
,
XBlockOutlineView
,
ViewUtils
,
XBlockOutlineInfo
,
EditSectionXBlockModal
,
ContentDragger
)
{
function
(
$
,
_
,
XBlockOutlineView
,
ViewUtils
,
XBlockOutlineInfo
,
EditSectionXBlockModal
)
{
var
CourseOutlineView
=
XBlockOutlineView
.
extend
({
var
CourseOutlineView
=
XBlockOutlineView
.
extend
({
// takes XBlockOutlineInfo as a model
// takes XBlockOutlineInfo as a model
templateName
:
'course-outline'
,
templateName
:
'course-outline'
,
render
:
function
()
{
var
renderResult
=
XBlockOutlineView
.
prototype
.
render
.
call
(
this
);
this
.
makeContentDraggable
(
this
.
el
);
return
renderResult
;
},
shouldExpandChildren
:
function
()
{
shouldExpandChildren
:
function
()
{
// Expand the children if this xblock's locator is in the initially expanded state
// Expand the children if this xblock's locator is in the initially expanded state
if
(
this
.
initialState
&&
_
.
contains
(
this
.
initialState
.
expanded_locators
,
this
.
model
.
id
))
{
if
(
this
.
initialState
&&
_
.
contains
(
this
.
initialState
.
expanded_locators
,
this
.
model
.
id
))
{
...
@@ -154,6 +159,36 @@ define(["jquery", "underscore", "js/views/xblock_outline", "js/views/utils/view_
...
@@ -154,6 +159,36 @@ define(["jquery", "underscore", "js/views/xblock_outline", "js/views/utils/view_
event
.
preventDefault
();
event
.
preventDefault
();
this
.
editXBlock
();
this
.
editXBlock
();
}.
bind
(
this
));
}.
bind
(
this
));
},
makeContentDraggable
:
function
(
element
)
{
if
(
$
(
element
).
hasClass
(
"outline-section"
))
{
ContentDragger
.
makeDraggable
(
element
,
{
type
:
'.outline-section'
,
handleClass
:
'.section-drag-handle'
,
droppableClass
:
'ol.list-sections'
,
parentLocationSelector
:
'article.outline'
,
refresh
:
this
.
refresh
.
bind
(
this
)
});
}
else
if
(
$
(
element
).
hasClass
(
"outline-subsection"
))
{
ContentDragger
.
makeDraggable
(
element
,
{
type
:
'.outline-subsection'
,
handleClass
:
'.subsection-drag-handle'
,
droppableClass
:
'ol.list-subsections'
,
parentLocationSelector
:
'li.outline-section'
,
refresh
:
this
.
refresh
.
bind
(
this
)
});
}
else
if
(
$
(
element
).
hasClass
(
"outline-unit"
))
{
ContentDragger
.
makeDraggable
(
element
,
{
type
:
'.outline-unit'
,
handleClass
:
'.unit-drag-handle'
,
droppableClass
:
'ol.list-units'
,
parentLocationSelector
:
'li.outline-subsection'
,
refresh
:
this
.
refresh
.
bind
(
this
)
});
}
}
}
});
});
...
...
cms/static/js/views/overview.js
View file @
650bdc2f
define
([
"domReady"
,
"jquery"
,
"jquery.ui"
,
"underscore"
,
"gettext"
,
"js/views/feedback_notification"
,
"js/utils/drag_and_drop"
,
define
([
"domReady"
,
"jquery"
,
"jquery.ui"
,
"underscore"
,
"gettext"
,
"js/views/feedback_notification"
,
"js/utils/cancel_on_escape"
,
"js/utils/date_utils"
,
"js/utils/module"
],
"js/utils/cancel_on_escape"
,
"js/utils/date_utils"
,
"js/utils/module"
],
function
(
domReady
,
$
,
ui
,
_
,
gettext
,
NotificationView
,
C
ontentDragger
,
C
ancelOnEscape
,
function
(
domReady
,
$
,
ui
,
_
,
gettext
,
NotificationView
,
CancelOnEscape
,
DateUtils
,
ModuleUtils
)
{
DateUtils
,
ModuleUtils
)
{
var
modalSelector
=
'.edit-section-publish-settings'
;
var
modalSelector
=
'.edit-section-publish-settings'
;
...
@@ -39,7 +39,7 @@ define(["domReady", "jquery", "jquery.ui", "underscore", "gettext", "js/views/fe
...
@@ -39,7 +39,7 @@ define(["domReady", "jquery", "jquery.ui", "underscore", "gettext", "js/views/fe
var
closeModalNew
=
function
(
e
)
{
var
closeModalNew
=
function
(
e
)
{
if
(
e
)
{
if
(
e
)
{
e
.
preventDefault
();
e
.
preventDefault
();
}
;
}
$
(
'body'
).
removeClass
(
'modal-window-is-shown'
);
$
(
'body'
).
removeClass
(
'modal-window-is-shown'
);
$
(
'.edit-section-publish-settings'
).
removeClass
(
'is-shown'
);
$
(
'.edit-section-publish-settings'
).
removeClass
(
'is-shown'
);
};
};
...
@@ -230,27 +230,6 @@ define(["domReady", "jquery", "jquery.ui", "underscore", "gettext", "js/views/fe
...
@@ -230,27 +230,6 @@ define(["domReady", "jquery", "jquery.ui", "underscore", "gettext", "js/views/fe
$
(
'.new-courseware-section-button'
).
bind
(
'click'
,
addNewSection
);
$
(
'.new-courseware-section-button'
).
bind
(
'click'
,
addNewSection
);
$
(
'.new-subsection-item'
).
bind
(
'click'
,
addNewSubsection
);
$
(
'.new-subsection-item'
).
bind
(
'click'
,
addNewSubsection
);
// Section
ContentDragger
.
makeDraggable
(
'.courseware-section'
,
'.section-drag-handle'
,
'.courseware-overview'
,
'article.courseware-overview'
);
// Subsection
ContentDragger
.
makeDraggable
(
'.id-holder'
,
'.subsection-drag-handle'
,
'.subsection-list > ol'
,
'.courseware-section'
);
// Unit
ContentDragger
.
makeDraggable
(
'.unit'
,
'.unit-drag-handle'
,
'ol.sortable-unit-list'
,
'li.courseware-subsection, article.subsection-body'
);
});
});
return
{
return
{
...
...
cms/static/sass/elements/_controls.scss
View file @
650bdc2f
...
@@ -394,6 +394,9 @@
...
@@ -394,6 +394,9 @@
box-shadow
:
0
1px
2px
0
$blue-t2
;
box-shadow
:
0
1px
2px
0
$blue-t2
;
}
}
}
}
.was-dragging
{
@include
transition
(
transform
$tmg-f2
ease-in-out
0
);
}
// UI: drag state - was dragging
// UI: drag state - was dragging
.was-dragging
{
.was-dragging
{
...
...
cms/static/sass/views/_outline.scss
View file @
650bdc2f
...
@@ -224,6 +224,10 @@
...
@@ -224,6 +224,10 @@
color
:
$blue
;
color
:
$blue
;
}
}
}
}
&
.is-dragging
{
@include
transition-property
(
none
);
}
}
}
// item: title
// item: title
...
...
cms/templates/js/course-outline.underscore
View file @
650bdc2f
...
@@ -35,6 +35,8 @@ if (statusType === 'warning') {
...
@@ -35,6 +35,8 @@ if (statusType === 'warning') {
<li class="outline-item outline-<%= xblockType %> <%= visibilityClass %> is-draggable <%= includesChildren ? 'is-collapsible' : '' %> <%= isCollapsed ? 'is-collapsed' : '' %>"
<li class="outline-item outline-<%= xblockType %> <%= visibilityClass %> is-draggable <%= includesChildren ? 'is-collapsible' : '' %> <%= isCollapsed ? 'is-collapsed' : '' %>"
data-parent="<%= parentInfo.get('id') %>" data-locator="<%= xblockInfo.get('id') %>">
data-parent="<%= parentInfo.get('id') %>" data-locator="<%= xblockInfo.get('id') %>">
<span class="draggable-drop-indicator draggable-drop-indicator-before"><i class="icon-caret-right"></i></span>
<div class="<%= xblockType %>-header">
<div class="<%= xblockType %>-header">
<% if (includesChildren) { %>
<% if (includesChildren) { %>
<h3 class="<%= xblockType %>-header-details expand-collapse <%= isCollapsed ? 'expand' : 'collapse' %> ui-toggle-expansion" title="<%= gettext('Collapse/Expand this Checklist') %>">
<h3 class="<%= xblockType %>-header-details expand-collapse <%= isCollapsed ? 'expand' : 'collapse' %> ui-toggle-expansion" title="<%= gettext('Collapse/Expand this Checklist') %>">
...
@@ -69,6 +71,12 @@ if (statusType === 'warning') {
...
@@ -69,6 +71,12 @@ if (statusType === 'warning') {
<span class="sr action-button-text"><%= gettext('Delete') %></span>
<span class="sr action-button-text"><%= gettext('Delete') %></span>
</a>
</a>
</li>
</li>
<li class="action-item action-drag">
<span data-tooltip="<%= gettext('Drag to reorder') %>"
class="drag-handle <%= xblockType %>-drag-handle action">
<span class="sr"><%= gettext('Drag to reorder') %></span>
</span>
</li>
</ul>
</ul>
</div>
</div>
</div>
</div>
...
@@ -125,10 +133,14 @@ if (statusType === 'warning') {
...
@@ -125,10 +133,14 @@ if (statusType === 'warning') {
</a>
</a>
</p>
</p>
</div>
</div>
<% } else { %>
<% } else
if (category !== 'vertical')
{ %>
<div class="outline-content <%= xblockType %>-content">
<div class="outline-content <%= xblockType %>-content">
<ol class="<%= typeListClass %> is-sortable">
<ol class="<%= typeListClass %> is-sortable">
<li class="ui-splint ui-splint-indicator">
<span class="draggable-drop-indicator draggable-drop-indicator-initial"><i class="icon-caret-right"></i></span>
</li>
</ol>
</ol>
<% if (childType) { %>
<% if (childType) { %>
<div class="add-<%= childType %> add-item">
<div class="add-<%= childType %> add-item">
<a href="#" class="button button-new" data-category="<%= childCategory %>"
<a href="#" class="button button-new" data-category="<%= childCategory %>"
...
@@ -141,5 +153,6 @@ if (statusType === 'warning') {
...
@@ -141,5 +153,6 @@ if (statusType === 'warning') {
<% } %>
<% } %>
<% if (parentInfo) { %>
<% if (parentInfo) { %>
<span class="draggable-drop-indicator draggable-drop-indicator-after"><i class="icon-caret-right"></i></span>
</li>
</li>
<% } %>
<% } %>
cms/templates/js/xblock-outline.underscore
View file @
650bdc2f
...
@@ -29,11 +29,6 @@
...
@@ -29,11 +29,6 @@
<span class="sr"><%= gettext('Delete') %></span>
<span class="sr"><%= gettext('Delete') %></span>
</a>
</a>
</li>
</li>
<li class="actions-item drag">
<span data-tooltip="<%= gettext('Drag to reorder') %>" class="drag-handle">
<span class="sr"><%= gettext('Drag to reorder') %></span>
</span>
</li>
</ul>
</ul>
</div>
</div>
</div>
</div>
...
...
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