Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
xblock-drag-and-drop-v2
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
OpenEdx
xblock-drag-and-drop-v2
Commits
82dad4ae
Commit
82dad4ae
authored
Jan 28, 2016
by
Jonathan Piacenti
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix unique IDs for placed item descriptions. Fix drop zone role.
parent
3066fdbb
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
272 additions
and
270 deletions
+272
-270
drag_and_drop_v2/drag_and_drop_v2.py
+0
-1
drag_and_drop_v2/public/js/drag_and_drop.js
+271
-0
drag_and_drop_v2/public/js/view.js
+0
-268
tests/integration/test_interaction.py
+1
-1
No files found.
drag_and_drop_v2/drag_and_drop_v2.py
View file @
82dad4ae
...
@@ -126,7 +126,6 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
...
@@ -126,7 +126,6 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
'public/js/vendor/jquery-ui-touch-punch-0.2.3.min.js'
,
# Makes it work on touch devices
'public/js/vendor/jquery-ui-touch-punch-0.2.3.min.js'
,
# Makes it work on touch devices
'public/js/vendor/virtual-dom-1.3.0.min.js'
,
'public/js/vendor/virtual-dom-1.3.0.min.js'
,
'public/js/drag_and_drop.js'
,
'public/js/drag_and_drop.js'
,
'public/js/view.js'
,
)
)
for
css_url
in
css_urls
:
for
css_url
in
css_urls
:
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
css_url
))
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
css_url
))
...
...
drag_and_drop_v2/public/js/drag_and_drop.js
View file @
82dad4ae
function
DragNDropTemplates
(
url_name
)
{
"use strict"
;
var
h
=
virtualDom
.
h
;
// Set up a mock for gettext if it isn't available in the client runtime:
if
(
!
window
.
gettext
)
{
window
.
gettext
=
function
gettext_stub
(
string
)
{
return
string
;
};
}
var
FocusHook
=
function
()
{
if
(
!
(
this
instanceof
FocusHook
))
{
return
new
FocusHook
();
}
};
FocusHook
.
prototype
.
hook
=
function
(
node
,
prop
,
prev
)
{
setTimeout
(
function
()
{
if
(
document
.
activeElement
!==
node
)
{
node
.
focus
();
}
},
0
);
};
var
itemSpinnerTemplate
=
function
(
xhr_active
)
{
if
(
!
xhr_active
)
{
return
null
;
}
return
(
h
(
"div.spinner-wrapper"
,
[
h
(
"i.fa.fa-spin.fa-spinner"
)
]
));
};
var
renderCollection
=
function
(
template
,
collection
,
ctx
)
{
return
collection
.
map
(
function
(
item
)
{
return
template
(
item
,
ctx
);
});
};
var
itemInputTemplate
=
function
(
input
)
{
if
(
!
input
)
{
return
null
;
}
var
focus_hook
=
input
.
has_value
?
undefined
:
FocusHook
();
return
(
h
(
'div.numerical-input'
,
{
className
:
input
.
class_name
,
style
:
{
display
:
input
.
is_visible
?
'block'
:
'none'
}},
[
h
(
'input.input'
,
{
type
:
'text'
,
value
:
input
.
value
,
disabled
:
input
.
has_value
,
focusHook
:
focus_hook
}),
itemSpinnerTemplate
(
input
.
xhr_active
),
h
(
'button.submit-input'
,
{
disabled
:
input
.
has_value
},
gettext
(
'ok'
))
])
);
};
var
itemTemplate
=
function
(
item
,
ctx
)
{
// Define properties
var
className
=
(
item
.
class_name
)
?
item
.
class_name
:
""
;
if
(
item
.
has_image
)
{
className
+=
" "
+
"option-with-image"
;
}
if
(
item
.
widthPercent
)
{
className
+=
" specified-width"
;
// The author has specified a width for this item.
}
var
attributes
=
{
'role'
:
'button'
,
'draggable'
:
!
item
.
drag_disabled
,
'aria-grabbed'
:
item
.
grabbed
,
'data-value'
:
item
.
value
,
'data-drag-disabled'
:
item
.
drag_disabled
};
var
style
=
{};
if
(
item
.
background_color
)
{
style
[
'background-color'
]
=
item
.
background_color
;
}
if
(
item
.
color
)
{
style
.
color
=
item
.
color
;
// Ensure contrast between outline-color and background color
// matches contrast between text color and background color:
style
[
'outline-color'
]
=
item
.
color
;
}
if
(
item
.
is_placed
)
{
style
.
left
=
item
.
x_percent
+
"%"
;
style
.
top
=
item
.
y_percent
+
"%"
;
if
(
item
.
widthPercent
)
{
style
.
width
=
item
.
widthPercent
+
"%"
;
style
.
maxWidth
=
item
.
widthPercent
+
"%"
;
// default maxWidth is ~33%
}
else
if
(
item
.
imgNaturalWidth
)
{
style
.
width
=
(
item
.
imgNaturalWidth
+
22
)
+
"px"
;
// 22px is for 10px padding + 1px border each side
// ^ Hack to detect image width at runtime and make webkit consistent with Firefox
}
}
else
{
// If an item has not been placed it must be possible to move focus to it using the keyboard:
attributes
.
tabindex
=
0
;
if
(
item
.
widthPercent
)
{
// The item bank container is often wider than the background image, and the
// widthPercent is specified relative to the background image so we have to
// convert it to pixels. But if the browser window / mobile screen is not as
// wide as the image, then the background image will be scaled down and this
// pixel value would be too large, so we also specify it as a max-width
// percentage.
style
.
width
=
(
item
.
widthPercent
/
100
*
ctx
.
bg_image_width
)
+
"px"
;
style
.
maxWidth
=
item
.
widthPercent
+
"%"
;
}
}
// Define children
var
children
=
[
itemSpinnerTemplate
(
item
.
xhr_active
),
itemInputTemplate
(
item
.
input
)
];
var
item_content_html
=
item
.
displayName
;
if
(
item
.
imageURL
)
{
item_content_html
=
'<img src="'
+
item
.
imageURL
+
'" alt="'
+
item
.
imageDescription
+
'" />'
;
}
var
item_content
=
h
(
'div'
,
{
innerHTML
:
item_content_html
,
className
:
"item-content"
});
if
(
item
.
is_placed
)
{
// Insert information about zone in which this item has been placed
var
item_description_id
=
url_name
+
'-item-'
+
item
.
value
+
'-description'
;
item_content
.
properties
.
attributes
=
{
'aria-describedby'
:
item_description_id
};
var
item_description
=
h
(
'div'
,
{
id
:
item_description_id
,
className
:
'sr'
},
gettext
(
'Correctly placed in: '
)
+
item
.
zone
);
children
.
splice
(
1
,
0
,
item_description
);
}
children
.
splice
(
1
,
0
,
item_content
);
return
(
h
(
'div.option'
,
{
// Unique key for virtual dom change tracking. Key must be different for
// Placed vs Unplaced, or weird bugs can occur.
key
:
item
.
value
+
(
item
.
is_placed
?
"-p"
:
"-u"
),
className
:
className
,
attributes
:
attributes
,
style
:
style
},
children
)
);
};
var
zoneTemplate
=
function
(
zone
,
ctx
)
{
var
className
=
ctx
.
display_zone_labels
?
'zone-name'
:
'zone-name sr'
;
var
selector
=
ctx
.
display_zone_borders
?
'div.zone.zone-with-borders'
:
'div.zone'
;
return
(
h
(
selector
,
{
id
:
zone
.
id
,
attributes
:
{
'tabindex'
:
0
,
'dropzone'
:
'move'
,
'aria-dropeffect'
:
'move'
,
'data-zone'
:
zone
.
title
,
'role'
:
'button'
,
},
style
:
{
top
:
zone
.
y_percent
+
'%'
,
left
:
zone
.
x_percent
+
"%"
,
width
:
zone
.
width_percent
+
'%'
,
height
:
zone
.
height_percent
+
"%"
,
}
},
[
h
(
'p'
,
{
className
:
className
},
zone
.
title
),
h
(
'p'
,
{
className
:
'zone-description sr'
},
zone
.
description
)
]
)
);
};
var
feedbackTemplate
=
function
(
ctx
)
{
var
feedback_display
=
ctx
.
feedback_html
?
'block'
:
'none'
;
var
reset_button_display
=
ctx
.
display_reset_button
?
'block'
:
'none'
;
var
properties
=
{
attributes
:
{
'aria-live'
:
'polite'
}
};
return
(
h
(
'section.feedback'
,
properties
,
[
h
(
'button.reset-button.unbutton.link-button'
,
{
style
:
{
display
:
reset_button_display
},
attributes
:
{
tabindex
:
0
},
'aria-live'
:
'off'
},
gettext
(
'Reset problem'
)
),
h
(
'h3.title1'
,
{
style
:
{
display
:
feedback_display
}
},
gettext
(
'Feedback'
)),
h
(
'p.message'
,
{
style
:
{
display
:
feedback_display
},
innerHTML
:
ctx
.
feedback_html
})
])
);
};
var
keyboardHelpTemplate
=
function
(
ctx
)
{
var
dialog_attributes
=
{
role
:
'dialog'
,
'aria-labelledby'
:
'modal-window-title'
};
var
dialog_style
=
{};
return
(
h
(
'section.keyboard-help'
,
[
h
(
'button.keyboard-help-button.unbutton.link-button'
,
{
attributes
:
{
tabindex
:
0
}
},
gettext
(
'Keyboard Help'
)),
h
(
'div.keyboard-help-dialog'
,
[
h
(
'div.modal-window-overlay'
),
h
(
'div.modal-window'
,
{
attributes
:
dialog_attributes
,
style
:
dialog_style
},
[
h
(
'div.modal-header'
,
[
h
(
'h2.modal-window-title'
,
gettext
(
'Keyboard Help'
))
]),
h
(
'div.modal-content'
,
[
h
(
'p'
,
gettext
(
'You can complete this problem using only your keyboard.'
)),
h
(
'ul'
,
[
h
(
'li'
,
gettext
(
'Use "Tab" and "Shift-Tab" to navigate between items and zones.'
)),
h
(
'li'
,
gettext
(
'Press "Enter", "Space", "Ctrl-m", or "⌘-m" on an item to select it for dropping, then navigate to the zone you want to drop it on.'
)),
h
(
'li'
,
gettext
(
'Press "Enter", "Space", "Ctrl-m", or "⌘-m" to drop the item on the current zone.'
)),
h
(
'li'
,
gettext
(
'Press "Esc" if you want to cancel the drop operation (for example, to select a different item).'
)),
])
]),
h
(
'div.modal-actions'
,
[
h
(
'button.modal-dismiss-button'
,
gettext
(
"OK"
))
])
])
])
])
);
};
var
mainTemplate
=
function
(
ctx
)
{
var
problemTitle
=
ctx
.
show_title
?
h
(
'h2.problem-title'
,
{
innerHTML
:
ctx
.
title_html
})
:
null
;
var
problemHeader
=
ctx
.
show_problem_header
?
h
(
'h3.title1'
,
gettext
(
'Problem'
))
:
null
;
var
popupSelector
=
'div.popup'
;
if
(
ctx
.
popup_html
&&
!
ctx
.
last_action_correct
)
{
popupSelector
+=
'.popup-incorrect'
;
}
var
is_item_placed
=
function
(
i
)
{
return
i
.
is_placed
;
};
var
items_placed
=
$
.
grep
(
ctx
.
items
,
is_item_placed
);
var
items_in_bank
=
$
.
grep
(
ctx
.
items
,
is_item_placed
,
true
);
return
(
h
(
'section.themed-xblock.xblock--drag-and-drop'
,
[
problemTitle
,
h
(
'section.problem'
,
[
problemHeader
,
h
(
'p'
,
{
innerHTML
:
ctx
.
problem_html
}),
]),
h
(
'section.drag-container'
,
{
attributes
:
{
role
:
'application'
}
},
[
h
(
'div.item-bank'
,
renderCollection
(
itemTemplate
,
items_in_bank
,
ctx
)
),
h
(
'div.target'
,
[
h
(
popupSelector
,
{
attributes
:
{
'aria-live'
:
'polite'
,
'tabindex'
:
0
},
style
:
{
display
:
ctx
.
popup_html
?
'block'
:
'none'
},
},
[
h
(
'button.unbutton.close.icon-remove-sign.fa-times-circle'
,
[
h
(
'div'
,
{
attributes
:
{
'class'
:
'sr'
}},
gettext
(
"Close"
))
]),
h
(
'p.popup-content'
,
{
innerHTML
:
ctx
.
popup_html
}),
]
),
h
(
'div.target-img-wrapper'
,
[
h
(
'img.target-img'
,
{
src
:
ctx
.
target_img_src
,
alt
:
ctx
.
target_img_description
}),
]),
renderCollection
(
zoneTemplate
,
ctx
.
zones
,
ctx
),
renderCollection
(
itemTemplate
,
items_placed
,
ctx
),
]),
]),
keyboardHelpTemplate
(
ctx
),
feedbackTemplate
(
ctx
),
])
);
};
DragAndDropBlock
.
renderView
=
mainTemplate
;
}
function
DragAndDropBlock
(
runtime
,
element
,
configuration
)
{
function
DragAndDropBlock
(
runtime
,
element
,
configuration
)
{
"use strict"
;
"use strict"
;
DragNDropTemplates
(
configuration
.
url_name
);
// Set up a mock for gettext if it isn't available in the client runtime:
// Set up a mock for gettext if it isn't available in the client runtime:
if
(
!
window
.
gettext
)
{
window
.
gettext
=
function
gettext_stub
(
string
)
{
return
string
;
};
}
if
(
!
window
.
gettext
)
{
window
.
gettext
=
function
gettext_stub
(
string
)
{
return
string
;
};
}
...
...
drag_and_drop_v2/public/js/view.js
deleted
100644 → 0
View file @
3066fdbb
(
function
(
h
)
{
"use strict"
;
// Set up a mock for gettext if it isn't available in the client runtime:
if
(
!
window
.
gettext
)
{
window
.
gettext
=
function
gettext_stub
(
string
)
{
return
string
;
};
}
var
FocusHook
=
function
()
{
if
(
!
(
this
instanceof
FocusHook
))
{
return
new
FocusHook
();
}
};
FocusHook
.
prototype
.
hook
=
function
(
node
,
prop
,
prev
)
{
setTimeout
(
function
()
{
if
(
document
.
activeElement
!==
node
)
{
node
.
focus
();
}
},
0
);
};
var
itemSpinnerTemplate
=
function
(
xhr_active
)
{
if
(
!
xhr_active
)
{
return
null
;
}
return
(
h
(
"div.spinner-wrapper"
,
[
h
(
"i.fa.fa-spin.fa-spinner"
)
]
));
};
var
renderCollection
=
function
(
template
,
collection
,
ctx
)
{
return
collection
.
map
(
function
(
item
)
{
return
template
(
item
,
ctx
);
});
};
var
itemInputTemplate
=
function
(
input
)
{
if
(
!
input
)
{
return
null
;
}
var
focus_hook
=
input
.
has_value
?
undefined
:
FocusHook
();
return
(
h
(
'div.numerical-input'
,
{
className
:
input
.
class_name
,
style
:
{
display
:
input
.
is_visible
?
'block'
:
'none'
}},
[
h
(
'input.input'
,
{
type
:
'text'
,
value
:
input
.
value
,
disabled
:
input
.
has_value
,
focusHook
:
focus_hook
}),
itemSpinnerTemplate
(
input
.
xhr_active
),
h
(
'button.submit-input'
,
{
disabled
:
input
.
has_value
},
gettext
(
'ok'
))
])
);
};
var
itemTemplate
=
function
(
item
,
ctx
)
{
// Define properties
var
className
=
(
item
.
class_name
)
?
item
.
class_name
:
""
;
if
(
item
.
has_image
)
{
className
+=
" "
+
"option-with-image"
;
}
if
(
item
.
widthPercent
)
{
className
+=
" specified-width"
;
// The author has specified a width for this item.
}
var
attributes
=
{
'role'
:
'button'
,
'draggable'
:
!
item
.
drag_disabled
,
'aria-grabbed'
:
item
.
grabbed
,
'data-value'
:
item
.
value
,
'data-drag-disabled'
:
item
.
drag_disabled
};
var
style
=
{};
if
(
item
.
background_color
)
{
style
[
'background-color'
]
=
item
.
background_color
;
}
if
(
item
.
color
)
{
style
.
color
=
item
.
color
;
// Ensure contrast between outline-color and background color
// matches contrast between text color and background color:
style
[
'outline-color'
]
=
item
.
color
;
}
if
(
item
.
is_placed
)
{
style
.
left
=
item
.
x_percent
+
"%"
;
style
.
top
=
item
.
y_percent
+
"%"
;
if
(
item
.
widthPercent
)
{
style
.
width
=
item
.
widthPercent
+
"%"
;
style
.
maxWidth
=
item
.
widthPercent
+
"%"
;
// default maxWidth is ~33%
}
else
if
(
item
.
imgNaturalWidth
)
{
style
.
width
=
(
item
.
imgNaturalWidth
+
22
)
+
"px"
;
// 22px is for 10px padding + 1px border each side
// ^ Hack to detect image width at runtime and make webkit consistent with Firefox
}
}
else
{
// If an item has not been placed it must be possible to move focus to it using the keyboard:
attributes
.
tabindex
=
0
;
if
(
item
.
widthPercent
)
{
// The item bank container is often wider than the background image, and the
// widthPercent is specified relative to the background image so we have to
// convert it to pixels. But if the browser window / mobile screen is not as
// wide as the image, then the background image will be scaled down and this
// pixel value would be too large, so we also specify it as a max-width
// percentage.
style
.
width
=
(
item
.
widthPercent
/
100
*
ctx
.
bg_image_width
)
+
"px"
;
style
.
maxWidth
=
item
.
widthPercent
+
"%"
;
}
}
// Define children
var
children
=
[
itemSpinnerTemplate
(
item
.
xhr_active
),
itemInputTemplate
(
item
.
input
)
];
var
item_content_html
=
item
.
displayName
;
if
(
item
.
imageURL
)
{
item_content_html
=
'<img src="'
+
item
.
imageURL
+
'" alt="'
+
item
.
imageDescription
+
'" />'
;
}
var
item_content
=
h
(
'div'
,
{
innerHTML
:
item_content_html
,
className
:
"item-content"
});
if
(
item
.
is_placed
)
{
// Insert information about zone in which this item has been placed
var
item_description_id
=
'item-'
+
item
.
value
+
'-description'
;
item_content
.
properties
.
attributes
=
{
'aria-describedby'
:
item_description_id
};
var
item_description
=
h
(
'div'
,
{
id
:
item_description_id
,
className
:
'sr'
},
gettext
(
'Correctly placed in: '
)
+
item
.
zone
);
children
.
splice
(
1
,
0
,
item_description
);
}
children
.
splice
(
1
,
0
,
item_content
);
return
(
h
(
'div.option'
,
{
// Unique key for virtual dom change tracking. Key must be different for
// Placed vs Unplaced, or weird bugs can occur.
key
:
item
.
value
+
(
item
.
is_placed
?
"-p"
:
"-u"
),
className
:
className
,
attributes
:
attributes
,
style
:
style
},
children
)
);
};
var
zoneTemplate
=
function
(
zone
,
ctx
)
{
var
className
=
ctx
.
display_zone_labels
?
'zone-name'
:
'zone-name sr'
;
var
selector
=
ctx
.
display_zone_borders
?
'div.zone.zone-with-borders'
:
'div.zone'
;
return
(
h
(
selector
,
{
id
:
zone
.
id
,
attributes
:
{
'tabindex'
:
0
,
'dropzone'
:
'move'
,
'aria-dropeffect'
:
'move'
,
'data-zone'
:
zone
.
title
},
style
:
{
top
:
zone
.
y_percent
+
'%'
,
left
:
zone
.
x_percent
+
"%"
,
width
:
zone
.
width_percent
+
'%'
,
height
:
zone
.
height_percent
+
"%"
,
}
},
[
h
(
'p'
,
{
className
:
className
},
zone
.
title
),
h
(
'p'
,
{
className
:
'zone-description sr'
},
zone
.
description
)
]
)
);
};
var
feedbackTemplate
=
function
(
ctx
)
{
var
feedback_display
=
ctx
.
feedback_html
?
'block'
:
'none'
;
var
reset_button_display
=
ctx
.
display_reset_button
?
'block'
:
'none'
;
var
properties
=
{
attributes
:
{
'aria-live'
:
'polite'
}
};
return
(
h
(
'section.feedback'
,
properties
,
[
h
(
'button.reset-button.unbutton.link-button'
,
{
style
:
{
display
:
reset_button_display
},
attributes
:
{
tabindex
:
0
},
'aria-live'
:
'off'
},
gettext
(
'Reset problem'
)
),
h
(
'h3.title1'
,
{
style
:
{
display
:
feedback_display
}
},
gettext
(
'Feedback'
)),
h
(
'p.message'
,
{
style
:
{
display
:
feedback_display
},
innerHTML
:
ctx
.
feedback_html
})
])
);
};
var
keyboardHelpTemplate
=
function
(
ctx
)
{
var
dialog_attributes
=
{
role
:
'dialog'
,
'aria-labelledby'
:
'modal-window-title'
};
var
dialog_style
=
{};
return
(
h
(
'section.keyboard-help'
,
[
h
(
'button.keyboard-help-button.unbutton.link-button'
,
{
attributes
:
{
tabindex
:
0
}
},
gettext
(
'Keyboard Help'
)),
h
(
'div.keyboard-help-dialog'
,
[
h
(
'div.modal-window-overlay'
),
h
(
'div.modal-window'
,
{
attributes
:
dialog_attributes
,
style
:
dialog_style
},
[
h
(
'div.modal-header'
,
[
h
(
'h2.modal-window-title'
,
gettext
(
'Keyboard Help'
))
]),
h
(
'div.modal-content'
,
[
h
(
'p'
,
gettext
(
'You can complete this problem using only your keyboard.'
)),
h
(
'ul'
,
[
h
(
'li'
,
gettext
(
'Use "Tab" and "Shift-Tab" to navigate between items and zones.'
)),
h
(
'li'
,
gettext
(
'Press "Enter", "Space", "Ctrl-m", or "⌘-m" on an item to select it for dropping, then navigate to the zone you want to drop it on.'
)),
h
(
'li'
,
gettext
(
'Press "Enter", "Space", "Ctrl-m", or "⌘-m" to drop the item on the current zone.'
)),
h
(
'li'
,
gettext
(
'Press "Esc" if you want to cancel the drop operation (for example, to select a different item).'
)),
])
]),
h
(
'div.modal-actions'
,
[
h
(
'button.modal-dismiss-button'
,
gettext
(
"OK"
))
])
])
])
])
);
};
var
mainTemplate
=
function
(
ctx
)
{
var
problemTitle
=
ctx
.
show_title
?
h
(
'h2.problem-title'
,
{
innerHTML
:
ctx
.
title_html
})
:
null
;
var
problemHeader
=
ctx
.
show_problem_header
?
h
(
'h3.title1'
,
gettext
(
'Problem'
))
:
null
;
var
popupSelector
=
'div.popup'
;
if
(
ctx
.
popup_html
&&
!
ctx
.
last_action_correct
)
{
popupSelector
+=
'.popup-incorrect'
;
}
var
is_item_placed
=
function
(
i
)
{
return
i
.
is_placed
;
};
var
items_placed
=
$
.
grep
(
ctx
.
items
,
is_item_placed
);
var
items_in_bank
=
$
.
grep
(
ctx
.
items
,
is_item_placed
,
true
);
return
(
h
(
'section.themed-xblock.xblock--drag-and-drop'
,
[
problemTitle
,
h
(
'section.problem'
,
[
problemHeader
,
h
(
'p'
,
{
innerHTML
:
ctx
.
problem_html
}),
]),
h
(
'section.drag-container'
,
{
attributes
:
{
role
:
'application'
}
},
[
h
(
'div.item-bank'
,
renderCollection
(
itemTemplate
,
items_in_bank
,
ctx
)
),
h
(
'div.target'
,
[
h
(
popupSelector
,
{
attributes
:
{
'aria-live'
:
'polite'
,
'tabindex'
:
0
},
style
:
{
display
:
ctx
.
popup_html
?
'block'
:
'none'
},
},
[
h
(
'button.unbutton.close.icon-remove-sign.fa-times-circle'
,
[
h
(
'div'
,
{
attributes
:
{
'class'
:
'sr'
}},
gettext
(
"Close"
))
]),
h
(
'p.popup-content'
,
{
innerHTML
:
ctx
.
popup_html
}),
]
),
h
(
'div.target-img-wrapper'
,
[
h
(
'img.target-img'
,
{
src
:
ctx
.
target_img_src
,
alt
:
ctx
.
target_img_description
}),
]),
renderCollection
(
zoneTemplate
,
ctx
.
zones
,
ctx
),
renderCollection
(
itemTemplate
,
items_placed
,
ctx
),
]),
]),
keyboardHelpTemplate
(
ctx
),
feedbackTemplate
(
ctx
),
])
);
};
DragAndDropBlock
.
renderView
=
mainTemplate
;
})(
virtualDom
.
h
);
tests/integration/test_interaction.py
View file @
82dad4ae
...
@@ -131,7 +131,7 @@ class InteractionTestBase(object):
...
@@ -131,7 +131,7 @@ class InteractionTestBase(object):
self
.
wait_until_visible
(
item
)
self
.
wait_until_visible
(
item
)
item_content
=
item
.
find_element_by_css_selector
(
'.item-content'
)
item_content
=
item
.
find_element_by_css_selector
(
'.item-content'
)
item_description
=
item
.
find_element_by_css_selector
(
'.sr'
)
item_description
=
item
.
find_element_by_css_selector
(
'.sr'
)
item_description_id
=
'item-{}-description'
.
format
(
item_value
)
item_description_id
=
'
-
item-{}-description'
.
format
(
item_value
)
self
.
assertIsNone
(
item
.
get_attribute
(
'tabindex'
))
self
.
assertIsNone
(
item
.
get_attribute
(
'tabindex'
))
self
.
assertEqual
(
item
.
get_attribute
(
'aria-grabbed'
),
'false'
)
self
.
assertEqual
(
item
.
get_attribute
(
'aria-grabbed'
),
'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