Free and Open source Web Builder Framework. Next generation tool for building templates without coding
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

269 lines
8.2 KiB

define(['backbone','./SelectPosition'],
function(Backbone, SelectPosition) {
/**
* @class CreateComponent
* */
return _.extend({},SelectPosition,{
newElement : null,
tempComponent: { style:{} },
init: function(opt) {
SelectPosition.init.apply(this, arguments);
_.bindAll(this,'startDraw','draw','endDraw','rollback');
this.config = opt;
this.heightType = this.config.newFixedH ? 'height' : 'min-height';
},
/**
* Returns creation placeholder
*
* @return {Object}
* */
getCreationPlaceholder: function()
{
return this.newElem;
},
/**
* Removes creation placeholder
*
* @return void
* */
removeCreationPlaceholder: function()
{
this.newElem.remove();
},
/**
* Start with enabling to select position and listening to start drawning
* @return void
* */
enable: function()
{
SelectPosition.enable.apply(this, arguments);
this.$el.css('cursor','crosshair');
this.enableToDraw();
},
/**
* Enable user to draw components
*
* @return void
* */
enableToDraw: function()
{
this.$el.on('mousedown', this.startDraw);
this.$el.disableSelection(); //Disable text selection
},
/**
* Start drawing component
* @param {Object} e Event
*
* @return void
* */
startDraw : function(e)
{
e.preventDefault();
this.stopSelectPosition(); //Interrupt selecting position
this.tempComponent = { style: {} }; //Reset the helper
this.isDragged = false;
this.beforeDraw(this.tempComponent);
this.getPositionPlaceholder().addClass('change-placeholder'); //Change color of the position placeholder
this.newElemOrig = { top : e.pageY, left: e.pageX };
this.newElem = $('<div>', {class: "tempComp"}).css(this.newElemOrig); //Create helper element with initial position
this.newElem.data('helper',1);
$('body').append(this.newElem); //Show helper component
this.parentElem=this.newElem.parent(); //For percent count
this.targetC = this.outsideElem;
$(document).mousemove(this.draw);
$(document).mouseup(this.endDraw);
$(document).keypress(this.rollback);
},
/**
* While drawing the component
* @param {Object} e Event
*
* @return void
* */
draw: function(e)
{
this.isDragged = true;
this.updateComponentSize(e);
},
/**
* End drawing component
* @param {Object} e Event
*
* @return void
* */
endDraw : function(e)
{
$(document).off('mouseup', this.endDraw);
$(document).off('mousemove', this.draw);
$(document).off('keypress',this.rollback);
var model = {};
if(this.isDragged){ //Only if the mouse was moved
this.updateComponentSize(e);
this.setRequirements(this.tempComponent);
model = this.create(null,this.tempComponent,this.posIndex,this.posMethod);
}
if(this.getPositionPlaceholder())
this.getPositionPlaceholder().removeClass('change-placeholder'); //Turn back the original color of the placeholder
this.startSelectPosition(); //Return with selecting new position
this.removeCreationPlaceholder(); //Remove the element used for size indication
this.afterDraw(model);
},
/**
* Create component
* @param {Object} target DOM of the target element which to push new component
* @param {Object} component New component to push
* @param {Integer} posIndex Index inside the collection, 0 if no children inside
* @param {String} method Before or after of the children
*
* @return {Object} Created model
* */
create: function(target, component, posIndex, method)
{
var index = posIndex || 0;
if(this.posTargetCollection && this.posTargetModel.get('droppable')){
//Check config parameters for center in wrapper
if(this.config.firstCentered && (this.el == this.posTargetEl.get(0)) ){
component.style.margin = '0 auto';
}
if(this.nearToFloat()) //Set not in flow if the nearest is too
component.style.float = 'left';
this.beforeCreation(component);
var model = this.posTargetCollection.add(component, { at: index, silent:false });
this.afterCreation(model);
return model;
}else
console.warn("Invalid target position");
},
/**
* Check and set basic requirements for the component
* @param {Object} component New component to be created
* @return {Object} Component updated
* */
setRequirements: function(component)
{
var c = this.config;
if(component.style.width.replace(/\D/g,'') < c.minComponentW) //Check min width
component.style.width = c.minComponentW +'px';
if(component.style[this.heightType].replace(/\D/g,'') < c.minComponentH) //Check min height
component.style[this.heightType] = c.minComponentH +'px';
if(c.newFixedH) //Set overflow in case of fixed height
component.style.overflow = 'auto';
if(!this.absoluteMode){
delete component.style.left;
delete component.style.top;
}else
component.style.position = 'absolute';
return component;
},
/**
* Update new component size while drawing
* @param {Object} e Event
*
* @return void
* */
updateComponentSize : function (e)
{
var newLeft = e.pageX;
var newTop = e.pageY;
var startLeft = this.newElemOrig.left;
var startTop = this.newElemOrig.top;
var newWidth = newLeft - startLeft;//$(this.newElem).offset().left
var newHeight = newTop - startTop;//$(this.newElem).offset().top
if (newLeft < this.newElemOrig.left) {
startLeft = newLeft;
newWidth = this.newElemOrig.left - newLeft;
}
if (newTop < this.newElemOrig.top) {
startTop = newTop;
newHeight = this.newElemOrig.top - newTop;
}
newWidth = this.absoluteMode ? (newWidth/this.parentElem.width()*100+"%") : newWidth+'px';
this.newElem[0].style.left = startLeft+'px';
this.newElem[0].style.top = startTop+'px';
this.newElem[0].style.width = newWidth;
this.newElem[0].style['min-height'] = newHeight+'px';
this.tempComponent.style.width = newWidth;
this.tempComponent.style[this.heightType] = newHeight+"px";
this.tempComponent.style.left = startLeft + "px";
this.tempComponent.style.top = startTop + "px";
},
/**
* Used to bring the previous situation before event started
* @param {Object} e Event
* @param {Boolean} forse Indicates if rollback in anycase
*
* @return void
* */
rollback: function(e, force)
{
var key = e.which || e.keyCode;
if(key == this.config.ESCAPE_KEY || force){
this.isDragged = false;
this.endDraw();
}
return;
},
/**
* This event is triggered at the beginning of a draw operation
* @param {Object} component Object component before creation
*
* @return void
* */
beforeDraw: function(component){
component.editable = false;//set this component editable
},
/**
* This event is triggered at the end of a draw operation
* @param {Object} model Component model created
*
* @return void
* */
afterDraw: function(model){},
/**
* This event is triggered just before a create operation
* @param {Object} component Object component before creation
*
* @return void
* */
beforeCreation: function(component){},
/**
* This event is triggered at the end of a create operation
* @param {Object} model Component model created
*
* @return void
* */
afterCreation: function(model){},
/** Run method
* */
run: function(){
this.enable();
},
/** Stop method
* */
stop: function(){
this.removePositionPlaceholder(); //Removes placeholder from eventSelectPosition
this.$el.css('cursor',''); //Changes back aspect of the cursor
this.$el.unbind(); //Removes all attached events
}
});
});