Commit a74d0850 by Jillian Vogel Committed by Jonathan Piacenti

OC-1320 Fixed zone alignment logic to prevent breaking existing tests.

* Items placed in aligned zones only are rendered as children of the zone.
* Items placed in non-aligned zones are rendered as children of the div.target, as per usual.
* Added an item.zone_align property, to maintain this distinction.
* Reverted positioning changes made to placeItem()
* Moved CSS up under the other item-related CSS
parent 2ea29649
...@@ -142,6 +142,26 @@ ...@@ -142,6 +142,26 @@
transform: translate(-50%, -50%); /* These blocks are to be centered on their absolute x,y position */ transform: translate(-50%, -50%); /* These blocks are to be centered on their absolute x,y position */
} }
/* Placed options in an aligned zone */
.xblock--drag-and-drop .zone .item-wrapper {
width: 100%;
position: relative;
}
.xblock--drag-and-drop .zone .item-align .option {
transform: none;
position: relative;
vertical-align: top;
}
.xblock--drag-and-drop .zone .item-align-left {
text-align: left;
}
.xblock--drag-and-drop .zone .item-align-right {
text-align: right;
}
.xblock--drag-and-drop .zone .item-align-center {
text-align: center;
}
/* Focused option */ /* Focused option */
.xblock--drag-and-drop .drag-container .item-bank .option:focus, .xblock--drag-and-drop .drag-container .item-bank .option:focus,
.xblock--drag-and-drop .drag-container .item-bank .option:hover, .xblock--drag-and-drop .drag-container .item-bank .option:hover,
...@@ -272,26 +292,6 @@ ...@@ -272,26 +292,6 @@
border: 2px solid #a5a5a5; border: 2px solid #a5a5a5;
} }
/* Zone that aligns its items */
.xblock--drag-and-drop .zone .item-wrapper {
width: 100%;
}
.xblock--drag-and-drop .zone .item-align .option {
display: inline-block;
vertical-align: top;
position: relative;
transform: none;
}
.xblock--drag-and-drop .zone .item-align-left {
text-align: left;
}
.xblock--drag-and-drop .zone .item-align-right {
text-align: right;
}
.xblock--drag-and-drop .zone .item-align-center {
text-align: center;
}
.xblock--drag-and-drop .drag-container .target .zone p { .xblock--drag-and-drop .drag-container .target .zone p {
width: 100%; width: 100%;
font-family: Arial; font-family: Arial;
......
...@@ -89,12 +89,9 @@ function DragNDropTemplates(url_name) { ...@@ -89,12 +89,9 @@ function DragNDropTemplates(url_name) {
style['outline-color'] = item.color; style['outline-color'] = item.color;
} }
if (item.is_placed) { if (item.is_placed) {
// If an item_zone is provided, and the zone is aligned, let CSS position the item. if (!item.zone_align) {
// Otherwise, use absolute positioning.
if (!ctx.item_zone || !ctx.item_zone.align) {
style.left = item.x_percent + "%"; style.left = item.x_percent + "%";
style.top = item.y_percent + "%"; style.top = item.y_percent + "%";
style.position = "absolute";
} }
if (item.widthPercent) { if (item.widthPercent) {
style.width = item.widthPercent + "%"; style.width = item.widthPercent + "%";
...@@ -159,10 +156,14 @@ function DragNDropTemplates(url_name) { ...@@ -159,10 +156,14 @@ function DragNDropTemplates(url_name) {
var className = ctx.display_zone_labels ? 'zone-name' : 'zone-name sr'; var className = ctx.display_zone_labels ? 'zone-name' : 'zone-name sr';
var selector = ctx.display_zone_borders ? 'div.zone.zone-with-borders' : 'div.zone'; var selector = ctx.display_zone_borders ? 'div.zone.zone-with-borders' : 'div.zone';
// Mark the zone's item alignment // If zone is aligned, mark its item alignment
// and render its placed items as children
var item_wrapper = 'div.item-wrapper'; var item_wrapper = 'div.item-wrapper';
var items_in_zone = [];
if (zone.align) { if (zone.align) {
item_wrapper += '.item-align.item-align-' + zone.align; item_wrapper += '.item-align.item-align-' + zone.align;
var is_item_in_zone = function(i) { return i.is_placed && (i.zone === zone.title); };
items_in_zone = $.grep(ctx.items, is_item_in_zone);
} }
// Render the items in the zone // Render the items in the zone
...@@ -181,6 +182,7 @@ function DragNDropTemplates(url_name) { ...@@ -181,6 +182,7 @@ function DragNDropTemplates(url_name) {
'aria-dropeffect': 'move', 'aria-dropeffect': 'move',
'data-uid': zone.uid, 'data-uid': zone.uid,
'data-zone_id': zone.id, 'data-zone_id': zone.id,
'data-zone_align': zone.align,
'role': 'button', 'role': 'button',
}, },
style: { style: {
...@@ -251,8 +253,13 @@ function DragNDropTemplates(url_name) { ...@@ -251,8 +253,13 @@ function DragNDropTemplates(url_name) {
if (ctx.popup_html && !ctx.last_action_correct) { if (ctx.popup_html && !ctx.last_action_correct) {
popupSelector += '.popup-incorrect'; popupSelector += '.popup-incorrect';
} }
// Render only items_in_bank and items_placed_unaligned here;
// items placed in aligned zones will be rendered by zoneTemplate.
var is_item_placed = function(i) { return i.is_placed; }; 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); var items_in_bank = $.grep(ctx.items, is_item_placed, true);
var is_item_placed_unaligned = function(i) { return i.is_placed && !i.zone_align; };
var items_placed_unaligned = $.grep(items_placed, is_item_placed_unaligned);
return ( return (
h('section.themed-xblock.xblock--drag-and-drop', [ h('section.themed-xblock.xblock--drag-and-drop', [
problemTitle, problemTitle,
...@@ -289,6 +296,7 @@ function DragNDropTemplates(url_name) { ...@@ -289,6 +296,7 @@ function DragNDropTemplates(url_name) {
] ]
), ),
renderCollection(zoneTemplate, ctx.zones, ctx), renderCollection(zoneTemplate, ctx.zones, ctx),
renderCollection(itemTemplate, items_placed_unaligned, ctx)
] ]
), ),
]), ]),
...@@ -352,6 +360,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -352,6 +360,7 @@ function DragAndDropBlock(runtime, element, configuration) {
state = stateResult[0]; // stateResult is an array of [data, statusText, jqXHR] state = stateResult[0]; // stateResult is an array of [data, statusText, jqXHR]
migrateConfiguration(bgImg.width); migrateConfiguration(bgImg.width);
migrateState(bgImg.width, bgImg.height); migrateState(bgImg.width, bgImg.height);
markItemZoneAlign();
bgImgNaturalWidth = bgImg.width; bgImgNaturalWidth = bgImg.width;
// Set up event handlers: // Set up event handlers:
...@@ -599,34 +608,33 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -599,34 +608,33 @@ function DragAndDropBlock(runtime, element, configuration) {
}; };
var placeItem = function($zone, $item) { var placeItem = function($zone, $item) {
var item_id;
var $anchor; var $anchor;
if ($item !== undefined) { if ($item !== undefined) {
item_id = $item.data('value');
// Element was placed using the mouse, // Element was placed using the mouse,
// so use relevant properties of *item* when calculating new position below. // so use relevant properties of *item* when calculating new position below.
$anchor = $item; $anchor = $item;
} else { } else {
item_id = $selectedItem.data('value');
// Element was placed using the keyboard, // Element was placed using the keyboard,
// so use relevant properties of *zone* when calculating new position below. // so use relevant properties of *zone* when calculating new position below.
$anchor = $zone; $anchor = $zone;
// Set $item so it can be used below
$item = $selectedItem;
} }
var zone = String($zone.data('uid')); var zone = String($zone.data('uid'));
var item_id = $item.data('value');
var zone_id = $zone.data('zone_id'); var zone_id = $zone.data('zone_id');
var zone_align = $zone.data('zone_align');
var $target_img = $root.find('.target-img'); var $target_img = $root.find('.target-img');
// Calculate the position of the item relative to the anchor element // Calculate the position of the item to place relative to the image.
var x_pos = $anchor.offset().left + ($anchor.outerWidth()/2); var x_pos = $anchor.offset().left + ($anchor.outerWidth()/2) - $target_img.offset().left;
var y_pos = $anchor.offset().top + ($anchor.outerHeight()/2); var y_pos = $anchor.offset().top + ($anchor.outerHeight()/2) - $target_img.offset().top;
var x_pos_percent = x_pos / $target_img.width() * 100;
// Calculate position as a percentage relative to the target image var y_pos_percent = y_pos / $target_img.height() * 100;
var x_pos_percent = (x_pos - $target_img.offset().left) / $target_img.width() * 100;
var y_pos_percent = (y_pos - $target_img.offset().top) / $target_img.height() * 100;
state.items[item_id] = { state.items[item_id] = {
zone: zone, zone: zone,
zone_align: zone_align,
x_percent: x_pos_percent, x_percent: x_pos_percent,
y_percent: y_pos_percent, y_percent: y_pos_percent,
submitting_location: true, submitting_location: true,
...@@ -901,6 +909,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -901,6 +909,7 @@ function DragAndDropBlock(runtime, element, configuration) {
if (item_user_state) { if (item_user_state) {
itemProperties.is_placed = true; itemProperties.is_placed = true;
itemProperties.zone = item_user_state.zone; itemProperties.zone = item_user_state.zone;
itemProperties.zone_align = item_user_state.zone_align;
itemProperties.x_percent = item_user_state.x_percent; itemProperties.x_percent = item_user_state.x_percent;
itemProperties.y_percent = item_user_state.y_percent; itemProperties.y_percent = item_user_state.y_percent;
} }
...@@ -985,5 +994,21 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -985,5 +994,21 @@ function DragAndDropBlock(runtime, element, configuration) {
}); });
}; };
/**
* markItemZoneAlign: Mark the items placed in an aligned zone with the zone
* alignment, so they can be properly placed inside the zone.
* We have do this in JS, not python, since zone configurations may change.
*/
var markItemZoneAlign = function() {
var zone_align = {};
configuration.zones.forEach(function(zone) {
zone_align[zone.title] = zone.align;
});
Object.keys(state.items).forEach(function(item_id) {
var item = state.items[item_id];
item.zone_align = zone_align[item.zone];
});
};
init(); init();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment