398 lines
12 KiB
JavaScript
398 lines
12 KiB
JavaScript
/* ========================================================================
|
|
* ZUI: jquery.extensions.js
|
|
* http://zui.sexy
|
|
* ========================================================================
|
|
* Copyright (c) 2014 cnezsoft.com; Licensed MIT
|
|
* ======================================================================== */
|
|
|
|
|
|
(function($, window){
|
|
'use strict';
|
|
|
|
/* Check jquery */
|
|
if (typeof($) === 'undefined') throw new Error('ZUI requires jQuery');
|
|
|
|
// ZUI shared object
|
|
if (!$.zui) $.zui = function(obj)
|
|
{
|
|
if ($.isPlainObject(obj))
|
|
{
|
|
$.extend($.zui, obj);
|
|
}
|
|
};
|
|
|
|
var lastUuidAmend = 0;
|
|
$.zui(
|
|
{
|
|
uuid: function()
|
|
{
|
|
return (new Date()).getTime() * 1000 + (lastUuidAmend++) % 1000;
|
|
},
|
|
|
|
callEvent: function(func, event, proxy)
|
|
{
|
|
if ($.isFunction(func))
|
|
{
|
|
if (typeof proxy != 'undefined')
|
|
{
|
|
func = $.proxy(func, proxy);
|
|
}
|
|
var result = func(event);
|
|
if (event) event.result = result;
|
|
return !(result !== undefined && (!result));
|
|
}
|
|
return 1;
|
|
},
|
|
|
|
clientLang: function()
|
|
{
|
|
var lang;
|
|
var config = window.config;
|
|
if (typeof(config) != 'undefined' && config.clientLang)
|
|
{
|
|
lang = config.clientLang;
|
|
}
|
|
else
|
|
{
|
|
var hl = $('html').attr('lang');
|
|
lang = hl ? hl : (navigator.userLanguage || navigator.userLanguage || 'zh_cn');
|
|
}
|
|
return lang.replace('-', '_').toLowerCase();
|
|
}
|
|
});
|
|
|
|
$.fn.callEvent = function(name, event, model)
|
|
{
|
|
var $this = $(this);
|
|
var dotIndex = name.indexOf('.zui.');
|
|
var shortName = name;
|
|
if (dotIndex < 0 && model && model.name)
|
|
{
|
|
name += '.' + model.name;
|
|
}
|
|
else
|
|
{
|
|
shortName = name.substring(0, dotIndex);
|
|
}
|
|
var e = $.Event(name, event);
|
|
|
|
if ((typeof model === 'undefined') && dotIndex > 0)
|
|
{
|
|
model = $this.data(name.substring(dotIndex + 1));
|
|
}
|
|
|
|
if (model && model.options)
|
|
{
|
|
var func = model.options[shortName];
|
|
if ($.isFunction(func))
|
|
{
|
|
$.zui.callEvent(model.options[shortName], e, model);
|
|
}
|
|
}
|
|
return e;
|
|
};
|
|
}(jQuery, window));
|
|
|
|
|
|
/* ========================================================================
|
|
* ZUI: droppable.js
|
|
* http://zui.sexy
|
|
* ========================================================================
|
|
* Copyright (c) 2014 cnezsoft.com; Licensed MIT
|
|
* ======================================================================== */
|
|
|
|
|
|
(function($, document, Math)
|
|
{
|
|
'use strict';
|
|
|
|
var Droppable = function(element, options)
|
|
{
|
|
this.$ = $(element);
|
|
this.options = this.getOptions(options);
|
|
|
|
this.init();
|
|
};
|
|
|
|
Droppable.DEFAULTS = {
|
|
container: 'body',
|
|
// flex: false,
|
|
// nested: false,
|
|
deviation: 5,
|
|
sensorOffsetX: 0,
|
|
sensorOffsetY: 0
|
|
};
|
|
|
|
Droppable.prototype.getOptions = function(options)
|
|
{
|
|
options = $.extend(
|
|
{}, Droppable.DEFAULTS, this.$.data(), options);
|
|
return options;
|
|
};
|
|
|
|
Droppable.prototype.callEvent = function(name, params)
|
|
{
|
|
return $.zui.callEvent(this.options[name], params, this);
|
|
};
|
|
|
|
Droppable.prototype.init = function()
|
|
{
|
|
this.handleMouseEvents();
|
|
};
|
|
|
|
Droppable.prototype.handleMouseEvents = function()
|
|
{
|
|
var $e = this.$,
|
|
self = this,
|
|
setting = this.options,
|
|
BEFORE = 'before';
|
|
|
|
this.$triggerTarget = (setting.trigger ? ($.isFunction(setting.trigger) ? setting.trigger($e) : $e.find(setting.trigger)).first() : $e);
|
|
|
|
this.$triggerTarget.on('mousedown', function(event)
|
|
{
|
|
if (setting.hasOwnProperty(BEFORE) && $.isFunction(setting[BEFORE]))
|
|
{
|
|
var isSure = setting[BEFORE](
|
|
{
|
|
event: event,
|
|
element: $e
|
|
});
|
|
if (isSure !== undefined && (!isSure)) return;
|
|
}
|
|
|
|
var $targets = $.isFunction(setting.target) ? setting.target($e) : $(setting.target),
|
|
target = null,
|
|
shadow = null,
|
|
$container = $(setting.container).first(),
|
|
isIn = false,
|
|
isSelf = true,
|
|
oldCssPosition,
|
|
startOffset = $e.offset(),
|
|
startMouseOffset = {
|
|
left: event.pageX,
|
|
top: event.pageY
|
|
};
|
|
var containerOffset = $container.offset();
|
|
var clickOffset = {
|
|
left: startMouseOffset.left - startOffset.left,
|
|
top: startMouseOffset.top - startOffset.top
|
|
};
|
|
var lastMouseOffset = {
|
|
left: startMouseOffset.left,
|
|
top: startMouseOffset.top
|
|
};
|
|
|
|
$e.addClass('drag-from');
|
|
$(document).bind('mousemove', mouseMove).bind('mouseup', mouseUp);
|
|
event.preventDefault();
|
|
|
|
function mouseMove(event)
|
|
{
|
|
var mouseOffset = {
|
|
left: event.pageX,
|
|
top: event.pageY
|
|
};
|
|
|
|
// ignore small move
|
|
if (Math.abs(mouseOffset.left - startMouseOffset.left) < setting.deviation && Math.abs(mouseOffset.top - startMouseOffset.top) < setting.deviation) return;
|
|
|
|
if (shadow === null) // create shadow
|
|
{
|
|
var cssPosition = $container.css('position');
|
|
if (cssPosition != 'absolute' && cssPosition != 'relative' && cssPosition != 'fixed')
|
|
{
|
|
oldCssPosition = cssPosition;
|
|
$container.css('position', 'relative');
|
|
}
|
|
|
|
shadow = $e.clone().removeClass('drag-from').addClass('drag-shadow').css(
|
|
{
|
|
position: 'absolute',
|
|
width: $e.outerWidth(),
|
|
transition: 'none'
|
|
}).appendTo($container);
|
|
$e.addClass('dragging');
|
|
|
|
self.callEvent('start',
|
|
{
|
|
event: event,
|
|
element: $e
|
|
});
|
|
}
|
|
|
|
var offset = {
|
|
left: mouseOffset.left - clickOffset.left,
|
|
top: mouseOffset.top - clickOffset.top
|
|
};
|
|
var position = {
|
|
left: offset.left - containerOffset.left,
|
|
top: offset.top - containerOffset.top
|
|
};
|
|
shadow.css(position);
|
|
lastMouseOffset.left = mouseOffset.left;
|
|
lastMouseOffset.top = mouseOffset.top;
|
|
|
|
var isNew = false;
|
|
isIn = false;
|
|
|
|
if (!setting.flex)
|
|
{
|
|
$targets.removeClass('drop-to');
|
|
}
|
|
|
|
var newTarget = null;
|
|
$targets.each(function()
|
|
{
|
|
var t = $(this);
|
|
var tPos = t.offset();
|
|
var tW = t.outerWidth(),
|
|
tH = t.outerHeight(),
|
|
tX = tPos.left + setting.sensorOffsetX,
|
|
tY = tPos.top + setting.sensorOffsetY;
|
|
|
|
if (mouseOffset.left > tX && mouseOffset.top > tY && mouseOffset.left < (tX + tW) && mouseOffset.top < (tY + tH))
|
|
{
|
|
if (newTarget) newTarget.removeClass('drop-to');
|
|
newTarget = t;
|
|
if (!setting.nested) return false;
|
|
}
|
|
});
|
|
|
|
if (newTarget)
|
|
{
|
|
isIn = true;
|
|
var id = newTarget.data('id');
|
|
if ($e.data('id') != id) isSelf = false;
|
|
if (target === null || (target.data('id') !== id && (!isSelf))) isNew = true;
|
|
target = newTarget;
|
|
if (setting.flex)
|
|
{
|
|
$targets.removeClass('drop-to');
|
|
}
|
|
target.addClass('drop-to');
|
|
}
|
|
|
|
if (!setting.flex)
|
|
{
|
|
$e.toggleClass('drop-in', isIn);
|
|
shadow.toggleClass('drop-in', isIn);
|
|
}
|
|
else if (target !== null && target.length)
|
|
{
|
|
isIn = true;
|
|
}
|
|
|
|
self.callEvent('drag',
|
|
{
|
|
event: event,
|
|
isIn: isIn,
|
|
target: target,
|
|
element: $e,
|
|
isNew: isNew,
|
|
selfTarget: isSelf,
|
|
clickOffset: clickOffset,
|
|
offset: offset,
|
|
position:
|
|
{
|
|
left: offset.left - containerOffset.left,
|
|
top: offset.top - containerOffset.top
|
|
},
|
|
mouseOffset: mouseOffset
|
|
});
|
|
event.preventDefault();
|
|
}
|
|
|
|
function mouseUp(event)
|
|
{
|
|
if (oldCssPosition)
|
|
{
|
|
$container.css('position', oldCssPosition);
|
|
}
|
|
|
|
if (shadow === null)
|
|
{
|
|
$e.removeClass('drag-from');
|
|
$(document).unbind('mousemove', mouseMove).unbind('mouseup', mouseUp);
|
|
self.callEvent('always', {event: event, cancel: true});
|
|
return;
|
|
}
|
|
|
|
if (!isIn) target = null;
|
|
var isSure = true,
|
|
mouseOffset = {
|
|
left: event.pageX,
|
|
top: event.pageY
|
|
};
|
|
var offset = {
|
|
left: mouseOffset.left - clickOffset.left,
|
|
top: mouseOffset.top - clickOffset.top
|
|
};
|
|
var moveOffset = {
|
|
left: mouseOffset.left - lastMouseOffset.left,
|
|
top: mouseOffset.top - lastMouseOffset.top
|
|
};
|
|
lastMouseOffset.left = mouseOffset.left;
|
|
lastMouseOffset.top = mouseOffset.top;
|
|
var eventOptions = {
|
|
event: event,
|
|
isIn: isIn,
|
|
target: target,
|
|
element: $e,
|
|
isNew: (!isSelf) && target !== null,
|
|
selfTarget: isSelf,
|
|
offset: offset,
|
|
mouseOffset: mouseOffset,
|
|
position:
|
|
{
|
|
left: offset.left - containerOffset.left,
|
|
top: offset.top - containerOffset.top
|
|
},
|
|
lastMouseOffset: lastMouseOffset,
|
|
moveOffset: moveOffset
|
|
};
|
|
|
|
isSure = self.callEvent('beforeDrop', eventOptions);
|
|
|
|
if (isSure && isIn)
|
|
{
|
|
self.callEvent('drop', eventOptions);
|
|
}
|
|
|
|
$(document).unbind('mousemove', mouseMove).unbind('mouseup', mouseUp);
|
|
$targets.removeClass('drop-to');
|
|
$e.removeClass('dragging').removeClass('drag-from');
|
|
shadow.remove();
|
|
|
|
self.callEvent('finish', eventOptions);
|
|
self.callEvent('always', eventOptions);
|
|
|
|
event.preventDefault();
|
|
}
|
|
});
|
|
|
|
};
|
|
|
|
Droppable.prototype.reset = function()
|
|
{
|
|
this.$triggerTarget.off('mousedown');
|
|
this.handleMouseEvents();
|
|
};
|
|
|
|
$.fn.droppable = function(option)
|
|
{
|
|
return this.each(function()
|
|
{
|
|
var $this = $(this);
|
|
var data = $this.data('zui.droppable');
|
|
var options = typeof option == 'object' && option;
|
|
|
|
if (!data) $this.data('zui.droppable', (data = new Droppable(this, options)));
|
|
|
|
if (typeof option == 'string') data[option]();
|
|
});
|
|
};
|
|
|
|
$.fn.droppable.Constructor = Droppable;
|
|
}(jQuery, document, Math));
|