Flex is the new black
@@ -445,7 +459,7 @@
background-image:url("http://placehold.it/350x250/e868a2/fff/image6.jpg");
}
.card-body{
- padding: 15px;
+ padding: 15px 15px 5px 15px;
color: #555;
}
.card-title{
diff --git a/src/commands/view/CommandAbstract.js b/src/commands/view/CommandAbstract.js
index 785bf81ed..ef849ec9d 100644
--- a/src/commands/view/CommandAbstract.js
+++ b/src/commands/view/CommandAbstract.js
@@ -17,9 +17,11 @@ define(['backbone'],
this.canvasId = this.config.canvasId || '';
this.wrapperId = this.config.wrapperId || 'wrapper';
this.pfx = this.config.stylePrefix;
+ this.ppfx = this.config.pStylePrefix;
this.hoverClass = this.pfx + 'hover';
this.badgeClass = this.pfx + 'badge';
this.plhClass = this.pfx + 'placeholder';
+ this.freezClass = this.ppfx + 'freezed';
if(this.editorModel.get)
this.setElement(this.editorModel.get('$editor').find('#'+this.canvasId));
this.$canvas = this.$el;
diff --git a/src/commands/view/MoveComponent.js b/src/commands/view/MoveComponent.js
index 90cd2273c..d49daf48f 100644
--- a/src/commands/view/MoveComponent.js
+++ b/src/commands/view/MoveComponent.js
@@ -8,7 +8,7 @@ define(['backbone', './SelectComponent','./SelectPosition'],
init: function(o){
SelectComponent.init.apply(this, arguments);
- _.bindAll(this,'startMove','onMove','endMove','rollback','selectingPosition','itemLeft');
+ _.bindAll(this,'initSorter','startMove','onMove','endMove','rollback','selectingPosition','itemLeft', 'onEndMove');
this.opt = o;
this.hoverClass = this.pfx + 'hover-move';
this.badgeClass = this.pfx + 'badge-yellow';
@@ -19,20 +19,38 @@ define(['backbone', './SelectComponent','./SelectPosition'],
this.canvasTop = this.$canvas.offset().top;
this.canvasLeft = this.$canvas.offset().left;
this.$el.css('cursor','move');
- this.$el.on('mousedown', this.startMove);
+ //this.$el.on('mousedown', this.startMove);
+ this.$el.on('mousedown', this.initSorter);
this.startSelectComponent();
//Avoid strange moving behavior
this.$el.addClass(this.noSelClass);
},
+ /**
+ * Delegate sorting
+ * @param {Event} e
+ * */
+ initSorter: function(e){
+ if(this.sorter)
+ this.sorter.startSort(e.target);
+ this.stopSelectComponent(e);
+ this.$el.off('mousedown', this.initSorter);
+ },
+
+ /**
+ * Callback after sorting
+ */
+ onEndMove: function(){
+ this.enable();
+ },
+
/**
* Hover command
* @param {Object} e
* @private
*/
- onHover: function(e)
- {
+ onHover: function(e) {
e.stopPropagation();
var $this = $(e.target);
@@ -140,7 +158,7 @@ define(['backbone', './SelectComponent','./SelectPosition'],
* */
freezeComponent: function($component){
$component.css({'pointer-events':'none'});
- $component.addClass('freezed');
+ $component.addClass(this.freezClass);
},
/** Make component touchable
@@ -149,7 +167,7 @@ define(['backbone', './SelectComponent','./SelectPosition'],
* */
unfreezeComponent: function($component){
$component.css({'pointer-events':'auto'});
- $component.removeClass('freezed');
+ $component.removeClass(this.freezClass);
},
/** Used to bring the previous situation before start moving the component
@@ -179,7 +197,23 @@ define(['backbone', './SelectComponent','./SelectPosition'],
$(document).off('keypress', this.rollback);
},
- run: function(){
+ run: function(editor, sender, opts){
+ this.editor = editor;
+
+ // Activate sorter, at any run? In layers, is called once at any stack
+ var utils = this.editor.Utils;
+ if(utils && utils.Sorter)
+ this.sorter = new utils.Sorter({
+ container: this.$el.get(0),
+ containerSel: '*',
+ itemSel: '*',
+ pfx: this.ppfx,
+ onEndMove: this.onEndMove,
+ direction: 'a',
+ nested: 1,
+ freezeClass: this.freezClass,
+ });
+
this.enable();
},
diff --git a/src/dom_components/view/ComponentView.js b/src/dom_components/view/ComponentView.js
index 8e278e581..98d5e36ed 100644
--- a/src/dom_components/view/ComponentView.js
+++ b/src/dom_components/view/ComponentView.js
@@ -25,6 +25,7 @@ define(['backbone', './ComponentsView'],
this.listenTo(this.model.get('classes'), 'add remove change', this.updateClasses);
this.$el.data("model", this.model);
this.$el.data("model-comp", this.components);
+ this.$el.data("collection", this.components);
if(this.model.get('classes').length)
this.importClasses();
diff --git a/src/editor/model/Editor.js b/src/editor/model/Editor.js
index 1c2ea520a..d7f77916a 100644
--- a/src/editor/model/Editor.js
+++ b/src/editor/model/Editor.js
@@ -338,6 +338,7 @@ define([
initCommands: function() {
var cfg = this.config.commands,
pfx = cfg.stylePrefix || 'com-';
+ cfg.pStylePrefix = this.config.stylePrefix;
cfg.stylePrefix = this.config.stylePrefix + pfx;
cfg.em = this;
cfg.canvasId = this.config.idCanvas;
diff --git a/src/utils/Sorter.js b/src/utils/Sorter.js
index c4e51ffa5..29f023bfb 100644
--- a/src/utils/Sorter.js
+++ b/src/utils/Sorter.js
@@ -18,6 +18,8 @@ define(['backbone'],
this.itemSel = o.itemSel || 'div';
this.nested = o.nested || 0;
this.pfx = o.pfx || '';
+ this.onEndMove = o.onEndMove || '';
+ this.direction = o.direction || 'v'; // v (vertical), h (horizontal), a (auto)
},
/**
@@ -152,7 +154,16 @@ define(['backbone'],
if(!this.matches(el, this.itemSel))
continue;
var dim = this.getDim(el);
- dim.push(true); //TODO check if in flow, now only for vertical elements
+ var dir = this.direction;
+
+ if(dir == 'v')
+ dir = true;
+ else if(dir == 'h')
+ dir = false;
+ else
+ dir = this.isInFlow(el, elem);
+
+ dim.push(dir);
dim.push(el);
dims.push(dim);
}
@@ -169,6 +180,60 @@ define(['backbone'],
return [o.top - this.elT, o.left - this.elL, el.offsetHeight, el.offsetWidth];
},
+ /**
+ * Returns true if the elements is in flow, so is not in flow where
+ * for example the component is with float:left
+ * @param {HTMLElement} el
+ * @param {HTMLElement} parent
+ * @return {Boolean}
+ * @private
+ * */
+ isInFlow: function(el, parent) {
+ if(!el)
+ return false;
+
+ parent = parent || document.body;
+ var ch = -1, h;
+ var elem = el;
+ //while (elem !== document.body) {
+ h = elem.offsetHeight;
+ if (h < ch || !this.styleInFlow(elem, parent))
+ return false;
+ else
+ return true;
+ },
+
+ /**
+ * Check if el has style to be in flow
+ * @param {HTMLElement} el
+ * @param {HTMLElement} parent
+ * @return {Boolean}
+ * @private
+ */
+ styleInFlow: function(el, parent) {
+ var style = el.style;
+ if (style.float && style.float !== 'none')
+ return;
+ if (style.overflow && style.overflow !== 'visible')
+ return;
+ if(parent && $(parent).css('display') == 'flex')
+ return;
+ switch (style.position) {
+ case 'static': case 'relative': case '':
+ break;
+ default:
+ return;
+ }
+ var disp = $(el).css('display');
+ switch (disp) {
+ case 'block':
+ case 'list-item':
+ case 'table':
+ return true;
+ }
+ return;
+ },
+
/**
* Get dimensions of nodes relative to the coordinates
* @param {HTMLElement} target
@@ -315,9 +380,8 @@ define(['backbone'],
t = elDim[0] + marg;
l = (method == 'before') ? (elDim[1] - marg) : (elDim[1] + elDim[3] - marg);
}else{
- //w = '100%';
w = elDim[3] + un;
- //h = elDim[3] + un;
+ h = 'auto';
t = (method == 'before') ? (elDim[0] - marg) : (elDim[0] + elDim[2] - marg);
l = elDim[1];
}
@@ -327,9 +391,10 @@ define(['backbone'],
return;
}
if(trgDim){
- t = trgDim[0] + margI + 17;
- l = trgDim[1] + margI * 7;
- w = (parseInt(trgDim[3]) - margI * 14) + un;
+ t = trgDim[0] + margI;
+ l = trgDim[1] + margI;
+ w = (parseInt(trgDim[3]) - margI * 2) + un;
+ h = 'auto';
}
}
plh.style.top = t + un;
@@ -355,6 +420,9 @@ define(['backbone'],
this.eV.className = this.eV.className.replace(clsReg, '');
if(this.moved)
this.move(this.target, this.eV, this.lastPos);
+
+ if(typeof this.onEndMove === 'function')
+ this.onEndMove();
},
/**
@@ -367,9 +435,12 @@ define(['backbone'],
var index = pos.index;
var model = $(src).data('model');
var collection = model.collection;
- var targetCollection = $(dst).data('collection');
+ var $dst = $(dst);
+ var targetCollection = $dst.data('collection');
+ var targetModel = $dst.data('model');
+ var droppable = targetModel ? targetModel.get('droppable') : 1;
- if(targetCollection){// && targetModel.get('droppable')
+ if(targetCollection && droppable){ // TODO && targetModel.get('droppable')
index = pos.method === 'after' ? index + 1 : index;
var modelTemp = targetCollection.add({}, {at: index, noIncrement: 1});
var modelRemoved = model.collection.remove(model);
diff --git a/styles/css/main.css b/styles/css/main.css
index 715f41df2..224ea1b9e 100644
--- a/styles/css/main.css
+++ b/styles/css/main.css
@@ -2602,6 +2602,11 @@ See http://bgrins.github.io/spectrum/themes/ for instructions.
height: 100%;
min-width: 1250px; }
+.wte-freezed {
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+ pointer-events: none; }
+
/************* CANVAS ****************/
.wte-cv-canvas {
position: absolute;
@@ -2612,7 +2617,7 @@ See http://bgrins.github.io/spectrum/themes/ for instructions.
overflow: auto;
z-index: 1;
/* This simulate body behaviour */ }
- .wte-cv-canvas > div {
+ .wte-cv-canvas > div:first-child {
background-color: #fff;
position: relative;
height: 100%;
diff --git a/styles/scss/main.scss b/styles/scss/main.scss
index ef82b4d5d..6c1d3c117 100644
--- a/styles/scss/main.scss
+++ b/styles/scss/main.scss
@@ -87,6 +87,10 @@ $imageCompDim: 50px;
height: 100%;
min-width: 1250px;
}
+.#{$app-prefix}freezed{
+ @include opacity(0.50);
+ pointer-events: none;
+}
/************* CANVAS ****************/
.#{$cv-prefix}canvas {
position: absolute;
@@ -97,7 +101,7 @@ $imageCompDim: 50px;
z-index:1;
/* This simulate body behaviour */
- > div {
+ > div:first-child {
background-color: #fff;
position: relative;
height: 100%;
diff --git a/test/specs/utils/Sorter.js b/test/specs/utils/Sorter.js
index fdc7a3213..bc14c640e 100644
--- a/test/specs/utils/Sorter.js
+++ b/test/specs/utils/Sorter.js
@@ -11,6 +11,7 @@ define([path + 'Sorter',],
var obj;
var parent;
var plh;
+ var html;
before(function () {
fixture = $('
').get(0);
@@ -24,11 +25,38 @@ define([path + 'Sorter',],
obj = new Sorter({container: '.parent1'});
document.body.appendChild(fixture);
fixture.appendChild(parent);
+ html = '
'+
+ '
ba' +
+ '
baa
' +
+ '
bab' +
+ '
bac'+
+ '
eldiv
'+
+ '
' +
+ '
' +
+ '
' +
+ '
aa' +
+ '
aaa
' +
+ '
aab' +
+ '
aac' +
+ '
' +
+ '
ab
' +
+ '
ac' +
+ '
aca
' +
+ '
acb
' +
+ '
' +
+ '
ad' +
+ '
ada
' +
+ '
adb' +
+ '
adc' +
+ '
' +
+ '
';
});
afterEach(function () {
document.body.removeChild(fixture);
delete obj;
+ delete parent;
+ delete html;
});
it('matches class', function() {
@@ -61,6 +89,102 @@ define([path + 'Sorter',],
obj.createPlaceholder().className.should.equal('placeholder');
});
+ it('isInFlow to overflow hidden', function(){
+ parent.innerHTML = html;
+ var el = parent.querySelector('#el1');
+ obj.isInFlow(el).should.equal(false);
+ });
+
+ it('isInFlow inner to overflow', function(){
+ parent.innerHTML = html;
+ var el = parent.querySelector('#el2');
+ if(!el){
+ console.log('phantom issue');
+ return;
+ }
+ obj.isInFlow(el).should.equal(true);
+ });
+
+ it('isInFlow for span', function(){
+ parent.innerHTML = html;
+ var el = parent.querySelector('#elspan');
+ obj.isInFlow(el).should.equal(false);
+ });
+
+ it('isInFlow for div #a', function(){
+ parent.innerHTML = html;
+ var el = parent.querySelector('#a');
+ if(!el){
+ console.log('phantom issue');
+ return;
+ }
+ obj.isInFlow(el).should.equal(true);
+ });
+
+ it('isInFlow for div #aa', function(){
+ parent.innerHTML = html;
+ var el = parent.querySelector('#aa');
+ if(!el){
+ console.log('phantom issue');
+ return;
+ }
+ obj.isInFlow(el).should.equal(true);
+ });
+
+ it('isInFlow for p #aaa', function(){
+ parent.innerHTML = html;
+ var el = parent.querySelector('#aaa');
+ if(!el){
+ console.log('phantom issue');
+ return;
+ }
+ obj.isInFlow(el).should.equal(true);
+ });
+
+ it('isInFlow for span #aab', function(){
+ parent.innerHTML = html;
+ var el = parent.querySelector('#aab');
+ obj.isInFlow(el).should.equal(false);
+ });
+
+ it('isInFlow for span #aac with display block', function(){
+ parent.innerHTML = html;
+ var el = parent.querySelector('#aac');
+ if(!el) // in phantom doesnt work
+ return;
+ obj.isInFlow(el).should.equal(true);
+ });
+
+ it('isInFlow for div #ab with float left', function(){
+ parent.innerHTML = html;
+ var el = parent.querySelector('#ab');
+ obj.isInFlow(el).should.equal(false);
+ });
+
+ it('isInFlow for div #ac in absolute', function(){
+ parent.innerHTML = html;
+ var el = parent.querySelector('#ac');
+ obj.isInFlow(el).should.equal(false);
+ });
+
+ it('isInFlow for div #acb inside absolute', function(){
+ parent.innerHTML = html;
+ var el = parent.querySelector('#acb');
+ if(!el){
+ console.log('phantom issue');
+ return;
+ }
+ obj.isInFlow(el).should.equal(true);
+ });
+
+ it('isInFlow for div #ad overflow hidden', function(){
+ parent.innerHTML = html;
+ var el = parent.querySelector('#ad');
+ obj.isInFlow(el).should.equal(false);
+ });
+
+
+
describe('Closest method', function() {
var parent2;
var parent3;