Browse Source

Setup relative positioning while sorting components

pull/79/merge
Artur Arseniev 9 years ago
parent
commit
492a8805db
  1. 3
      src/block_manager/view/BlocksView.js
  2. 24
      src/canvas/main.js
  3. 294
      src/commands/view/MoveComponent.js
  4. 185
      src/commands/view/SelectPosition.js
  5. 55
      src/utils/Sorter.js

3
src/block_manager/view/BlocksView.js

@ -40,7 +40,8 @@ function(Backbone, BlockView) {
direction: 'a', direction: 'a',
wmargin: 1, wmargin: 1,
nested: 1, nested: 1,
em: this.em em: this.em,
canvasRelative: 1,
}); });
} }
return this.sorter; return this.sorter;

24
src/canvas/main.js

@ -283,8 +283,8 @@ define(function(require) {
var yOffset = subWinOffset ? win.pageYOffset : 0; var yOffset = subWinOffset ? win.pageYOffset : 0;
var xOffset = subWinOffset ? win.pageXOffset : 0; var xOffset = subWinOffset ? win.pageXOffset : 0;
if(frame) { if (frame) {
var frameRect = frame.getBoundingClientRect(); // maybe to cache ?!? var frameRect = frame.getBoundingClientRect();
addTop = frameRect.top || 0; addTop = frameRect.top || 0;
addLeft = frameRect.left || 0; addLeft = frameRect.left || 0;
} }
@ -295,6 +295,26 @@ define(function(require) {
}; };
}, },
/**
* X and Y mouse position relative to the canvas
* @param {Event} e
* @return {Object}
*/
getMouseRelativeCanvas: function (e, options) {
var opts = options || {};
var frame = this.getFrameEl();
var body = this.getBody();
var addTop = frame.offsetTop || 0;
var addLeft = frame.offsetLeft || 0;
var yOffset = body.scrollTop || 0;
var xOffset = body.scrollLeft || 0;
return {
y: e.clientY + addTop + yOffset,
x: e.clientX + addLeft + xOffset,
};
},
/** /**
* Returns wrapper element * Returns wrapper element
* @return {HTMLElement} * @return {HTMLElement}

294
src/commands/view/MoveComponent.js

@ -1,148 +1,148 @@
define(['backbone', './SelectComponent','./SelectPosition'], define(['backbone', './SelectComponent','./SelectPosition'],
function(Backbone, SelectComponent, SelectPosition) { function(Backbone, SelectComponent, SelectPosition) {
return _.extend({}, SelectPosition, SelectComponent, { return _.extend({}, SelectPosition, SelectComponent, {
init: function(o){ init: function(o){
SelectComponent.init.apply(this, arguments); SelectComponent.init.apply(this, arguments);
_.bindAll(this, 'initSorter','rollback', 'onEndMove'); _.bindAll(this, 'initSorter','rollback', 'onEndMove');
this.opt = o; this.opt = o;
this.hoverClass = this.ppfx + 'highlighter-warning'; this.hoverClass = this.ppfx + 'highlighter-warning';
this.badgeClass = this.ppfx + 'badge-warning'; this.badgeClass = this.ppfx + 'badge-warning';
this.noSelClass = this.ppfx + 'no-select'; this.noSelClass = this.ppfx + 'no-select';
}, },
enable: function() { enable: function() {
SelectComponent.enable.apply(this, arguments); SelectComponent.enable.apply(this, arguments);
this.getBadgeEl().addClass(this.badgeClass); this.getBadgeEl().addClass(this.badgeClass);
this.getHighlighterEl().addClass(this.hoverClass); this.getHighlighterEl().addClass(this.hoverClass);
var wp = this.$wrapper; var wp = this.$wrapper;
wp.css('cursor','move'); wp.css('cursor','move');
wp.on('mousedown', this.initSorter); wp.on('mousedown', this.initSorter);
// Avoid strange moving behavior // Avoid strange moving behavior
wp.addClass(this.noSelClass); wp.addClass(this.noSelClass);
}, },
/** /**
* Overwrite for doing nothing * Overwrite for doing nothing
* @private * @private
*/ */
toggleClipboard: function(){}, toggleClipboard: function(){},
/** /**
* Delegate sorting * Delegate sorting
* @param {Event} e * @param {Event} e
* @private * @private
* */ * */
initSorter: function(e){ initSorter: function(e){
var el = $(e.target).data('model'); var el = $(e.target).data('model');
var drag = el.get('draggable'); var drag = el.get('draggable');
if(!drag) if(!drag)
return; return;
// Avoid badge showing on move // Avoid badge showing on move
this.cacheEl = null; this.cacheEl = null;
this.startSelectPosition(e.target, this.frameEl.contentDocument); this.startSelectPosition(e.target, this.frameEl.contentDocument);
this.sorter.draggable = drag; this.sorter.draggable = drag;
this.sorter.onEndMove = this.onEndMove.bind(this); this.sorter.onEndMove = this.onEndMove.bind(this);
this.stopSelectComponent(); this.stopSelectComponent();
this.$wrapper.off('mousedown', this.initSorter); this.$wrapper.off('mousedown', this.initSorter);
this.getContentWindow().on('keydown', this.rollback); this.getContentWindow().on('keydown', this.rollback);
}, },
/** /**
* Init sorter from model * Init sorter from model
* @param {Object} model * @param {Object} model
* @private * @private
*/ */
initSorterFromModel: function(model) { initSorterFromModel: function(model) {
var drag = model.get('draggable'); var drag = model.get('draggable');
if(!drag) if(!drag)
return; return;
// Avoid badge showing on move // Avoid badge showing on move
this.cacheEl = null; this.cacheEl = null;
var el = model.view.el; var el = model.view.el;
this.startSelectPosition(el, this.frameEl.contentDocument); this.startSelectPosition(el, this.frameEl.contentDocument);
this.sorter.draggable = drag; this.sorter.draggable = drag;
this.sorter.onEndMove = this.onEndMoveFromModel.bind(this); this.sorter.onEndMove = this.onEndMoveFromModel.bind(this);
/* /*
this.sorter.setDragHelper(el); this.sorter.setDragHelper(el);
var dragHelper = this.sorter.dragHelper; var dragHelper = this.sorter.dragHelper;
dragHelper.className = this.ppfx + 'drag-helper'; dragHelper.className = this.ppfx + 'drag-helper';
dragHelper.innerHTML = ''; dragHelper.innerHTML = '';
dragHelper.backgroundColor = 'white'; dragHelper.backgroundColor = 'white';
*/ */
this.stopSelectComponent(); this.stopSelectComponent();
this.getContentWindow().on('keydown', this.rollback); this.getContentWindow().on('keydown', this.rollback);
}, },
onEndMoveFromModel: function() { onEndMoveFromModel: function() {
this.getContentWindow().off('keydown', this.rollback); this.getContentWindow().off('keydown', this.rollback);
}, },
/** /**
* Callback after sorting * Callback after sorting
* @private * @private
*/ */
onEndMove: function(){ onEndMove: function(){
this.enable(); this.enable();
this.getContentWindow().off('keydown', this.rollback); this.getContentWindow().off('keydown', this.rollback);
}, },
/** /**
* Say what to do after the component was selected (selectComponent) * Say what to do after the component was selected (selectComponent)
* @param {Event} e * @param {Event} e
* @param {Object} Selected element * @param {Object} Selected element
* @private * @private
* */ * */
onSelect: function(e,el){}, onSelect: function(e,el){},
/** /**
* Used to bring the previous situation before start moving the component * Used to bring the previous situation before start moving the component
* @param {Event} e * @param {Event} e
* @param {Boolean} Indicates if rollback in anycase * @param {Boolean} Indicates if rollback in anycase
* @private * @private
* */ * */
rollback: function(e, force){ rollback: function(e, force){
var key = e.which || e.keyCode; var key = e.which || e.keyCode;
if(key == this.opt.ESCAPE_KEY || force){ if(key == this.opt.ESCAPE_KEY || force){
this.sorter.moved = false; this.sorter.moved = false;
this.sorter.endMove(); this.sorter.endMove();
} }
return; return;
}, },
/** /**
* Returns badge element * Returns badge element
* @return {HTMLElement} * @return {HTMLElement}
* @private * @private
*/ */
getBadgeEl: function(){ getBadgeEl: function(){
if(!this.$badge) if(!this.$badge)
this.$badge = $(this.getBadge()); this.$badge = $(this.getBadge());
return this.$badge; return this.$badge;
}, },
/** /**
* Returns highlighter element * Returns highlighter element
* @return {HTMLElement} * @return {HTMLElement}
* @private * @private
*/ */
getHighlighterEl: function(){ getHighlighterEl: function(){
if(!this.$hl) if(!this.$hl)
this.$hl = $(this.canvas.getHighlighter()); this.$hl = $(this.canvas.getHighlighter());
return this.$hl; return this.$hl;
}, },
stop: function(){ stop: function(){
SelectComponent.stop.apply(this, arguments); SelectComponent.stop.apply(this, arguments);
this.getBadgeEl().removeClass(this.badgeClass); this.getBadgeEl().removeClass(this.badgeClass);
this.getHighlighterEl().removeClass(this.hoverClass); this.getHighlighterEl().removeClass(this.hoverClass);
var wp = this.$wrapper; var wp = this.$wrapper;
wp.css('cursor', '').unbind().removeClass(this.noSelClass); wp.css('cursor', '').unbind().removeClass(this.noSelClass);
} }
}); });
}); });

185
src/commands/view/SelectPosition.js

@ -1,102 +1,103 @@
define(function() { define(function() {
return { return {
/** /**
* Start select position event * Start select position event
* @param {HTMLElement} trg * @param {HTMLElement} trg
* @private * @private
* */ * */
startSelectPosition: function(trg, doc) { startSelectPosition: function(trg, doc) {
this.isPointed = false; this.isPointed = false;
var utils = this.editorModel.get('Utils'); var utils = this.editorModel.get('Utils');
if(utils && !this.sorter) if(utils && !this.sorter)
this.sorter = new utils.Sorter({ this.sorter = new utils.Sorter({
container: this.getCanvasBody(), container: this.getCanvasBody(),
placer: this.canvas.getPlacerEl(), placer: this.canvas.getPlacerEl(),
containerSel: '*', containerSel: '*',
itemSel: '*', itemSel: '*',
pfx: this.ppfx, pfx: this.ppfx,
direction: 'a', direction: 'a',
document: doc, document: doc,
wmargin: 1, wmargin: 1,
nested: 1, nested: 1,
em: this.editorModel, em: this.editorModel,
}); canvasRelative: 1,
this.sorter.startSort(trg); });
}, this.sorter.startSort(trg);
},
/** /**
* Get frame position * Get frame position
* @return {Object} * @return {Object}
* @private * @private
*/ */
getOffsetDim: function() { getOffsetDim: function() {
var frameOff = this.offset(this.canvas.getFrameEl()); var frameOff = this.offset(this.canvas.getFrameEl());
var canvasOff = this.offset(this.canvas.getElement()); var canvasOff = this.offset(this.canvas.getElement());
var top = frameOff.top - canvasOff.top; var top = frameOff.top - canvasOff.top;
var left = frameOff.left - canvasOff.left; var left = frameOff.left - canvasOff.left;
return { top: top, left: left }; return { top: top, left: left };
}, },
/** /**
* Stop select position event * Stop select position event
* @private * @private
* */ * */
stopSelectPosition: function() { stopSelectPosition: function() {
this.posTargetCollection = null; this.posTargetCollection = null;
this.posIndex = this.posMethod=='after' && this.cDim.length!==0 ? this.posIndex + 1 : this.posIndex; //Normalize this.posIndex = this.posMethod=='after' && this.cDim.length!==0 ? this.posIndex + 1 : this.posIndex; //Normalize
if(this.sorter){ if(this.sorter){
this.sorter.moved = 0; this.sorter.moved = 0;
this.sorter.endMove(); this.sorter.endMove();
} }
if(this.cDim){ if(this.cDim){
this.posIsLastEl = this.cDim.length!==0 && this.posMethod=='after' && this.posIndex==this.cDim.length; this.posIsLastEl = this.cDim.length!==0 && this.posMethod=='after' && this.posIndex==this.cDim.length;
this.posTargetEl = (this.cDim.length===0 ? $(this.outsideElem) : this.posTargetEl = (this.cDim.length===0 ? $(this.outsideElem) :
(!this.posIsLastEl && this.cDim[this.posIndex] ? $(this.cDim[this.posIndex][5]).parent() : $(this.outsideElem) )); (!this.posIsLastEl && this.cDim[this.posIndex] ? $(this.cDim[this.posIndex][5]).parent() : $(this.outsideElem) ));
this.posTargetModel = this.posTargetEl.data("model"); this.posTargetModel = this.posTargetEl.data("model");
this.posTargetCollection = this.posTargetEl.data("model-comp"); this.posTargetCollection = this.posTargetEl.data("model-comp");
} }
}, },
/** /**
* Enabel select position * Enabel select position
* @private * @private
*/ */
enable: function() { enable: function() {
this.startSelectPosition(); this.startSelectPosition();
}, },
/** /**
* Check if the pointer is near to the float component * Check if the pointer is near to the float component
* @param {number} index * @param {number} index
* @param {string} method * @param {string} method
* @param {Array<Array>} dims * @param {Array<Array>} dims
* @return {Boolean} * @return {Boolean}
* @private * @private
* */ * */
nearFloat: function(index, method, dims) { nearFloat: function(index, method, dims) {
var i = index || 0; var i = index || 0;
var m = method || 'before'; var m = method || 'before';
var len = dims.length; var len = dims.length;
var isLast = len !== 0 && m == 'after' && i == len; var isLast = len !== 0 && m == 'after' && i == len;
if(len !== 0 && ( if(len !== 0 && (
(!isLast && !dims[i][4]) || (!isLast && !dims[i][4]) ||
(dims[i-1] && !dims[i-1][4]) || (dims[i-1] && !dims[i-1][4]) ||
(isLast && !dims[i-1][4]) ) ) (isLast && !dims[i-1][4]) ) )
return 1; return 1;
return 0; return 0;
}, },
run: function() { run: function() {
this.enable(); this.enable();
}, },
stop: function() { stop: function() {
this.stopSelectPosition(); this.stopSelectPosition();
this.$wrapper.css('cursor',''); this.$wrapper.css('cursor','');
this.$wrapper.unbind(); this.$wrapper.unbind();
} }
}; };
}); });

55
src/utils/Sorter.js

@ -38,6 +38,7 @@ define(function(require) {
this.dropContent = null; this.dropContent = null;
this.em = o.em || ''; this.em = o.em || '';
this.dragHelper = null; this.dragHelper = null;
this.canvasRelative = o.canvasRelative || 0;
if(this.em && this.em.on){ if(this.em && this.em.on){
this.em.on('change:canvasOffset', this.udpateOffset); this.em.on('change:canvasOffset', this.udpateOffset);
@ -269,21 +270,34 @@ define(function(require) {
var eO = this.offset(this.el); var eO = this.offset(this.el);
this.elT = this.wmargin ? Math.abs(eO.top) : eO.top; this.elT = this.wmargin ? Math.abs(eO.top) : eO.top;
this.elL = this.wmargin ? Math.abs(eO.left): eO.left; this.elL = this.wmargin ? Math.abs(eO.left): eO.left;
this.rY = (e.pageY - this.elT) + this.el.scrollTop; var rY = (e.pageY - this.elT) + this.el.scrollTop;
this.rX = (e.pageX - this.elL) + this.el.scrollLeft; var rX = (e.pageX - this.elL) + this.el.scrollLeft;
var dims = this.dimsFromTarget(e.target, this.rX, this.rY);
if (this.canvasRelative && this.em) {
var mousePos = this.em.get('Canvas').getMouseRelativeCanvas(e);
rX = mousePos.x;
rY = mousePos.y;
}
var dims = this.dimsFromTarget(e.target, rX, rY);
this.lastDims = dims; this.lastDims = dims;
var pos = this.findPosition(dims, this.rX, this.rY); var pos = this.findPosition(dims, rX, rY);
// If there is a significant changes with the pointer // If there is a significant changes with the pointer
if( !this.lastPos || if( !this.lastPos ||
(this.lastPos.index != pos.index || this.lastPos.method != pos.method)){ (this.lastPos.index != pos.index || this.lastPos.method != pos.method)){
this.movePlaceholder(this.plh, dims, pos, this.prevTargetDim); this.movePlaceholder(this.plh, dims, pos, this.prevTargetDim);
if(!this.$plh) if(!this.$plh)
this.$plh = $(this.plh); this.$plh = $(this.plh);
if(this.offTop)
this.$plh.css('top', '+=' + this.offTop + 'px'); // With canvasRelative the offset is calculated automatically for
if(this.offLeft) // each element
this.$plh.css('left', '+=' + this.offLeft + 'px'); if (!this.canvasRelative) {
if(this.offTop)
this.$plh.css('top', '+=' + this.offTop + 'px');
if(this.offLeft)
this.$plh.css('left', '+=' + this.offLeft + 'px');
}
this.lastPos = pos; this.lastPos = pos;
} }
@ -411,11 +425,26 @@ define(function(require) {
* @param {HTMLElement} el * @param {HTMLElement} el
* @return {Array<number>} * @return {Array<number>}
*/ */
getDim: function(el){ getDim: function(el) {
var o = this.offset(el); var top, left, height, width;
var top = this.relative ? el.offsetTop : o.top - (this.wmargin ? -1 : 1) * this.elT;
var left = this.relative ? el.offsetLeft : o.left - (this.wmargin ? -1 : 1) * this.elL; if (this.canvasRelative && this.em) {
return [top, left, el.offsetHeight, el.offsetWidth]; var pos = this.em.get('Canvas').getElementPos(el);
top = pos.top;
left = pos.left;
height = pos.height;
width = pos.width;
} else {
var o = this.offset(el);
top = this.relative ? el.offsetTop : o.top - (this.wmargin ? -1 : 1) * this.elT;
left = this.relative ? el.offsetLeft : o.left - (this.wmargin ? -1 : 1) * this.elL;
height = el.offsetHeight;
width = el.offsetWidth;
}
//console.log('get dim', top, left, this.canvasRelative);
return [top, left, height, width];
}, },
/** /**

Loading…
Cancel
Save