Commit ead346ee by Valera Rozuvan Committed by Alexander Kryklia

Refactoring. New feature: adding multiple draggables from one.

parent e2bbaf08
......@@ -5,189 +5,170 @@
(function (requirejs, require, define) {
define(['logme', 'update_input'], function (logme, updateInput) {
return Draggables;
return {
'init': init
};
function Draggables(state) {
var c1;
function init(state) {
logme('Draggables.init; state = ', state);
state.draggables = [];
state.numDraggablesInSlider = 0;
state.currentMovingDraggable = null;
for (c1 = 0; c1 < state.config.draggables.length; c1 += 1) {
processDraggable(state.config.draggables[c1], c1 + 1);
}
(function (c1) {
while (c1 < state.config.draggables.length) {
processDraggable(state, state.config.draggables[c1], c1 + 1);
c1 += 1
}
}(0));
state.updateArrowOpacity();
state.currentMovingDraggable = null;
$(document).mousemove(function (event) {
if (state.currentMovingDraggable !== null) {
state.currentMovingDraggable.iconEl.css(
documentMouseMove(state, event);
});
}
function documentMouseMove(state, event) {
if (state.currentMovingDraggable !== null) {
state.currentMovingDraggable.iconEl.css(
'left',
event.pageX -
state.baseImageEl.offset().left -
state.currentMovingDraggable.iconWidth * 0.5
- state.currentMovingDraggable.iconElLeftOffset
);
state.currentMovingDraggable.iconEl.css(
'top',
event.pageY -
state.baseImageEl.offset().top -
state.currentMovingDraggable.iconHeight * 0.5
);
if (state.currentMovingDraggable.labelEl !== null) {
state.currentMovingDraggable.labelEl.css(
'left',
event.pageX -
state.baseImageEl.offset().left -
state.currentMovingDraggable.iconWidth * 0.5
- state.currentMovingDraggable.iconElLeftOffset
state.currentMovingDraggable.labelWidth * 0.5
- 9 // Account for padding, border.
);
state.currentMovingDraggable.iconEl.css(
state.currentMovingDraggable.labelEl.css(
'top',
event.pageY -
state.baseImageEl.offset().top -
state.currentMovingDraggable.iconHeight * 0.5
state.baseImageEl.offset().top +
state.currentMovingDraggable.iconHeight * 0.5 +
5
);
if (state.currentMovingDraggable.labelEl !== null) {
state.currentMovingDraggable.labelEl.css(
'left',
event.pageX -
state.baseImageEl.offset().left -
state.currentMovingDraggable.labelWidth * 0.5
- 9 // Account for padding, border.
);
state.currentMovingDraggable.labelEl.css(
'top',
event.pageY -
state.baseImageEl.offset().top +
state.currentMovingDraggable.iconHeight * 0.5 +
5
);
}
}
});
}
}
return;
function processDraggable(obj, objIndex) {
var inContainer, mousePressed, onTarget, draggableObj;
draggableObj = {
'zIndex': objIndex,
'oldZIndex': objIndex,
'labelEl': null,
'hasLoaded': false
};
draggableObj.containerEl = $(
'<div ' +
'style=" ' +
'width: 100px; ' +
'height: 100px; ' +
'display: inline; ' +
'float: left; ' +
'overflow: hidden; ' +
'z-index: ' + objIndex + '; ' +
'border-left: 1px solid #CCC; ' +
'border-right: 1px solid #CCC; ' +
'text-align: center; ' +
'position: relative; ' +
'" ' +
'></div>'
function processDraggable(state, obj, objIndex) {
var draggableObj;
logme('processDraggable; state = ', state);
logme('Processing draggable #' + objIndex);
draggableObj = {
'zIndex': objIndex,
'oldZIndex': objIndex,
'labelEl': null,
'hasLoaded': false,
'inContainer': true,
'mousePressed': false,
'onTarget': null,
'state': state,
'mouseDown': mouseDown,
'mouseUp': mouseUp,
'mouseMove': mouseMove,
'checkLandingElement': checkLandingElement,
'removeObjIdFromTarget': removeObjIdFromTarget,
'checkIfOnTarget': checkIfOnTarget,
'snapToTarget': snapToTarget,
'correctZIndexes': correctZIndexes,
'moveBackToSlider': moveBackToSlider
};
draggableObj.containerEl = $(
'<div ' +
'style=" ' +
'width: 100px; ' +
'height: 100px; ' +
'display: inline; ' +
'float: left; ' +
'overflow: hidden; ' +
'z-index: ' + objIndex + '; ' +
'border-left: 1px solid #CCC; ' +
'border-right: 1px solid #CCC; ' +
'text-align: center; ' +
'position: relative; ' +
'" ' +
'></div>'
);
draggableObj.containerEl.appendTo(state.sliderEl);
if (obj.icon.length > 0) {
draggableObj.iconElBGColor = 'transparent';
draggableObj.iconElPadding = 0;
draggableObj.iconElBorder = 'none';
draggableObj.iconElLeftOffset = 0;
draggableObj.iconEl = $('<img />');
draggableObj.iconEl.attr(
'src',
obj.icon
);
draggableObj.iconEl.load(function () {
draggableObj.iconWidth = this.width;
draggableObj.iconHeight = this.height;
if (draggableObj.iconWidth >= draggableObj.iconHeight) {
draggableObj.iconWidthSmall = 60;
draggableObj.iconHeightSmall =
draggableObj.iconWidthSmall *
(draggableObj.iconHeight / draggableObj.iconWidth);
} else {
draggableObj.iconHeightSmall = 60;
draggableObj.iconWidthSmall =
draggableObj.iconHeightSmall *
(draggableObj.iconWidth / draggableObj.iconHeight);
}
draggableObj.containerEl.appendTo(state.sliderEl);
if (obj.icon.length > 0) {
draggableObj.iconElBGColor = 'transparent';
draggableObj.iconElPadding = 0;
draggableObj.iconElBorder = 'none';
draggableObj.iconElLeftOffset = 0;
draggableObj.iconEl.css('position', 'absolute');
draggableObj.iconEl = $('<img />');
draggableObj.iconEl.attr(
'src',
obj.icon
draggableObj.iconEl.css(
'width',
draggableObj.iconWidthSmall
);
draggableObj.iconEl.css(
'height',
draggableObj.iconHeightSmall
);
draggableObj.iconEl.load(function () {
draggableObj.iconWidth = this.width;
draggableObj.iconHeight = this.height;
if (draggableObj.iconWidth >= draggableObj.iconHeight) {
draggableObj.iconWidthSmall = 60;
draggableObj.iconHeightSmall =
draggableObj.iconWidthSmall *
(draggableObj.iconHeight / draggableObj.iconWidth);
} else {
draggableObj.iconHeightSmall = 60;
draggableObj.iconWidthSmall =
draggableObj.iconHeightSmall *
(draggableObj.iconWidth / draggableObj.iconHeight);
}
draggableObj.iconEl.css('position', 'absolute');
draggableObj.iconEl.css(
'width',
draggableObj.iconWidthSmall
);
draggableObj.iconEl.css(
'height',
draggableObj.iconHeightSmall
);
draggableObj.iconEl.css(
'left',
50 - draggableObj.iconWidthSmall * 0.5
);
if (obj.label.length > 0) {
draggableObj.iconEl.css('top', 5);
} else {
draggableObj.iconEl.css(
'left',
50 - draggableObj.iconWidthSmall * 0.5
'top',
50 - draggableObj.iconHeightSmall * 0.5
);
}
if (obj.label.length > 0) {
draggableObj.iconEl.css('top', 5);
} else {
draggableObj.iconEl.css(
'top',
50 - draggableObj.iconHeightSmall * 0.5
);
}
draggableObj.iconEl.appendTo(draggableObj.containerEl);
if (obj.label.length > 0) {
draggableObj.labelEl = $(
'<div ' +
'style=" ' +
'position: absolute; ' +
'color: black; ' +
'font-size: 0.95em; ' +
'z-index: ' + objIndex + '; ' +
'" ' +
'>' +
obj.label +
'</div>'
);
draggableObj.labelEl.appendTo(
draggableObj.containerEl
);
draggableObj.labelWidth = draggableObj.labelEl.width();
draggableObj.labelEl.css(
'left',
50 - draggableObj.labelWidth * 0.5
);
draggableObj.labelEl.css(
'top',
5 + draggableObj.iconHeightSmall + 5
);
draggableObj.labelEl.mousedown(mouseDown);
draggableObj.labelEl.mouseup(mouseUp);
draggableObj.labelEl.mousemove(mouseMove);
}
draggableObj.iconEl.appendTo(draggableObj.containerEl);
draggableObj.hasLoaded = true;
});
} else {
// To make life easier, if there is no icon, but there is a
// label, we will create a label and store it as if it was an
// icon. All the existing code will work, and the user will
// see a label instead of an icon.
if (obj.label.length > 0) {
draggableObj.iconElBGColor = state.config.labelBgColor;
draggableObj.iconElPadding = 8;
draggableObj.iconElBorder = '1px solid black';
draggableObj.iconElLeftOffset = 9;
draggableObj.iconEl = $(
draggableObj.labelEl = $(
'<div ' +
'style=" ' +
'position: absolute; ' +
......@@ -200,599 +181,631 @@ define(['logme', 'update_input'], function (logme, updateInput) {
'</div>'
);
draggableObj.iconEl.appendTo(draggableObj.containerEl);
draggableObj.labelEl.appendTo(
draggableObj.containerEl
);
draggableObj.iconWidth = draggableObj.iconEl.width();
draggableObj.iconHeight = draggableObj.iconEl.height();
draggableObj.iconWidthSmall = draggableObj.iconWidth;
draggableObj.iconHeightSmall = draggableObj.iconHeight;
draggableObj.labelWidth = draggableObj.labelEl.width();
draggableObj.iconEl.css(
draggableObj.labelEl.css(
'left',
50 - draggableObj.iconWidthSmall * 0.5
50 - draggableObj.labelWidth * 0.5
);
draggableObj.iconEl.css(
draggableObj.labelEl.css(
'top',
50 - draggableObj.iconHeightSmall * 0.5
5 + draggableObj.iconHeightSmall + 5
);
} else {
// If no icon and no label, don't create a draggable.
return;
}
}
draggableObj.iconEl.mousedown(mouseDown);
draggableObj.iconEl.mouseup(mouseUp);
draggableObj.iconEl.mousemove(mouseMove);
draggableObj.containerEl.mousedown(mouseDown);
draggableObj.containerEl.mouseup(mouseUp);
draggableObj.containerEl.mousemove(mouseMove);
inContainer = true;
mousePressed = false;
onTarget = null;
draggableObj.id = obj.id;
draggableObj.x = -1;
draggableObj.y = -1;
draggableObj.setInContainer = function (val) {
inContainer = val;
};
draggableObj.setOnTarget = function (val) {
onTarget = val;
};
state.draggables.push(draggableObj);
state.numDraggablesInSlider += 1;
draggableObj.labelEl.mousedown(function (event) {
draggableObj.mouseDown.call(draggableObj, event);
});
draggableObj.labelEl.mouseup(function (event) {
draggableObj.mouseUp.call(draggableObj, event);
});
draggableObj.labelEl.mousemove(function (event) {
draggableObj.mouseMove.call(draggableObj, event);
});
}
if (obj.icon.length === 0) {
draggableObj.hasLoaded = true;
}
return;
});
} else {
// To make life easier, if there is no icon, but there is a
// label, we will create a label and store it as if it was an
// icon. All the existing code will work, and the user will
// see a label instead of an icon.
if (obj.label.length > 0) {
draggableObj.iconElBGColor = state.config.labelBgColor;
draggableObj.iconElPadding = 8;
draggableObj.iconElBorder = '1px solid black';
draggableObj.iconElLeftOffset = 9;
draggableObj.iconEl = $(
'<div ' +
'style=" ' +
'position: absolute; ' +
'color: black; ' +
'font-size: 0.95em; ' +
'z-index: ' + objIndex + '; ' +
'" ' +
'>' +
obj.label +
'</div>'
);
function mouseDown(event) {
if (mousePressed === false) {
// So that the browser does not perform a default drag.
// If we don't do this, each drag operation will
// potentially cause the highlghting of the dragged element.
event.preventDefault();
draggableObj.iconEl.appendTo(draggableObj.containerEl);
// If this draggable is just being dragged out of the
// container, we must perform some additional tasks.
if (inContainer === true) {
draggableObj.containerEl.hide();
draggableObj.iconWidth = draggableObj.iconEl.width();
draggableObj.iconHeight = draggableObj.iconEl.height();
draggableObj.iconWidthSmall = draggableObj.iconWidth;
draggableObj.iconHeightSmall = draggableObj.iconHeight;
draggableObj.iconEl.detach();
draggableObj.iconEl.css(
'background-color', draggableObj.iconElBGColor
);
draggableObj.iconEl.css(
'padding-left', draggableObj.iconElPadding
);
draggableObj.iconEl.css(
'padding-right', draggableObj.iconElPadding
);
draggableObj.iconEl.css(
'border', draggableObj.iconElBorder
);
draggableObj.iconEl.css(
'width',
draggableObj.iconWidth
);
draggableObj.iconEl.css(
'height',
draggableObj.iconHeight
);
draggableObj.iconEl.css(
'left',
event.pageX -
state.baseImageEl.offset().left -
draggableObj.iconWidth * 0.5
- draggableObj.iconElLeftOffset
);
draggableObj.iconEl.css(
'top',
event.pageY -
state.baseImageEl.offset().top -
draggableObj.iconHeight * 0.5
);
draggableObj.iconEl.appendTo(
state.baseImageEl.parent()
);
draggableObj.iconEl.css(
'left',
50 - draggableObj.iconWidthSmall * 0.5
);
draggableObj.iconEl.css(
'top',
50 - draggableObj.iconHeightSmall * 0.5
);
} else {
// If no icon and no label, don't create a draggable.
return;
}
}
if (draggableObj.labelEl !== null) {
draggableObj.labelEl.detach();
draggableObj.labelEl.css(
'background-color', state.config.labelBgColor
);
draggableObj.labelEl.css(
'padding-left', 8
);
draggableObj.labelEl.css(
'padding-right', 8
);
draggableObj.labelEl.css(
'border', '1px solid black'
);
draggableObj.labelEl.css(
'left',
event.pageX -
state.baseImageEl.offset().left -
draggableObj.labelWidth * 0.5
- 9 // Account for padding, border.
);
draggableObj.labelEl.css(
'top',
event.pageY -
state.baseImageEl.offset().top +
draggableObj.iconHeight * 0.5 + 5
);
draggableObj.labelEl.appendTo(
state.baseImageEl.parent()
);
}
draggableObj.iconEl.mousedown(function (event) {
draggableObj.mouseDown.call(draggableObj, event);
});
draggableObj.iconEl.mouseup(function (event) {
draggableObj.mouseUp.call(draggableObj, event);
});
draggableObj.iconEl.mousemove(function (event) {
draggableObj.mouseMove.call(draggableObj, event);
});
inContainer = false;
state.numDraggablesInSlider -= 1;
}
draggableObj.containerEl.mousedown(function (event) {
draggableObj.mouseDown.call(draggableObj, event);
});
draggableObj.containerEl.mouseup(function (event) {
draggableObj.mouseUp.call(draggableObj, event);
});
draggableObj.containerEl.mousemove(function (event) {
draggableObj.mouseMove.call(draggableObj, event);
});
draggableObj.oldZIndex = draggableObj.zIndex;
draggableObj.zIndex = 1000;
draggableObj.iconEl.css('z-index', '1000');
if (draggableObj.labelEl !== null) {
draggableObj.labelEl.css('z-index', '1000');
}
draggableObj.id = obj.id;
draggableObj.x = -1;
draggableObj.y = -1;
mousePressed = true;
state.currentMovingDraggable = draggableObj;
}
}
state.numDraggablesInSlider += 1;
function mouseUp() {
if (mousePressed === true) {
state.currentMovingDraggable = null;
if (obj.icon.length === 0) {
draggableObj.hasLoaded = true;
}
checkLandingElement();
}
}
state.draggables.push(draggableObj);
}
function mouseMove() {
if (mousePressed === true) {
// Because we have also attached a 'mousemove' event to the
// 'document' (that will do the same thing), let's tell the
// browser not to bubble up this event. The attached event
// on the 'document' will only be triggered when the mouse
// pointer leaves the draggable while it is in the middle
// of a drag operation (user moves the mouse very quickly).
event.stopPropagation();
function mouseDown(event) {
if (this.mousePressed === false) {
// So that the browser does not perform a default drag.
// If we don't do this, each drag operation will
// potentially cause the highlghting of the dragged element.
event.preventDefault();
// If this draggable is just being dragged out of the
// container, we must perform some additional tasks.
if (this.inContainer === true) {
this.containerEl.hide();
this.iconEl.detach();
this.iconEl.css(
'background-color', this.iconElBGColor
);
this.iconEl.css(
'padding-left', this.iconElPadding
);
this.iconEl.css(
'padding-right', this.iconElPadding
);
this.iconEl.css(
'border', this.iconElBorder
);
this.iconEl.css(
'width',
this.iconWidth
);
this.iconEl.css(
'height',
this.iconHeight
);
this.iconEl.css(
'left',
event.pageX -
this.state.baseImageEl.offset().left -
this.iconWidth * 0.5
- this.iconElLeftOffset
);
this.iconEl.css(
'top',
event.pageY -
this.state.baseImageEl.offset().top -
this.iconHeight * 0.5
);
this.iconEl.appendTo(
state.baseImageEl.parent()
);
draggableObj.iconEl.css(
if (this.labelEl !== null) {
this.labelEl.detach();
this.labelEl.css(
'background-color', this.state.config.labelBgColor
);
this.labelEl.css(
'padding-left', 8
);
this.labelEl.css(
'padding-right', 8
);
this.labelEl.css(
'border', '1px solid black'
);
this.labelEl.css(
'left',
event.pageX -
state.baseImageEl.offset().left -
draggableObj.iconWidth * 0.5
- draggableObj.iconElLeftOffset
this.state.baseImageEl.offset().left -
this.labelWidth * 0.5
- 9 // Account for padding, border.
);
draggableObj.iconEl.css(
this.labelEl.css(
'top',
event.pageY -
state.baseImageEl.offset().top -
draggableObj.iconHeight * 0.5
this.state.baseImageEl.offset().top +
this.iconHeight * 0.5 + 5
);
this.labelEl.appendTo(
this.state.baseImageEl.parent()
);
if (draggableObj.labelEl !== null) {
draggableObj.labelEl.css(
'left',
event.pageX -
state.baseImageEl.offset().left -
draggableObj.labelWidth * 0.5
- 9 // Acoount for padding, border.
);
draggableObj.labelEl.css(
'top',
event.pageY -
state.baseImageEl.offset().top +
draggableObj.iconHeight * 0.5 +
5
);
}
}
}
// 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 positionIE, targetFound;
this.inContainer = false;
this.state.numDraggablesInSlider -= 1;
}
mousePressed = false;
positionIE = draggableObj.iconEl.position();
this.oldZIndex = this.zIndex;
this.zIndex = 1000;
this.iconEl.css('z-index', '1000');
if (this.labelEl !== null) {
this.labelEl.css('z-index', '1000');
}
if (state.individualTargets === true) {
targetFound = false;
this.mousePressed = true;
this.state.currentMovingDraggable = this;
}
}
checkIfOnTarget();
function mouseUp() {
if (this.mousePressed === true) {
this.state.currentMovingDraggable = null;
if (targetFound === true) {
correctZIndexes();
} else {
moveBackToSlider();
removeObjIdFromTarget();
this.checkLandingElement();
}
}
state.numDraggablesInSlider += 1;
}
} else {
if (
(positionIE.left < 0) ||
(
positionIE.left + draggableObj.iconWidth >
state.baseImageEl.width()
) ||
(positionIE.top < 0) ||
(
positionIE.top + draggableObj.iconHeight >
state.baseImageEl.height()
)
) {
moveBackToSlider();
function mouseMove() {
if (this.mousePressed === true) {
// Because we have also attached a 'mousemove' event to the
// 'document' (that will do the same thing), let's tell the
// browser not to bubble up this event. The attached event
// on the 'document' will only be triggered when the mouse
// pointer leaves the draggable while it is in the middle
// of a drag operation (user moves the mouse very quickly).
event.stopPropagation();
this.iconEl.css(
'left',
event.pageX -
this.state.baseImageEl.offset().left -
this.iconWidth * 0.5
- this.iconElLeftOffset
);
this.iconEl.css(
'top',
event.pageY -
this.state.baseImageEl.offset().top -
this.iconHeight * 0.5
);
draggableObj.x = -1;
draggableObj.y = -1;
if (this.labelEl !== null) {
this.labelEl.css(
'left',
event.pageX -
this.state.baseImageEl.offset().left -
this.labelWidth * 0.5
- 9 // Acoount for padding, border.
);
this.labelEl.css(
'top',
event.pageY -
this.state.baseImageEl.offset().top +
this.iconHeight * 0.5 +
5
);
}
}
}
state.numDraggablesInSlider += 1;
} else {
correctZIndexes();
// 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 positionIE;
draggableObj.x =
positionIE.left + draggableObj.iconWidth * 0.5;
draggableObj.y =
positionIE.top + draggableObj.iconHeight * 0.5;
}
}
this.mousePressed = false;
positionIE = this.iconEl.position();
state.updateArrowOpacity();
updateInput(state);
if (this.state.individualTargets === true) {
if (this.checkIfOnTarget(positionIE) === true) {
this.correctZIndexes();
} else {
this.moveBackToSlider();
this.removeObjIdFromTarget();
return;
this.state.numDraggablesInSlider += 1;
}
} else {
if (
(positionIE.left < 0) ||
(
positionIE.left + this.iconWidth >
this.state.baseImageEl.width()
) ||
(positionIE.top < 0) ||
(
positionIE.top + this.iconHeight >
this.state.baseImageEl.height()
)
) {
this.moveBackToSlider();
this.x = -1;
this.y = -1;
this.state.numDraggablesInSlider += 1;
} else {
this.correctZIndexes();
function removeObjIdFromTarget() {
var c1;
this.x =
positionIE.left + this.iconWidth * 0.5;
this.y =
positionIE.top + this.iconHeight * 0.5;
}
}
if (onTarget !== null) {
for (c1 = 0; c1 < onTarget.draggable.length; c1 += 1) {
if (onTarget.draggable[c1] === draggableObj.id) {
onTarget.draggable.splice(c1, 1);
this.state.updateArrowOpacity();
updateInput(this.state);
}
break;
}
}
function removeObjIdFromTarget() {
var c1;
if (onTarget.numTextEl !== null) {
onTarget.updateNumTextEl();
}
if (this.onTarget !== null) {
for (c1 = 0; c1 < this.onTarget.draggable.length; c1 += 1) {
if (this.onTarget.draggable[c1] === this.id) {
this.onTarget.draggable.splice(c1, 1);
onTarget = null;
}
break;
}
}
//
// 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.
//
// positionIE is the object as returned by
//
// draggableObj.iconEl.position()
//
function checkIfOnTarget() {
var c1, target;
for (c1 = 0; c1 < state.targets.length; c1 += 1) {
target = state.targets[c1];
// If only one draggable per target is allowed, and
// the current target already has a draggable on it
// (with an ID different from the one we are checking
// against), then go to next target.
if (
(state.config.one_per_target === true) &&
(target.draggable.length === 1) &&
(target.draggable[0] !== draggableObj.id)
) {
continue;
}
if (this.onTarget.numTextEl !== null) {
this.onTarget.updateNumTextEl();
}
// Check if the draggable's center coordinate is within
// the target's dimensions. If not, go to next target.
if (
positionIE.top + draggableObj.iconHeight * 0.5 <
target.offset.top
) {
continue;
}
if (
positionIE.top + draggableObj.iconHeight * 0.5 >
target.offset.top + target.h
) {
continue;
}
if (
positionIE.left + draggableObj.iconWidth * 0.5 <
target.offset.left
) {
continue;
}
if (
positionIE.left + draggableObj.iconWidth * 0.5 >
target.offset.left + target.w
) {
continue;
}
this.onTarget = null;
}
}
// If we got here, then our draggable is on top of a
// target.
targetFound = true;
//
// 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.
//
// positionIE is the object as returned by
//
// this.iconEl.position()
//
function checkIfOnTarget(positionIE) {
var c1, target, targetFound;
targetFound = false;
for (c1 = 0; c1 < this.state.targets.length; c1 += 1) {
target = this.state.targets[c1];
// If only one draggable per target is allowed, and
// the current target already has a draggable on it
// (with an ID different from the one we are checking
// against), then go to next target.
if (
(this.state.config.one_per_target === true) &&
(target.draggable.length === 1) &&
(target.draggable[0] !== this.id)
) {
continue;
}
// 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(draggableObj.id);
}
// If the draggable was moved from the slider to a
// target, remember the target, and add ID to the
// target's draggables list.
else if (onTarget === null) {
onTarget = target;
target.draggable.push(draggableObj.id);
}
// Check if the draggable's center coordinate is within
// the target's dimensions. If not, go to next target.
if (
positionIE.top + this.iconHeight * 0.5 <
target.offset.top
) {
continue;
}
if (
positionIE.top + this.iconHeight * 0.5 >
target.offset.top + target.h
) {
continue;
}
if (
positionIE.left + this.iconWidth * 0.5 <
target.offset.left
) {
continue;
}
if (
positionIE.left + this.iconWidth * 0.5 >
target.offset.left + target.w
) {
continue;
}
if (target.numTextEl !== null) {
target.updateNumTextEl();
}
// If we got here, then our draggable is on top of a
// target.
targetFound = true;
// 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 (
(this.onTarget !== null) &&
(this.onTarget.id !== target.id)
) {
this.removeObjIdFromTarget();
this.onTarget = target;
target.draggable.push(this.id);
}
// If the draggable was moved from the slider to a
// target, remember the target, and add ID to the
// target's draggables list.
else if (this.onTarget === null) {
this.onTarget = target;
target.draggable.push(this.id);
}
// Reposition the draggable so that it's center
// coincides with the center of the target.
snapToTarget(target);
if (target.numTextEl !== null) {
target.updateNumTextEl();
}
break;
}
}
// Reposition the draggable so that it's center
// coincides with the center of the target.
this.snapToTarget(target);
function snapToTarget(target) {
var offset;
break;
}
offset = 0;
if (state.config.targetOutline === true) {
offset = 1;
}
return targetFound;
}
draggableObj.iconEl.css(
'left',
target.offset.left + 0.5 * target.w -
draggableObj.iconWidth * 0.5 + offset
- draggableObj.iconElLeftOffset
);
draggableObj.iconEl.css(
'top',
target.offset.top + 0.5 * target.h -
draggableObj.iconHeight * 0.5 + offset
);
function snapToTarget(target) {
var offset;
if (draggableObj.labelEl !== null) {
draggableObj.labelEl.css(
'left',
target.offset.left + 0.5 * target.w -
draggableObj.labelWidth * 0.5 + offset
- 9 // Acoount for padding, border.
);
draggableObj.labelEl.css(
'top',
target.offset.top + 0.5 * target.h +
draggableObj.iconHeight * 0.5 + 5 + offset
);
offset = 0;
if (this.state.config.targetOutline === true) {
offset = 1;
}
this.iconEl.css(
'left',
target.offset.left + 0.5 * target.w -
this.iconWidth * 0.5 + offset
- this.iconElLeftOffset
);
this.iconEl.css(
'top',
target.offset.top + 0.5 * target.h -
this.iconHeight * 0.5 + offset
);
if (this.labelEl !== null) {
this.labelEl.css(
'left',
target.offset.left + 0.5 * target.w -
this.labelWidth * 0.5 + offset
- 9 // Acoount for padding, border.
);
this.labelEl.css(
'top',
target.offset.top + 0.5 * target.h +
this.iconHeight * 0.5 + 5 + offset
);
}
}
// 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 draggablesInMe, c1, c2, highestZIndex;
if (this.state.individualTargets === true) {
if (this.onTarget.draggable.length > 0) {
draggablesInMe = [];
for (c1 = 0; c1 < this.onTarget.draggable.length; c1 += 1) {
for (c2 = 0; c2 < this.state.draggables.length; c2 += 1) {
if (
this.onTarget.draggable[c1] ===
this.state.draggables[c2].id
) {
draggablesInMe.push(this.state.draggables[c2]);
}
}
}
// 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 draggablesInMe, c1, c2, highestZIndex;
if (state.individualTargets === true) {
logme('In correctZIndexes.');
if (onTarget.draggable.length > 0) {
logme('onTarget.draggable.length > 0');
draggablesInMe = [];
for (c1 = 0; c1 < onTarget.draggable.length; c1 += 1) {
for (c2 = 0; c2 < state.draggables.length; c2 += 1) {
if (
onTarget.draggable[c1] ===
state.draggables[c2].id
) {
draggablesInMe.push(state.draggables[c2]);
}
}
}
highestZIndex = -10000;
for (c1 = 0; c1 < draggablesInMe.length; c1 += 1) {
if (
(draggablesInMe[c1].zIndex > highestZIndex) &&
(draggablesInMe[c1].zIndex !== 1000)
) {
highestZIndex = draggablesInMe[c1].zIndex;
}
}
if (highestZIndex === -10000) {
highestZIndex = onTarget.draggable.length;
} else if (highestZIndex < draggableObj.oldZIndex) {
highestZIndex = draggableObj.oldZIndex;
} else {
for (c1 = 0; c1 < draggablesInMe.length; c1 += 1) {
logme('draggablesInMe[' + c1 + '].id = ' + draggablesInMe[c1].id);
logme('draggablesInMe[' + c1 + '].zIndex = ' + draggablesInMe[c1].zIndex);
logme('draggablesInMe[' + c1 + '].oldZIndex = ' + draggablesInMe[c1].oldZIndex);
}
logme('----------------');
logme('highestZIndex = ' + highestZIndex);
for (c1 = 0; c1 < draggablesInMe.length; c1 += 1) {
draggablesInMe[c1].zIndex -= 1;
draggablesInMe[c1].oldZIndex -= 1;
draggablesInMe[c1].iconEl.css(
'z-index',
draggablesInMe[c1].zIndex
);
if (draggablesInMe[c1].labelEl !== null) {
draggablesInMe[c1].labelEl.css(
'z-index',
draggablesInMe[c1].zIndex
);
}
}
}
} else {
logme('highestZIndex = onTarget.draggable.length');
highestZIndex = onTarget.draggable.length;
}
highestZIndex = -10000;
draggableObj.zIndex = highestZIndex;
draggableObj.oldZIndex = highestZIndex;
for (c1 = 0; c1 < draggablesInMe.length; c1 += 1) {
if (
(draggablesInMe[c1].zIndex > highestZIndex) &&
(draggablesInMe[c1].zIndex !== 1000)
) {
highestZIndex = draggablesInMe[c1].zIndex;
}
}
draggableObj.iconEl.css(
if (highestZIndex === -10000) {
highestZIndex = this.onTarget.draggable.length;
} else if (highestZIndex < this.oldZIndex) {
highestZIndex = this.oldZIndex;
} else {
for (c1 = 0; c1 < draggablesInMe.length; c1 += 1) {
draggablesInMe[c1].zIndex -= 1;
draggablesInMe[c1].oldZIndex -= 1;
draggablesInMe[c1].iconEl.css(
'z-index',
draggableObj.zIndex
draggablesInMe[c1].zIndex
);
if (draggableObj.labelEl !== null) {
draggableObj.labelEl.css(
if (draggablesInMe[c1].labelEl !== null) {
draggablesInMe[c1].labelEl.css(
'z-index',
draggableObj.zIndex
draggablesInMe[c1].zIndex
);
}
} else {
for (c1 = 0; c1 < state.draggables.length; c1++) {
if (
draggableObj.oldZIndex <
state.draggables[c1].zIndex
) {
state.draggables[c1].zIndex -= 1;
state.draggables[c1].oldZIndex = state.draggables[c1].zIndex;
state.draggables[c1].iconEl.css(
'z-index',
state.draggables[c1].zIndex
);
if (state.draggables[c1].labelEl !== null) {
state.draggables[c1].labelEl.css(
'z-index',
state.draggables[c1].zIndex
);
}
}
}
draggableObj.zIndex = c1;
draggableObj.oldZIndex = c1;
draggableObj.iconEl.css('z-index', c1);
if (draggableObj.labelEl !== null) {
draggableObj.labelEl.css('z-index', c1);
}
}
}
} else {
highestZIndex = this.onTarget.draggable.length;
}
// 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() {
draggableObj.containerEl.show();
draggableObj.zIndex = draggableObj.oldZIndex;
this.zIndex = highestZIndex;
this.oldZIndex = highestZIndex;
draggableObj.iconEl.detach();
draggableObj.iconEl.css('border', 'none');
draggableObj.iconEl.css('background-color', 'transparent');
draggableObj.iconEl.css('padding-left', 0);
draggableObj.iconEl.css('padding-right', 0);
draggableObj.iconEl.css('z-index', draggableObj.zIndex);
draggableObj.iconEl.css(
'width',
draggableObj.iconWidthSmall
);
draggableObj.iconEl.css(
'height',
draggableObj.iconHeightSmall
);
draggableObj.iconEl.css(
'left',
50 - draggableObj.iconWidthSmall * 0.5
this.iconEl.css(
'z-index',
this.zIndex
);
if (this.labelEl !== null) {
this.labelEl.css(
'z-index',
this.zIndex
);
}
} else {
for (c1 = 0; c1 < this.state.draggables.length; c1++) {
if (
this.oldZIndex <
this.state.draggables[c1].zIndex
) {
this.state.draggables[c1].zIndex -= 1;
this.state.draggables[c1].oldZIndex = this.state.draggables[c1].zIndex;
this.state.draggables[c1].iconEl.css(
'z-index',
this.state.draggables[c1].zIndex
);
if (draggableObj.labelEl !== null) {
draggableObj.iconEl.css('top', 5);
} else {
draggableObj.iconEl.css(
'top',
50 - draggableObj.iconHeightSmall * 0.5
);
}
draggableObj.iconEl.appendTo(draggableObj.containerEl);
if (draggableObj.labelEl !== null) {
draggableObj.labelEl.detach();
draggableObj.labelEl.css('border', 'none');
draggableObj.labelEl.css('background-color', 'transparent');
draggableObj.labelEl.css('padding-left', 0);
draggableObj.labelEl.css('padding-right', 0);
draggableObj.labelEl.css('z-index', draggableObj.zIndex);
draggableObj.labelEl.css(
'left',
50 - draggableObj.labelWidth * 0.5
);
draggableObj.labelEl.css(
'top',
5 + draggableObj.iconHeightSmall + 5
);
draggableObj.labelEl.appendTo(
draggableObj.containerEl
if (this.state.draggables[c1].labelEl !== null) {
this.state.draggables[c1].labelEl.css(
'z-index',
this.state.draggables[c1].zIndex
);
}
inContainer = true;
}
}
this.zIndex = c1;
this.oldZIndex = c1;
this.iconEl.css('z-index', c1);
if (this.labelEl !== null) {
this.labelEl.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() {
this.containerEl.show();
this.zIndex = this.oldZIndex;
this.iconEl.detach();
this.iconEl.css('border', 'none');
this.iconEl.css('background-color', 'transparent');
this.iconEl.css('padding-left', 0);
this.iconEl.css('padding-right', 0);
this.iconEl.css('z-index', this.zIndex);
this.iconEl.css(
'width',
this.iconWidthSmall
);
this.iconEl.css(
'height',
this.iconHeightSmall
);
this.iconEl.css(
'left',
50 - this.iconWidthSmall * 0.5
);
if (this.labelEl !== null) {
this.iconEl.css('top', 5);
} else {
this.iconEl.css(
'top',
50 - this.iconHeightSmall * 0.5
);
}
this.iconEl.appendTo(this.containerEl);
if (this.labelEl !== null) {
this.labelEl.detach();
this.labelEl.css('border', 'none');
this.labelEl.css('background-color', 'transparent');
this.labelEl.css('padding-left', 0);
this.labelEl.css('padding-right', 0);
this.labelEl.css('z-index', this.zIndex);
this.labelEl.css(
'left',
50 - this.labelWidth * 0.5
);
this.labelEl.css(
'top',
5 + this.iconHeightSmall + 5
);
this.labelEl.appendTo(
this.containerEl
);
}
this.inContainer = true;
}
});
......
......@@ -63,7 +63,9 @@ define(
Targets(state);
Scroller(state);
Draggables(state);
Draggables.init(state);
logme('After Draggables.init(state); state = ', state);
// Update the input element, checking first that it is not filled with
// an answer from the server.
......
......@@ -120,15 +120,6 @@ define(['logme'], function (logme) {
lowestZIndex = 10000;
for (c1 = 0; c1 < draggablesInMe.length; c1 += 1) {
logme(
'draggablesInMe[' + c1 + '].id = ' + draggablesInMe[c1].id,
'draggablesInMe[' + c1 + '].zIndex = ' + draggablesInMe[c1].zIndex,
'draggablesInMe[' + c1 + '].oldZIndex = ' + draggablesInMe[c1].oldZIndex
);
}
logme('------------------');
for (c1 = 0; c1 < draggablesInMe.length; c1 += 1) {
if (draggablesInMe[c1].zIndex < lowestZIndex) {
lowestZIndex = draggablesInMe[c1].zIndex;
}
......
......@@ -10,6 +10,8 @@ define(['logme'], function (logme) {
function updateInput(state, checkFirst) {
var inputEl, stateStr, targets, draggables, c1, c2, tempObj;
logme('updateInput; state = ', state);
if (checkFirst === true) {
if (checkIfHasAnswer() === true) {
return;
......@@ -126,7 +128,7 @@ define(['logme'], function (logme) {
return;
}
draggable.setInContainer(false);
draggable.inContainer = false;
draggable.containerEl.hide();
draggable.iconEl.detach();
......@@ -196,7 +198,7 @@ define(['logme'], function (logme) {
);
}
draggable.setOnTarget(target);
draggable.onTarget = target;
target.draggable.push(draggableId);
if (target.numTextEl !== null) {
......@@ -244,7 +246,7 @@ define(['logme'], function (logme) {
return;
}
draggable.setInContainer(false);
draggable.inContainer = false;
draggable.containerEl.hide();
draggable.iconEl.detach();
......
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