First commit

This commit is contained in:
Theodotos Andreou 2018-01-14 13:10:16 +00:00
commit c6e2478c40
13918 changed files with 2303184 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 955 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 817 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 894 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,620 @@
/*!
* jQuery blockUI plugin
* Version 2.70.0-2014.11.23
* Requires jQuery v1.7 or later
*
* Examples at: http://malsup.com/jquery/block/
* Copyright (c) 2007-2013 M. Alsup
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* Thanks to Amir-Hossein Sobhi for some excellent contributions!
*/
;(function() {
/*jshint eqeqeq:false curly:false latedef:false */
"use strict";
function setup($) {
$.fn._fadeIn = $.fn.fadeIn;
var noOp = $.noop || function() {};
// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
// confusing userAgent strings on Vista)
var msie = /MSIE/.test(navigator.userAgent);
var ie6 = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent);
var mode = document.documentMode || 0;
var setExpr = $.isFunction( document.createElement('div').style.setExpression );
// global $ methods for blocking/unblocking the entire page
$.blockUI = function(opts) { install(window, opts); };
$.unblockUI = function(opts) { remove(window, opts); };
// convenience method for quick growl-like notifications (http://www.google.com/search?q=growl)
$.growlUI = function(title, message, timeout, onClose) {
var $m = $('<div class="growlUI"></div>');
if (title) $m.append('<h1>'+title+'</h1>');
if (message) $m.append('<h2>'+message+'</h2>');
if (timeout === undefined) timeout = 3000;
// Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications
var callBlock = function(opts) {
opts = opts || {};
$.blockUI({
message: $m,
fadeIn : typeof opts.fadeIn !== 'undefined' ? opts.fadeIn : 700,
fadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000,
timeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout,
centerY: false,
showOverlay: false,
onUnblock: onClose,
css: $.blockUI.defaults.growlCSS
});
};
callBlock();
var nonmousedOpacity = $m.css('opacity');
$m.mouseover(function() {
callBlock({
fadeIn: 0,
timeout: 30000
});
var displayBlock = $('.blockMsg');
displayBlock.stop(); // cancel fadeout if it has started
displayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency
}).mouseout(function() {
$('.blockMsg').fadeOut(1000);
});
// End konapun additions
};
// plugin method for blocking element content
$.fn.block = function(opts) {
if ( this[0] === window ) {
$.blockUI( opts );
return this;
}
var fullOpts = $.extend({}, $.blockUI.defaults, opts || {});
this.each(function() {
var $el = $(this);
if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked'))
return;
$el.unblock({ fadeOut: 0 });
});
return this.each(function() {
if ($.css(this,'position') == 'static') {
this.style.position = 'relative';
$(this).data('blockUI.static', true);
}
this.style.zoom = 1; // force 'hasLayout' in ie
install(this, opts);
});
};
// plugin method for unblocking element content
$.fn.unblock = function(opts) {
if ( this[0] === window ) {
$.unblockUI( opts );
return this;
}
return this.each(function() {
remove(this, opts);
});
};
$.blockUI.version = 2.70; // 2nd generation blocking at no extra cost!
// override these in your code to change the default behavior and style
$.blockUI.defaults = {
// message displayed when blocking (use null for no message)
message: '<h1>Please wait...</h1>',
title: null, // title string; only used when theme == true
draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded)
theme: false, // set to true to use with jQuery UI themes
// styles for the message when blocking; if you wish to disable
// these and use an external stylesheet then do this in your code:
// $.blockUI.defaults.css = {};
css: {
padding: 0,
margin: 0,
width: '30%',
top: '40%',
left: '35%',
textAlign: 'center',
color: '#000',
border: '3px solid #aaa',
backgroundColor:'#fff',
cursor: 'wait'
},
// minimal style set used when themes are used
themedCSS: {
width: '30%',
top: '40%',
left: '35%'
},
// styles for the overlay
overlayCSS: {
backgroundColor: '#000',
opacity: 0.6,
cursor: 'wait'
},
// style to replace wait cursor before unblocking to correct issue
// of lingering wait cursor
cursorReset: 'default',
// styles applied when using $.growlUI
growlCSS: {
width: '350px',
top: '10px',
left: '',
right: '10px',
border: 'none',
padding: '5px',
opacity: 0.6,
cursor: 'default',
color: '#fff',
backgroundColor: '#000',
'-webkit-border-radius':'10px',
'-moz-border-radius': '10px',
'border-radius': '10px'
},
// IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
// (hat tip to Jorge H. N. de Vasconcelos)
/*jshint scripturl:true */
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',
// force usage of iframe in non-IE browsers (handy for blocking applets)
forceIframe: false,
// z-index for the blocking overlay
baseZ: 1000,
// set these to true to have the message automatically centered
centerX: true, // <-- only effects element blocking (page block controlled via css above)
centerY: true,
// allow body element to be stetched in ie6; this makes blocking look better
// on "short" pages. disable if you wish to prevent changes to the body height
allowBodyStretch: true,
// enable if you want key and mouse events to be disabled for content that is blocked
bindEvents: true,
// be default blockUI will supress tab navigation from leaving blocking content
// (if bindEvents is true)
constrainTabKey: true,
// fadeIn time in millis; set to 0 to disable fadeIn on block
fadeIn: 200,
// fadeOut time in millis; set to 0 to disable fadeOut on unblock
fadeOut: 400,
// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
timeout: 0,
// disable if you don't want to show the overlay
showOverlay: true,
// if true, focus will be placed in the first available input field when
// page blocking
focusInput: true,
// elements that can receive focus
focusableElements: ':input:enabled:visible',
// suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
// no longer needed in 2012
// applyPlatformOpacityRules: true,
// callback method invoked when fadeIn has completed and blocking message is visible
onBlock: null,
// callback method invoked when unblocking has completed; the callback is
// passed the element that has been unblocked (which is the window object for page
// blocks) and the options that were passed to the unblock call:
// onUnblock(element, options)
onUnblock: null,
// callback method invoked when the overlay area is clicked.
// setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used.
onOverlayClick: null,
// don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
quirksmodeOffsetHack: 4,
// class name of the message block
blockMsgClass: 'blockMsg',
// if it is already blocked, then ignore it (don't unblock and reblock)
ignoreIfBlocked: false
};
// private data and functions follow...
var pageBlock = null;
var pageBlockEls = [];
function install(el, opts) {
var css, themedCSS;
var full = (el == window);
var msg = (opts && opts.message !== undefined ? opts.message : undefined);
opts = $.extend({}, $.blockUI.defaults, opts || {});
if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked'))
return;
opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
if (opts.onOverlayClick)
opts.overlayCSS.cursor = 'pointer';
themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
msg = msg === undefined ? opts.message : msg;
// remove the current block (if there is one)
if (full && pageBlock)
remove(window, {fadeOut:0});
// if an existing element is being used as the blocking content then we capture
// its current place in the DOM (and current display style) so we can restore
// it when we unblock
if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
var node = msg.jquery ? msg[0] : msg;
var data = {};
$(el).data('blockUI.history', data);
data.el = node;
data.parent = node.parentNode;
data.display = node.style.display;
data.position = node.style.position;
if (data.parent)
data.parent.removeChild(node);
}
$(el).data('blockUI.onUnblock', opts.onUnblock);
var z = opts.baseZ;
// blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
// layer1 is the iframe layer which is used to supress bleed through of underlying content
// layer2 is the overlay layer which has opacity and a wait cursor (by default)
// layer3 is the message content that is displayed while blocking
var lyr1, lyr2, lyr3, s;
if (msie || opts.forceIframe)
lyr1 = $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>');
else
lyr1 = $('<div class="blockUI" style="display:none"></div>');
if (opts.theme)
lyr2 = $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>');
else
lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
if (opts.theme && full) {
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">';
if ( opts.title ) {
s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>';
}
s += '<div class="ui-widget-content ui-dialog-content"></div>';
s += '</div>';
}
else if (opts.theme) {
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">';
if ( opts.title ) {
s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || '&nbsp;')+'</div>';
}
s += '<div class="ui-widget-content ui-dialog-content"></div>';
s += '</div>';
}
else if (full) {
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>';
}
else {
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>';
}
lyr3 = $(s);
// if we have a message, style it
if (msg) {
if (opts.theme) {
lyr3.css(themedCSS);
lyr3.addClass('ui-widget-content');
}
else
lyr3.css(css);
}
// style the overlay
if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/)
lyr2.css(opts.overlayCSS);
lyr2.css('position', full ? 'fixed' : 'absolute');
// make iframe layer transparent in IE
if (msie || opts.forceIframe)
lyr1.css('opacity',0.0);
//$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
$.each(layers, function() {
this.appendTo($par);
});
if (opts.theme && opts.draggable && $.fn.draggable) {
lyr3.draggable({
handle: '.ui-dialog-titlebar',
cancel: 'li'
});
}
// ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0);
if (ie6 || expr) {
// give body 100% height
if (full && opts.allowBodyStretch && $.support.boxModel)
$('html,body').css('height','100%');
// fix ie6 issue when blocked element has a border width
if ((ie6 || !$.support.boxModel) && !full) {
var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
var fixT = t ? '(0 - '+t+')' : 0;
var fixL = l ? '(0 - '+l+')' : 0;
}
// simulate fixed position
$.each(layers, function(i,o) {
var s = o[0].style;
s.position = 'absolute';
if (i < 2) {
if (full)
s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"');
else
s.setExpression('height','this.parentNode.offsetHeight + "px"');
if (full)
s.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"');
else
s.setExpression('width','this.parentNode.offsetWidth + "px"');
if (fixL) s.setExpression('left', fixL);
if (fixT) s.setExpression('top', fixT);
}
else if (opts.centerY) {
if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
s.marginTop = 0;
}
else if (!opts.centerY && full) {
var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0;
var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
s.setExpression('top',expression);
}
});
}
// show the message
if (msg) {
if (opts.theme)
lyr3.find('.ui-widget-content').append(msg);
else
lyr3.append(msg);
if (msg.jquery || msg.nodeType)
$(msg).show();
}
if ((msie || opts.forceIframe) && opts.showOverlay)
lyr1.show(); // opacity is zero
if (opts.fadeIn) {
var cb = opts.onBlock ? opts.onBlock : noOp;
var cb1 = (opts.showOverlay && !msg) ? cb : noOp;
var cb2 = msg ? cb : noOp;
if (opts.showOverlay)
lyr2._fadeIn(opts.fadeIn, cb1);
if (msg)
lyr3._fadeIn(opts.fadeIn, cb2);
}
else {
if (opts.showOverlay)
lyr2.show();
if (msg)
lyr3.show();
if (opts.onBlock)
opts.onBlock.bind(lyr3)();
}
// bind key and mouse events
bind(1, el, opts);
if (full) {
pageBlock = lyr3[0];
pageBlockEls = $(opts.focusableElements,pageBlock);
if (opts.focusInput)
setTimeout(focus, 20);
}
else
center(lyr3[0], opts.centerX, opts.centerY);
if (opts.timeout) {
// auto-unblock
var to = setTimeout(function() {
if (full)
$.unblockUI(opts);
else
$(el).unblock(opts);
}, opts.timeout);
$(el).data('blockUI.timeout', to);
}
}
// remove the block
function remove(el, opts) {
var count;
var full = (el == window);
var $el = $(el);
var data = $el.data('blockUI.history');
var to = $el.data('blockUI.timeout');
if (to) {
clearTimeout(to);
$el.removeData('blockUI.timeout');
}
opts = $.extend({}, $.blockUI.defaults, opts || {});
bind(0, el, opts); // unbind events
if (opts.onUnblock === null) {
opts.onUnblock = $el.data('blockUI.onUnblock');
$el.removeData('blockUI.onUnblock');
}
var els;
if (full) // crazy selector to handle odd field errors in ie6/7
els = $('body').children().filter('.blockUI').add('body > .blockUI');
else
els = $el.find('>.blockUI');
// fix cursor issue
if ( opts.cursorReset ) {
if ( els.length > 1 )
els[1].style.cursor = opts.cursorReset;
if ( els.length > 2 )
els[2].style.cursor = opts.cursorReset;
}
if (full)
pageBlock = pageBlockEls = null;
if (opts.fadeOut) {
count = els.length;
els.stop().fadeOut(opts.fadeOut, function() {
if ( --count === 0)
reset(els,data,opts,el);
});
}
else
reset(els, data, opts, el);
}
// move blocking element back into the DOM where it started
function reset(els,data,opts,el) {
var $el = $(el);
if ( $el.data('blockUI.isBlocked') )
return;
els.each(function(i,o) {
// remove via DOM calls so we don't lose event handlers
if (this.parentNode)
this.parentNode.removeChild(this);
});
if (data && data.el) {
data.el.style.display = data.display;
data.el.style.position = data.position;
data.el.style.cursor = 'default'; // #59
if (data.parent)
data.parent.appendChild(data.el);
$el.removeData('blockUI.history');
}
if ($el.data('blockUI.static')) {
$el.css('position', 'static'); // #22
}
if (typeof opts.onUnblock == 'function')
opts.onUnblock(el,opts);
// fix issue in Safari 6 where block artifacts remain until reflow
var body = $(document.body), w = body.width(), cssW = body[0].style.width;
body.width(w-1).width(w);
body[0].style.width = cssW;
}
// bind/unbind the handler
function bind(b, el, opts) {
var full = el == window, $el = $(el);
// don't bother unbinding if there is nothing to unbind
if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
return;
$el.data('blockUI.isBlocked', b);
// don't bind events when overlay is not in use or if bindEvents is false
if (!full || !opts.bindEvents || (b && !opts.showOverlay))
return;
// bind anchors and inputs for mouse and key events
var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove';
if (b)
$(document).bind(events, opts, handler);
else
$(document).unbind(events, handler);
// former impl...
// var $e = $('a,:input');
// b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
}
// event handler to suppress keyboard/mouse events when blocking
function handler(e) {
// allow tab navigation (conditionally)
if (e.type === 'keydown' && e.keyCode && e.keyCode == 9) {
if (pageBlock && e.data.constrainTabKey) {
var els = pageBlockEls;
var fwd = !e.shiftKey && e.target === els[els.length-1];
var back = e.shiftKey && e.target === els[0];
if (fwd || back) {
setTimeout(function(){focus(back);},10);
return false;
}
}
}
var opts = e.data;
var target = $(e.target);
if (target.hasClass('blockOverlay') && opts.onOverlayClick)
opts.onOverlayClick(e);
// allow events within the message content
if (target.parents('div.' + opts.blockMsgClass).length > 0)
return true;
// allow events for content that is not being blocked
return target.parents().children().filter('div.blockUI').length === 0;
}
function focus(back) {
if (!pageBlockEls)
return;
var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
if (e)
e.focus();
}
function center(el, x, y) {
var p = el.parentNode, s = el.style;
var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
if (x) s.left = l > 0 ? (l+'px') : '0';
if (y) s.top = t > 0 ? (t+'px') : '0';
}
function sz(el, p) {
return parseInt($.css(el,p),10)||0;
}
}
/*global define:true */
if (typeof define === 'function' && define.amd && define.amd.jQuery) {
define(['jquery'], setup);
} else {
setup(jQuery);
}
})();

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,543 @@
/*
* Jeditable - jQuery in place edit plugin
*
* Copyright (c) 2006-2009 Mika Tuupola, Dylan Verheul
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Project home:
* http://www.appelsiini.net/projects/jeditable
*
* Based on editable by Dylan Verheul <dylan_at_dyve.net>:
* http://www.dyve.net/jquery/?editable
*
*/
/**
* Version 1.7.1
*
* ** means there is basic unit tests for this parameter.
*
* @name Jeditable
* @type jQuery
* @param String target (POST) URL or function to send edited content to **
* @param Hash options additional options
* @param String options[method] method to use to send edited content (POST or PUT) **
* @param Function options[callback] Function to run after submitting edited content **
* @param String options[name] POST parameter name of edited content
* @param String options[id] POST parameter name of edited div id
* @param Hash options[submitdata] Extra parameters to send when submitting edited content.
* @param String options[type] text, textarea or select (or any 3rd party input type) **
* @param Integer options[rows] number of rows if using textarea **
* @param Integer options[cols] number of columns if using textarea **
* @param Mixed options[height] 'auto', 'none' or height in pixels **
* @param Mixed options[width] 'auto', 'none' or width in pixels **
* @param String options[loadurl] URL to fetch input content before editing **
* @param String options[loadtype] Request type for load url. Should be GET or POST.
* @param String options[loadtext] Text to display while loading external content.
* @param Mixed options[loaddata] Extra parameters to pass when fetching content before editing.
* @param Mixed options[data] Or content given as paramameter. String or function.**
* @param String options[indicator] indicator html to show when saving
* @param String options[tooltip] optional tooltip text via title attribute **
* @param String options[event] jQuery event such as 'click' of 'dblclick' **
* @param String options[submit] submit button value, empty means no button **
* @param String options[cancel] cancel button value, empty means no button **
* @param String options[cssclass] CSS class to apply to input form. 'inherit' to copy from parent. **
* @param String options[style] Style to apply to input form 'inherit' to copy from parent. **
* @param String options[select] true or false, when true text is highlighted ??
* @param String options[placeholder] Placeholder text or html to insert when element is empty. **
* @param String options[onblur] 'cancel', 'submit', 'ignore' or function ??
*
* @param Function options[onsubmit] function(settings, original) { ... } called before submit
* @param Function options[onreset] function(settings, original) { ... } called before reset
* @param Function options[onerror] function(settings, original, xhr) { ... } called on error
*
* @param Hash options[ajaxoptions] jQuery Ajax options. See docs.jquery.com.
*
*/
(function($) {
$.fn.editable = function(target, options) {
if ('disable' == target) {
$(this).data('disabled.editable', true);
return;
}
if ('enable' == target) {
$(this).data('disabled.editable', false);
return;
}
if ('destroy' == target) {
$(this)
.unbind($(this).data('event.editable'))
.removeData('disabled.editable')
.removeData('event.editable');
return;
}
var settings = $.extend({}, $.fn.editable.defaults, {target:target}, options);
/* setup some functions */
var plugin = $.editable.types[settings.type].plugin || function() { };
var submit = $.editable.types[settings.type].submit || function() { };
var buttons = $.editable.types[settings.type].buttons
|| $.editable.types['defaults'].buttons;
var content = $.editable.types[settings.type].content
|| $.editable.types['defaults'].content;
var element = $.editable.types[settings.type].element
|| $.editable.types['defaults'].element;
var reset = $.editable.types[settings.type].reset
|| $.editable.types['defaults'].reset;
var callback = settings.callback || function() { };
var onedit = settings.onedit || function() { };
var onsubmit = settings.onsubmit || function() { };
var onreset = settings.onreset || function() { };
var onerror = settings.onerror || reset;
/* show tooltip */
if (settings.tooltip) {
$(this).attr('title', settings.tooltip);
}
settings.autowidth = 'auto' == settings.width;
settings.autoheight = 'auto' == settings.height;
return this.each(function() {
/* save this to self because this changes when scope changes */
var self = this;
/* inlined block elements lose their width and height after first edit */
/* save them for later use as workaround */
var savedwidth = $(self).width();
var savedheight = $(self).height();
/* save so it can be later used by $.editable('destroy') */
$(this).data('event.editable', settings.event);
/* if element is empty add something clickable (if requested) */
if (!$.trim($(this).html())) {
$(this).html(settings.placeholder);
}
$(this).bind(settings.event, function(e) {
/* abort if disabled for this element */
if (true === $(this).data('disabled.editable')) {
return;
}
/* prevent throwing an exeption if edit field is clicked again */
if (self.editing) {
return;
}
/* abort if onedit hook returns false */
if (false === onedit.apply(this, [settings, self])) {
return;
}
/* prevent default action and bubbling */
e.preventDefault();
e.stopPropagation();
/* remove tooltip */
if (settings.tooltip) {
$(self).removeAttr('title');
}
/* figure out how wide and tall we are, saved width and height */
/* are workaround for http://dev.jquery.com/ticket/2190 */
if (0 == $(self).width()) {
//$(self).css('visibility', 'hidden');
settings.width = savedwidth;
settings.height = savedheight;
} else {
if (settings.width != 'none') {
settings.width =
settings.autowidth ? $(self).width() : settings.width;
}
if (settings.height != 'none') {
settings.height =
settings.autoheight ? $(self).height() : settings.height;
}
}
//$(this).css('visibility', '');
/* remove placeholder text, replace is here because of IE */
if ($(this).html().toLowerCase().replace(/(;|")/g, '') ==
settings.placeholder.toLowerCase().replace(/(;|")/g, '')) {
$(this).html('');
}
self.editing = true;
self.revert = $(self).html();
$(self).html('');
/* create the form object */
var form = $('<form />');
/* apply css or style or both */
if (settings.cssclass) {
if ('inherit' == settings.cssclass) {
form.attr('class', $(self).attr('class'));
} else {
form.attr('class', settings.cssclass);
}
}
if (settings.style) {
if ('inherit' == settings.style) {
form.attr('style', $(self).attr('style'));
/* IE needs the second line or display wont be inherited */
form.css('display', $(self).css('display'));
} else {
form.attr('style', settings.style);
}
}
/* add main input element to form and store it in input */
var input = element.apply(form, [settings, self]);
/* set input content via POST, GET, given data or existing value */
var input_content;
if (settings.loadurl) {
var t = setTimeout(function() {
input.disabled = true;
content.apply(form, [settings.loadtext, settings, self]);
}, 100);
var loaddata = {};
loaddata[settings.id] = self.id;
if ($.isFunction(settings.loaddata)) {
$.extend(loaddata, settings.loaddata.apply(self, [self.revert, settings]));
} else {
$.extend(loaddata, settings.loaddata);
}
$.ajax({
type : settings.loadtype,
url : settings.loadurl,
data : loaddata,
async : false,
success: function(result) {
window.clearTimeout(t);
input_content = result;
input.disabled = false;
}
});
} else if (settings.data) {
input_content = settings.data;
if ($.isFunction(settings.data)) {
input_content = settings.data.apply(self, [self.revert, settings]);
}
} else {
input_content = self.revert;
}
content.apply(form, [input_content, settings, self]);
input.attr('name', settings.name);
/* add buttons to the form */
buttons.apply(form, [settings, self]);
/* add created form to self */
$(self).append(form);
/* attach 3rd party plugin if requested */
plugin.apply(form, [settings, self]);
/* focus to first visible form element */
$(':input:visible:enabled:first', form).focus();
/* highlight input contents when requested */
if (settings.select) {
input.select();
}
/* discard changes if pressing esc */
input.keydown(function(e) {
if (e.keyCode == 27) {
e.preventDefault();
//self.reset();
reset.apply(form, [settings, self]);
}
});
/* discard, submit or nothing with changes when clicking outside */
/* do nothing is usable when navigating with tab */
var t;
if ('cancel' == settings.onblur) {
input.blur(function(e) {
/* prevent canceling if submit was clicked */
t = setTimeout(function() {
reset.apply(form, [settings, self]);
}, 500);
});
} else if ('submit' == settings.onblur) {
input.blur(function(e) {
/* prevent double submit if submit was clicked */
t = setTimeout(function() {
form.submit();
}, 200);
});
} else if ($.isFunction(settings.onblur)) {
input.blur(function(e) {
settings.onblur.apply(self, [input.val(), settings]);
});
} else {
input.blur(function(e) {
/* TODO: maybe something here */
});
}
form.submit(function(e) {
if (t) {
clearTimeout(t);
}
/* do no submit */
e.preventDefault();
/* call before submit hook. */
/* if it returns false abort submitting */
if (false !== onsubmit.apply(form, [settings, self])) {
/* custom inputs call before submit hook. */
/* if it returns false abort submitting */
if (false !== submit.apply(form, [settings, self])) {
/* check if given target is function */
if ($.isFunction(settings.target)) {
var str = settings.target.apply(self, [input.val(), settings]);
$(self).html(str);
self.editing = false;
callback.apply(self, [self.innerHTML, settings]);
/* TODO: this is not dry */
if (!$.trim($(self).html())) {
$(self).html(settings.placeholder);
}
} else {
/* add edited content and id of edited element to POST */
var submitdata = {};
submitdata[settings.name] = input.val();
submitdata[settings.id] = self.id;
/* add extra data to be POST:ed */
if ($.isFunction(settings.submitdata)) {
$.extend(submitdata, settings.submitdata.apply(self, [self.revert, settings]));
} else {
$.extend(submitdata, settings.submitdata);
}
/* quick and dirty PUT support */
if ('PUT' == settings.method) {
submitdata['_method'] = 'put';
}
/* show the saving indicator */
$(self).html(settings.indicator);
/* defaults for ajaxoptions */
var ajaxoptions = {
type : 'POST',
data : submitdata,
dataType: 'html',
url : settings.target,
success : function(result, status) {
if (ajaxoptions.dataType == 'html') {
$(self).html(result);
}
self.editing = false;
callback.apply(self, [result, settings]);
if (!$.trim($(self).html())) {
$(self).html(settings.placeholder);
}
},
error : function(xhr, status, error) {
onerror.apply(form, [settings, self, xhr]);
}
};
/* override with what is given in settings.ajaxoptions */
$.extend(ajaxoptions, settings.ajaxoptions);
$.ajax(ajaxoptions);
}
}
}
/* show tooltip again */
$(self).attr('title', settings.tooltip);
return false;
});
});
/* privileged methods */
this.reset = function(form) {
/* prevent calling reset twice when blurring */
if (this.editing) {
/* before reset hook, if it returns false abort reseting */
if (false !== onreset.apply(form, [settings, self])) {
$(self).html(self.revert);
self.editing = false;
if (!$.trim($(self).html())) {
$(self).html(settings.placeholder);
}
/* show tooltip again */
if (settings.tooltip) {
$(self).attr('title', settings.tooltip);
}
}
}
};
});
};
$.editable = {
types: {
defaults: {
element : function(settings, original) {
var input = $('<input type="hidden"></input>');
$(this).append(input);
return(input);
},
content : function(string, settings, original) {
$(':input:first', this).val(string);
},
reset : function(settings, original) {
original.reset(this);
},
buttons : function(settings, original) {
var form = this;
if (settings.submit) {
/* if given html string use that */
if (settings.submit.match(/>$/)) {
var submit = $(settings.submit).click(function() {
if (submit.attr("type") != "submit") {
form.submit();
}
});
/* otherwise use button with given string as text */
} else {
var submit = $('<button type="submit" />');
submit.html(settings.submit);
}
$(this).append(submit);
}
if (settings.cancel) {
/* if given html string use that */
if (settings.cancel.match(/>$/)) {
var cancel = $(settings.cancel);
/* otherwise use button with given string as text */
} else {
var cancel = $('<button type="cancel" />');
cancel.html(settings.cancel);
}
$(this).append(cancel);
$(cancel).click(function(event) {
//original.reset();
if ($.isFunction($.editable.types[settings.type].reset)) {
var reset = $.editable.types[settings.type].reset;
} else {
var reset = $.editable.types['defaults'].reset;
}
reset.apply(form, [settings, original]);
return false;
});
}
}
},
text: {
element : function(settings, original) {
var input = $('<input />');
if (settings.width != 'none') { input.width(settings.width); }
if (settings.height != 'none') { input.height(settings.height); }
/* https://bugzilla.mozilla.org/show_bug.cgi?id=236791 */
//input[0].setAttribute('autocomplete','off');
input.attr('autocomplete','off');
$(this).append(input);
return(input);
}
},
textarea: {
element : function(settings, original) {
var textarea = $('<textarea />');
if (settings.rows) {
textarea.attr('rows', settings.rows);
} else if (settings.height != "none") {
textarea.height(settings.height);
}
if (settings.cols) {
textarea.attr('cols', settings.cols);
} else if (settings.width != "none") {
textarea.width(settings.width);
}
$(this).append(textarea);
return(textarea);
}
},
select: {
element : function(settings, original) {
var select = $('<select />');
$(this).append(select);
return(select);
},
content : function(data, settings, original) {
/* If it is string assume it is json. */
if (String == data.constructor) {
eval ('var json = ' + data);
} else {
/* Otherwise assume it is a hash already. */
var json = data;
}
for (var key in json) {
if (!json.hasOwnProperty(key)) {
continue;
}
if ('selected' == key) {
continue;
}
var option = $('<option />').val(key).append(json[key]);
$('select', this).append(option);
}
/* Loop option again to set selected. IE needed this... */
$('select', this).children().each(function() {
if ($(this).val() == json['selected'] ||
$(this).text() == $.trim(original.revert)) {
$(this).attr('selected', 'selected');
}
});
}
}
},
/* Add new input type */
addInputType: function(name, input) {
$.editable.types[name] = input;
}
};
// publicly accessible defaults
$.fn.editable.defaults = {
name : 'value',
id : 'id',
type : 'text',
width : 'auto',
height : 'auto',
event : 'click.editable',
onblur : 'cancel',
loadtype : 'GET',
loadtext : 'Loading...',
placeholder: 'Click to edit',
loaddata : {},
submitdata : {},
ajaxoptions: {}
};
})(jQuery);

View file

@ -0,0 +1,38 @@
(function($){$.fn.editable=function(target,options){if('disable'==target){$(this).data('disabled.editable',true);return;}
if('enable'==target){$(this).data('disabled.editable',false);return;}
if('destroy'==target){$(this).unbind($(this).data('event.editable')).removeData('disabled.editable').removeData('event.editable');return;}
var settings=$.extend({},$.fn.editable.defaults,{target:target},options);var plugin=$.editable.types[settings.type].plugin||function(){};var submit=$.editable.types[settings.type].submit||function(){};var buttons=$.editable.types[settings.type].buttons||$.editable.types['defaults'].buttons;var content=$.editable.types[settings.type].content||$.editable.types['defaults'].content;var element=$.editable.types[settings.type].element||$.editable.types['defaults'].element;var reset=$.editable.types[settings.type].reset||$.editable.types['defaults'].reset;var callback=settings.callback||function(){};var onedit=settings.onedit||function(){};var onsubmit=settings.onsubmit||function(){};var onreset=settings.onreset||function(){};var onerror=settings.onerror||reset;if(settings.tooltip){$(this).attr('title',settings.tooltip);}
settings.autowidth='auto'==settings.width;settings.autoheight='auto'==settings.height;return this.each(function(){var self=this;var savedwidth=$(self).width();var savedheight=$(self).height();$(this).data('event.editable',settings.event);if(!$.trim($(this).html())){$(this).html(settings.placeholder);}
$(this).bind(settings.event,function(e){if(true===$(this).data('disabled.editable')){return;}
if(self.editing){return;}
if(false===onedit.apply(this,[settings,self])){return;}
e.preventDefault();e.stopPropagation();if(settings.tooltip){$(self).removeAttr('title');}
if(0==$(self).width()){settings.width=savedwidth;settings.height=savedheight;}else{if(settings.width!='none'){settings.width=settings.autowidth?$(self).width():settings.width;}
if(settings.height!='none'){settings.height=settings.autoheight?$(self).height():settings.height;}}
if($(this).html().toLowerCase().replace(/(;|")/g,'')==settings.placeholder.toLowerCase().replace(/(;|")/g,'')){$(this).html('');}
self.editing=true;self.revert=$(self).html();$(self).html('');var form=$('<form />');if(settings.cssclass){if('inherit'==settings.cssclass){form.attr('class',$(self).attr('class'));}else{form.attr('class',settings.cssclass);}}
if(settings.style){if('inherit'==settings.style){form.attr('style',$(self).attr('style'));form.css('display',$(self).css('display'));}else{form.attr('style',settings.style);}}
var input=element.apply(form,[settings,self]);var input_content;if(settings.loadurl){var t=setTimeout(function(){input.disabled=true;content.apply(form,[settings.loadtext,settings,self]);},100);var loaddata={};loaddata[settings.id]=self.id;if($.isFunction(settings.loaddata)){$.extend(loaddata,settings.loaddata.apply(self,[self.revert,settings]));}else{$.extend(loaddata,settings.loaddata);}
$.ajax({type:settings.loadtype,url:settings.loadurl,data:loaddata,async:false,success:function(result){window.clearTimeout(t);input_content=result;input.disabled=false;}});}else if(settings.data){input_content=settings.data;if($.isFunction(settings.data)){input_content=settings.data.apply(self,[self.revert,settings]);}}else{input_content=self.revert;}
content.apply(form,[input_content,settings,self]);input.attr('name',settings.name);buttons.apply(form,[settings,self]);$(self).append(form);plugin.apply(form,[settings,self]);$(':input:visible:enabled:first',form).focus();if(settings.select){input.select();}
input.keydown(function(e){if(e.keyCode==27){e.preventDefault();reset.apply(form,[settings,self]);}});var t;if('cancel'==settings.onblur){input.blur(function(e){t=setTimeout(function(){reset.apply(form,[settings,self]);},500);});}else if('submit'==settings.onblur){input.blur(function(e){t=setTimeout(function(){form.submit();},200);});}else if($.isFunction(settings.onblur)){input.blur(function(e){settings.onblur.apply(self,[input.val(),settings]);});}else{input.blur(function(e){});}
form.submit(function(e){if(t){clearTimeout(t);}
e.preventDefault();if(false!==onsubmit.apply(form,[settings,self])){if(false!==submit.apply(form,[settings,self])){if($.isFunction(settings.target)){var str=settings.target.apply(self,[input.val(),settings]);$(self).html(str);self.editing=false;callback.apply(self,[self.innerHTML,settings]);if(!$.trim($(self).html())){$(self).html(settings.placeholder);}}else{var submitdata={};submitdata[settings.name]=input.val();submitdata[settings.id]=self.id;if($.isFunction(settings.submitdata)){$.extend(submitdata,settings.submitdata.apply(self,[self.revert,settings]));}else{$.extend(submitdata,settings.submitdata);}
if('PUT'==settings.method){submitdata['_method']='put';}
$(self).html(settings.indicator);var ajaxoptions={type:'POST',data:submitdata,dataType:'html',url:settings.target,success:function(result,status){if(ajaxoptions.dataType=='html'){$(self).html(result);}
self.editing=false;callback.apply(self,[result,settings]);if(!$.trim($(self).html())){$(self).html(settings.placeholder);}},error:function(xhr,status,error){onerror.apply(form,[settings,self,xhr]);}};$.extend(ajaxoptions,settings.ajaxoptions);$.ajax(ajaxoptions);}}}
$(self).attr('title',settings.tooltip);return false;});});this.reset=function(form){if(this.editing){if(false!==onreset.apply(form,[settings,self])){$(self).html(self.revert);self.editing=false;if(!$.trim($(self).html())){$(self).html(settings.placeholder);}
if(settings.tooltip){$(self).attr('title',settings.tooltip);}}}};});};$.editable={types:{defaults:{element:function(settings,original){var input=$('<input type="hidden"></input>');$(this).append(input);return(input);},content:function(string,settings,original){$(':input:first',this).val(string);},reset:function(settings,original){original.reset(this);},buttons:function(settings,original){var form=this;if(settings.submit){if(settings.submit.match(/>$/)){var submit=$(settings.submit).click(function(){if(submit.attr("type")!="submit"){form.submit();}});}else{var submit=$('<button type="submit" />');submit.html(settings.submit);}
$(this).append(submit);}
if(settings.cancel){if(settings.cancel.match(/>$/)){var cancel=$(settings.cancel);}else{var cancel=$('<button type="cancel" />');cancel.html(settings.cancel);}
$(this).append(cancel);$(cancel).click(function(event){if($.isFunction($.editable.types[settings.type].reset)){var reset=$.editable.types[settings.type].reset;}else{var reset=$.editable.types['defaults'].reset;}
reset.apply(form,[settings,original]);return false;});}}},text:{element:function(settings,original){var input=$('<input />');if(settings.width!='none'){input.width(settings.width);}
if(settings.height!='none'){input.height(settings.height);}
input.attr('autocomplete','off');$(this).append(input);return(input);}},textarea:{element:function(settings,original){var textarea=$('<textarea />');if(settings.rows){textarea.attr('rows',settings.rows);}else if(settings.height!="none"){textarea.height(settings.height);}
if(settings.cols){textarea.attr('cols',settings.cols);}else if(settings.width!="none"){textarea.width(settings.width);}
$(this).append(textarea);return(textarea);}},select:{element:function(settings,original){var select=$('<select />');$(this).append(select);return(select);},content:function(data,settings,original){if(String==data.constructor){eval('var json = '+data);}else{var json=data;}
for(var key in json){if(!json.hasOwnProperty(key)){continue;}
if('selected'==key){continue;}
var option=$('<option />').val(key).append(json[key]);$('select',this).append(option);}
$('select',this).children().each(function(){if($(this).val()==json['selected']||$(this).text()==$.trim(original.revert)){$(this).attr('selected','selected');}});}}},addInputType:function(name,input){$.editable.types[name]=input;}};$.fn.editable.defaults={name:'value',id:'id',type:'text',width:'auto',height:'auto',event:'click.editable',onblur:'cancel',loadtype:'GET',loadtext:'Loading...',placeholder:'Click to edit',loaddata:{},submitdata:{},ajaxoptions:{}};})(jQuery);

View file

@ -0,0 +1,939 @@
/*
* jQuery Menu plugin
* Version: 0.0.9
*
* Copyright (c) 2007 Roman Weich
* http://p.sohei.org
*
* Dual licensed under the MIT and GPL licenses
* (This means that you can choose the license that best suits your project, and use it accordingly):
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* Changelog:
* v 0.0.9 - 2008-01-19
*/
(function($)
{
var menus = [], //list of all menus
visibleMenus = [], //list of all visible menus
activeMenu = activeItem = null,
menuDIVElement = $('<div class="menu-div outerbox" style="position:absolute;top:0;left:0;display:none;"><div class="shadowbox1"></div><div class="shadowbox2"></div><div class="shadowbox3"></div></div>')[0],
menuULElement = $('<ul class="menu-ul innerbox"></ul>')[0],
menuItemElement = $('<li style="position:relative;"><div class="menu-item"></div></li>')[0],
arrowElement = $('<img class="menu-item-arrow" />')[0],
$rootDiv = $('<div id="root-menu-div" style="position:absolute;top:0;left:0;"></div>'), //create main menu div
defaults = {
// $.Menu options
showDelay : 200,
hideDelay : 200,
hoverOpenDelay: 0,
offsetTop : 0,
offsetLeft : 0,
minWidth: 0,
onOpen: null,
onClose: null,
// $.MenuItem options
onClick: null,
arrowSrc: null,
addExpando: false,
// $.fn.menuFromElement options
copyClassAttr: false
};
$(function(){
$rootDiv.appendTo('body');
});
$.extend({
MenuCollection : function(items) {
this.menus = [];
this.init(items);
}
});
$.extend($.MenuCollection, {
prototype : {
init : function(items)
{
if ( items && items.length )
{
for ( var i = 0; i < items.length; i++ )
{
this.addMenu(items[i]);
items[i].menuCollection = this;
}
}
},
addMenu : function(menu)
{
if ( menu instanceof $.Menu )
this.menus.push(menu);
menu.menuCollection = this;
var self = this;
$(menu.target).hover(function(){
if ( menu.visible )
return;
//when there is an open menu in this collection, hide it and show the new one
for ( var i = 0; i < self.menus.length; i++ )
{
if ( self.menus[i].visible )
{
self.menus[i].hide();
menu.show();
return;
}
}
}, function(){});
}
}
});
$.extend({
Menu : function(target, items, options) {
this.menuItems = []; //all direct child $.MenuItem objects
this.subMenus = []; //all subMenus from this.menuItems
this.visible = false;
this.active = false; //this menu has hover or one of its submenus is open
this.parentMenuItem = null;
this.settings = $.extend({}, defaults, options);
this.target = target;
this.$eDIV = null;
this.$eUL = null;
this.timer = null;
this.menuCollection = null;
this.openTimer = null;
this.init();
if ( items && items.constructor == Array )
this.addItems(items);
}
});
$.extend($.Menu, {
checkMouse : function(e)
{
var t = e.target;
//the user clicked on the target of the currenty open menu
if ( visibleMenus.length && t == visibleMenus[0].target )
return;
//get the last node before the #root-menu-div
while ( t.parentNode && t.parentNode != $rootDiv[0] )
t = t.parentNode;
//is the found node one of the visible menu elements?
if ( !$(visibleMenus).filter(function(){ return this.$eDIV[0] == t }).length )
{
$.Menu.closeAll();
}
},
checkKey : function(e)
{
switch ( e.keyCode )
{
case 13: //return
if ( activeItem )
activeItem.click(e, activeItem.$eLI[0]);
break;
case 27: //ESC
$.Menu.closeAll();
break;
case 37: //left
if ( !activeMenu )
activeMenu = visibleMenus[0];
var a = activeMenu;
if ( a && a.parentMenuItem ) //select the parent menu and close the submenu
{
//unbind the events temporary, as we dont want the hoverout event to fire
var pmi = a.parentMenuItem;
pmi.$eLI.unbind('mouseout').unbind('mouseover');
a.hide();
pmi.hoverIn(true);
setTimeout(function(){ //bind again..but delay it
pmi.bindHover();
});
}
else if ( a && a.menuCollection ) //select the previous menu in the collection
{
var pos,
mcm = a.menuCollection.menus;
if ( (pos = $.inArray(a, mcm)) > -1 )
{
if ( --pos < 0 )
pos = mcm.length - 1;
$.Menu.closeAll();
mcm[pos].show();
mcm[pos].setActive();
if ( mcm[pos].menuItems.length ) //select the first item
mcm[pos].menuItems[0].hoverIn(true);
}
}
break;
case 38: //up
if ( activeMenu )
activeMenu.selectNextItem(-1);
break;
case 39: //right
if ( !activeMenu )
activeMenu = visibleMenus[0];
var m,
a = activeMenu,
asm = activeItem ? activeItem.subMenu : null;
if ( a )
{
if ( asm && asm.menuItems.length ) //select the submenu
{
asm.show();
asm.menuItems[0].hoverIn();
}
else if ( (a = a.inMenuCollection()) ) //select the next menu in the collection
{
var pos,
mcm = a.menuCollection.menus;
if ( (pos = $.inArray(a, mcm)) > -1 )
{
if ( ++pos >= mcm.length )
pos = 0;
$.Menu.closeAll();
mcm[pos].show();
mcm[pos].setActive();
if ( mcm[pos].menuItems.length ) //select the first item
mcm[pos].menuItems[0].hoverIn(true);
}
}
}
break;
case 40: //down
if ( !activeMenu )
{
if ( visibleMenus.length && visibleMenus[0].menuItems.length )
visibleMenus[0].menuItems[0].hoverIn();
}
else
activeMenu.selectNextItem();
break;
}
if ( e.keyCode > 36 && e.keyCode < 41 )
return false; //this will prevent scrolling
},
closeAll : function()
{
while ( visibleMenus.length )
visibleMenus[0].hide();
},
setDefaults : function(d)
{
$.extend(defaults, d);
},
prototype : {
/**
* create / initialize new menu
*/
init : function()
{
var self = this;
if ( !this.target )
return;
else if ( this.target instanceof $.MenuItem )
{
this.parentMenuItem = this.target;
this.target.addSubMenu(this);
this.target = this.target.$eLI;
}
menus.push(this);
//use the dom methods instead the ones from jquery (faster)
this.$eDIV = $(menuDIVElement.cloneNode(1));
this.$eUL = $(menuULElement.cloneNode(1));
this.$eDIV[0].appendChild(this.$eUL[0]);
$rootDiv[0].appendChild(this.$eDIV[0]);
//bind events
if ( !this.parentMenuItem )
{
$(this.target).click(function(e){
self.onClick(e);
}).hover(function(e){
self.setActive();
if ( self.settings.hoverOpenDelay )
{
self.openTimer = setTimeout(function(){
if ( !self.visible )
self.onClick(e);
}, self.settings.hoverOpenDelay);
}
}, function(){
if ( !self.visible )
$(this).removeClass('activetarget');
if ( self.openTimer )
clearTimeout(self.openTimer);
});
}
else
{
this.$eDIV.hover(function(){
self.setActive();
}, function(){});
}
},
setActive : function()
{
if ( !this.parentMenuItem )
$(this.target).addClass('activetarget');
else
this.active = true;
},
addItem : function(item)
{
if ( item instanceof $.MenuItem )
{
if ( $.inArray(item, this.menuItems) == -1 )
{
this.$eUL.append(item.$eLI);
this.menuItems.push(item);
item.parentMenu = this;
if ( item.subMenu )
this.subMenus.push(item.subMenu);
}
}
else
{
this.addItem(new $.MenuItem(item, this.settings));
}
},
addItems : function(items)
{
for ( var i = 0; i < items.length; i++ )
{
this.addItem(items[i]);
}
},
removeItem : function(item)
{
var pos = $.inArray(item, this.menuItems);
if ( pos > -1 )
this.menuItems.splice(pos, 1);
item.parentMenu = null;
},
hide : function()
{
if ( !this.visible )
return;
var i,
pos = $.inArray(this, visibleMenus);
this.$eDIV.hide();
if ( pos >= 0 )
visibleMenus.splice(pos, 1);
this.visible = this.active = false;
$(this.target).removeClass('activetarget');
//hide all submenus
for ( i = 0; i < this.subMenus.length; i++ )
{
this.subMenus[i].hide();
}
//set all items inactive (e.g. remove hover class..)
for ( i = 0; i < this.menuItems.length; i++ )
{
if ( this.menuItems[i].active )
this.menuItems[i].setInactive();
}
if ( !visibleMenus.length ) //unbind events when the last menu was closed
$(document).unbind('mousedown', $.Menu.checkMouse).unbind('keydown', $.Menu.checkKey);
if ( activeMenu == this )
activeMenu = null;
if ( this.settings.onClose )
this.settings.onClose.call(this);
},
show : function(e)
{
if ( this.visible )
return;
var zi,
pmi = this.parentMenuItem;
if ( this.menuItems.length ) //show only when it has items
{
if ( pmi ) //set z-index
{
zi = parseInt(pmi.parentMenu.$eDIV.css('z-index'));
this.$eDIV.css('z-index', (isNaN(zi) ? 1 : zi + 1));
}
this.$eDIV.css({visibility: 'hidden', display:'block'});
//set min-width
if ( this.settings.minWidth )
{
if ( this.$eDIV.width() < this.settings.minWidth )
this.$eDIV.css('width', this.settings.minWidth);
}
this.setPosition();
this.$eDIV.css({display:'none', visibility: ''}).show();
if ( this.settings.onOpen )
this.settings.onOpen.call(this);
}
if ( visibleMenus.length == 0 )
$(document).bind('mousedown', $.Menu.checkMouse).bind('keydown', $.Menu.checkKey);
this.visible = true;
visibleMenus.push(this);
},
setPosition : function()
{
var $t, o, posX, posY,
pmo, //parent menu offset
wst, //window scroll top
wsl, //window scroll left
ww = $(window).width(),
wh = $(window).height(),
pmi = this.parentMenuItem,
height = this.$eDIV[0].clientHeight,
width = this.$eDIV[0].clientWidth,
pheight; //parent height
if ( pmi )
{
//position on the right side of the parent menu item
o = pmi.$eLI.offset();
posX = o.left + pmi.$eLI.width();
posY = o.top;
}
else
{
//position right below the target
$t = $(this.target);
o = $t.offset();
posX = o.left + this.settings.offsetLeft;
posY = o.top + $t.height() + this.settings.offsetTop;
}
//y-pos
if ( $.fn.scrollTop )
{
wst = $(window).scrollTop();
if ( wh < height ) //menu is bigger than the window
{
//position the menu at the top of the visible area
posY = wst;
}
else if ( wh + wst < posY + height ) //outside on the bottom?
{
if ( pmi )
{
pmo = pmi.parentMenu.$eDIV.offset();
pheight = pmi.parentMenu.$eDIV[0].clientHeight;
if ( height <= pheight )
{
//bottom position = parentmenu-bottom position
posY = pmo.top + pheight - height;
}
else
{
//top position = parentmenu-top position
posY = pmo.top;
}
//still outside on the bottom?
if ( wh + wst < posY + height )
{
//shift the menu upwards till the bottom is visible
posY -= posY + height - (wh + wst);
}
}
else
{
//shift the menu upwards till the bottom is visible
posY -= posY + height - (wh + wst);
}
}
}
//x-pos
if ( $.fn.scrollLeft )
{
wsl = $(window).scrollLeft();
if ( ww + wsl < posX + width )
{
if ( pmi )
{
//display the menu not on the right side but on the left side
posX -= pmi.$eLI.width() + width;
//outside on the left now?
if ( posX < wsl )
posX = wsl;
}
else
{
//shift the menu to the left until it fits
posX -= posX + width - (ww + wsl);
}
}
}
//set position
this.$eDIV.css({left: posX, top: posY});
},
onClick : function(e)
{
if ( this.visible )
{
this.hide();
this.setActive(); //the class is removed in the hide() method..add it again
}
else
{
//close all open menus
$.Menu.closeAll();
this.show(e);
}
},
addTimer : function(callback, delay)
{
var self = this;
this.timer = setTimeout(function(){
callback.call(self);
self.timer = null;
}, delay);
},
removeTimer : function()
{
if ( this.timer )
{
clearTimeout(this.timer);
this.timer = null;
}
},
selectNextItem : function(offset)
{
var i, pos = 0,
mil = this.menuItems.length,
o = offset || 1;
//get current pos
for ( i = 0; i < mil; i++ )
{
if ( this.menuItems[i].active )
{
pos = i;
break;
}
}
this.menuItems[pos].hoverOut();
do //jump over the separators
{
pos += o;
if ( pos >= mil )
pos = 0;
else if ( pos < 0 )
pos = mil - 1;
} while ( this.menuItems[pos].separator );
this.menuItems[pos].hoverIn(true);
},
inMenuCollection : function()
{
var m = this;
while ( m.parentMenuItem )
m = m.parentMenuItem.parentMenu;
return m.menuCollection ? m : null;
},
destroy : function() //delete menu
{
var pos, item;
this.hide();
//unbind events
if ( !this.parentMenuItem )
$(this.target).unbind('click').unbind('mouseover').unbind('mouseout');
else
this.$eDIV.unbind('mouseover').unbind('mouseout');
//destroy all items
while ( this.menuItems.length )
{
item = this.menuItems[0];
item.destroy();
delete item;
}
if ( (pos = $.inArray(this, menus)) > -1 )
menus.splice(pos, 1);
if ( this.menuCollection )
{
if ( (pos = $.inArray(this, this.menuCollection.menus)) > -1 )
this.menuCollection.menus.splice(pos, 1);
}
this.$eDIV.remove();
}
}
});
$.extend({
MenuItem : function(obj, options)
{
if ( typeof obj == 'string' )
obj = {src: obj};
this.src = obj.src || '';
this.url = obj.url || null;
this.urlTarget = obj.target || null;
this.addClass = obj.addClass || null;
this.data = obj.data || null;
this.$eLI = null;
this.parentMenu = null;
this.subMenu = null;
this.settings = $.extend({}, defaults, options);
this.active = false;
this.enabled = true;
this.separator = false;
this.init();
if ( obj.subMenu )
new $.Menu(this, obj.subMenu, options);
}
});
$.extend($.MenuItem, {
prototype : {
init : function()
{
var i, isStr,
src = this.src,
self = this;
this.$eLI = $(menuItemElement.cloneNode(1));
if ( this.addClass )
this.$eLI[0].setAttribute('class', this.addClass);
if ( this.settings.addExpando && this.data )
this.$eLI[0].menuData = this.data;
if ( src == '' )
{
this.$eLI.addClass('menu-separator');
this.separator = true;
}
else
{
isStr = typeof src == 'string';
if ( isStr && this.url ) //create a link node, when we have an url
src = $('<a href="' + this.url + '"' + (this.urlTarget ? 'target="' + this.urlTarget + '"' : '') + '>' + src + '</a>');
else if ( isStr || !src.length )
src = [src];
//go through the passed DOM-Elements (or jquery objects or text nodes.) and append them to the menus list item
//this.$eLI.append(this.src) is really slow when having a lot(!!!) of items
for ( i = 0; i < src.length; i++ )
{
if ( typeof src[i] == 'string' )
{
//we cant use createTextNode, as html entities won't be displayed correctly (eg. &copy;)
elem = document.createElement('span');
elem.innerHTML = src[i];
this.$eLI[0].firstChild.appendChild(elem);
}
else
this.$eLI[0].firstChild.appendChild(src[i].cloneNode(1));
}
}
this.$eLI.click(function(e){
self.click(e, this);
});
this.bindHover();
},
click : function(e, scope)
{
if ( this.enabled && this.settings.onClick )
this.settings.onClick.call(scope, e, this);
},
bindHover : function()
{
var self = this;
this.$eLI.hover(function(){
self.hoverIn();
}, function(){
self.hoverOut();
});
},
hoverIn : function(noSubMenu)
{
this.removeTimer();
var i,
pms = this.parentMenu.subMenus,
pmi = this.parentMenu.menuItems,
self = this;
//remove the timer from the parent item, when there is one (e.g. to close the menu)
if ( this.parentMenu.timer )
this.parentMenu.removeTimer();
if ( !this.enabled )
return;
//deactivate all menuItems on the same level
for ( i = 0; i < pmi.length; i++ )
{
if ( pmi[i].active )
pmi[i].setInactive();
}
this.setActive();
activeMenu = this.parentMenu;
//are there open submenus on the same level? close them!
for ( i = 0; i < pms.length; i++ )
{
if ( pms[i].visible && pms[i] != this.subMenu && !pms[i].timer ) //close if there is no closetimer running already
pms[i].addTimer(function(){
this.hide();
}, pms[i].settings.hideDelay);
}
if ( this.subMenu && !noSubMenu )
{
//set timeout to show menu
this.subMenu.addTimer(function(){
this.show();
}, this.subMenu.settings.showDelay);
}
},
hoverOut : function()
{
this.removeTimer();
if ( !this.enabled )
return;
if ( !this.subMenu || !this.subMenu.visible )
this.setInactive();
},
removeTimer : function()
{
if ( this.subMenu )
{
this.subMenu.removeTimer();
}
},
setActive : function()
{
this.active = true;
this.$eLI.addClass('active');
//set the parent menu item active too if necessary
var pmi = this.parentMenu.parentMenuItem;
if ( pmi && !pmi.active )
pmi.setActive();
activeItem = this;
},
setInactive : function()
{
this.active = false;
this.$eLI.removeClass('active');
if ( this == activeItem )
activeItem = null;
},
enable : function()
{
this.$eLI.removeClass('disabled');
this.enabled = true;
},
disable : function()
{
this.$eLI.addClass('disabled');
this.enabled = false;
},
destroy : function()
{
this.removeTimer();
this.$eLI.remove();
//unbind events
this.$eLI.unbind('mouseover').unbind('mouseout').unbind('click');
//delete submenu
if ( this.subMenu )
{
this.subMenu.destroy();
delete this.subMenu;
}
this.parentMenu.removeItem(this);
},
addSubMenu : function(menu)
{
if ( this.subMenu )
return;
this.subMenu = menu;
if ( this.parentMenu && $.inArray(menu, this.parentMenu.subMenus) == -1 )
this.parentMenu.subMenus.push(menu);
if ( this.settings.arrowSrc )
{
var a = arrowElement.cloneNode(0);
a.setAttribute('src', this.settings.arrowSrc);
this.$eLI[0].firstChild.appendChild(a);
}
}
}
});
$.extend($.fn, {
menuFromElement : function(options, list, bar)
{
var createItems = function(ul)
{
var menuItems = [],
subItems,
menuItem,
lis, $li, i, subUL, submenu, target,
classNames = null;
lis = getAllChilds(ul, 'LI');
for ( i = 0; i < lis.length; i++ )
{
subItems = [];
if ( !lis[i].childNodes.length ) //empty item? add separator
{
menuItems.push(new $.MenuItem('', options));
continue;
}
if ( (subUL = getOneChild(lis[i], 'UL')) )
{
subItems = createItems(subUL);
//remove subUL from DOM
$(subUL).remove();
}
//select the target...get the elements inside the li
$li = $(lis[i]);
if ( $li[0].childNodes.length == 1 && $li[0].childNodes[0].nodeType == 3 )
target = $li[0].childNodes[0].nodeValue;
else
target = $li[0].childNodes;
if ( options && options.copyClassAttr )
classNames = $li.attr('class');
//create item
menuItem = new $.MenuItem({src: target, addClass: classNames}, options);
menuItems.push(menuItem);
//add submenu
if ( subItems.length )
new $.Menu(menuItem, subItems, options);
}
return menuItems;
};
return this.each(function()
{
var ul, m;
//get the list element
if ( list || (ul = getOneChild(this, 'UL')) )
{
//if a specific list element is used, clone it, as we probably need it more than once
ul = list ? $(list).clone(true)[0] : ul;
menuItems = createItems(ul);
if ( menuItems.length )
{
m = new $.Menu(this, menuItems, options);
if ( bar )
bar.addMenu(m);
}
$(ul).hide();
}
});
},
menuBarFromUL : function(options)
{
return this.each(function()
{
var i,
lis = getAllChilds(this, 'LI');
if ( lis.length )
{
bar = new $.MenuCollection();
for ( i = 0; i < lis.length; i++ )
$(lis[i]).menuFromElement(options, null, bar);
}
});
},
menuBar : function(options, items)
{
return this.each(function()
{
if ( items && items.constructor == Array )
new $.Menu(this, items, options);
else
{
if ( this.nodeName.toUpperCase() == 'UL' )
$(this).menuBarFromUL(options);
else
$(this).menuFromElement(options, items);
}
});
}
});
//faster than using jquery
var getOneChild = function(elem, name)
{
if ( !elem )
return null;
var n = elem.firstChild;
for ( ; n; n = n.nextSibling )
{
if ( n.nodeType == 1 && n.nodeName.toUpperCase() == name )
return n;
}
return null;
};
//faster than using jquery
var getAllChilds = function(elem, name)
{
if ( !elem )
return [];
var r = [],
n = elem.firstChild;
for ( ; n; n = n.nextSibling )
{
if ( n.nodeType == 1 && n.nodeName.toUpperCase() == name )
r[r.length] = n;
}
return r;
};
})(jQuery);

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,205 @@
/*! Copyright (c) 2013 Brandon Aaron (http://brandon.aaron.sh)
* Licensed under the MIT License (LICENSE.txt).
*
* Version: 3.1.10-pre
*
* Requires: jQuery 1.2.2+
*/
(function (factory) {
if ( typeof define === 'function' && define.amd ) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS style for Browserify
module.exports = factory;
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
slice = Array.prototype.slice,
nullLowestDeltaTimeout, lowestDelta;
if ( $.event.fixHooks ) {
for ( var i = toFix.length; i; ) {
$.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
}
}
var special = $.event.special.mousewheel = {
version: '3.1.9',
setup: function() {
if ( this.addEventListener ) {
for ( var i = toBind.length; i; ) {
this.addEventListener( toBind[--i], handler, false );
}
} else {
this.onmousewheel = handler;
}
// Store the line height and page height for this particular element
$.data(this, 'mousewheel-line-height', special.getLineHeight(this));
$.data(this, 'mousewheel-page-height', special.getPageHeight(this));
},
teardown: function() {
if ( this.removeEventListener ) {
for ( var i = toBind.length; i; ) {
this.removeEventListener( toBind[--i], handler, false );
}
} else {
this.onmousewheel = null;
}
},
getLineHeight: function(elem) {
var $parent = $(elem)['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
if (!$parent.length) {
$parent = $('body');
}
return parseInt($parent.css('fontSize'), 10);
},
getPageHeight: function(elem) {
return $(elem).height();
},
settings: {
adjustOldDeltas: true
}
};
$.fn.extend({
mousewheel: function(fn) {
return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
},
unmousewheel: function(fn) {
return this.unbind('mousewheel', fn);
}
});
function handler(event) {
var orgEvent = event || window.event,
args = slice.call(arguments, 1),
delta = 0,
deltaX = 0,
deltaY = 0,
absDelta = 0;
event = $.event.fix(orgEvent);
event.type = 'mousewheel';
// Old school scrollwheel delta
if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; }
if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; }
if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }
if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }
// Firefox < 17 horizontal scrolling related to DOMMouseScroll event
if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
deltaX = deltaY * -1;
deltaY = 0;
}
// Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
delta = deltaY === 0 ? deltaX : deltaY;
// New school wheel delta (wheel event)
if ( 'deltaY' in orgEvent ) {
deltaY = orgEvent.deltaY * -1;
delta = deltaY;
}
if ( 'deltaX' in orgEvent ) {
deltaX = orgEvent.deltaX;
if ( deltaY === 0 ) { delta = deltaX * -1; }
}
// No change actually happened, no reason to go any further
if ( deltaY === 0 && deltaX === 0 ) { return; }
// Need to convert lines and pages to pixels if we aren't already in pixels
// There are three delta modes:
// * deltaMode 0 is by pixels, nothing to do
// * deltaMode 1 is by lines
// * deltaMode 2 is by pages
if ( orgEvent.deltaMode === 1 ) {
var lineHeight = $.data(this, 'mousewheel-line-height');
delta *= lineHeight;
deltaY *= lineHeight;
deltaX *= lineHeight;
} else if ( orgEvent.deltaMode === 2 ) {
var pageHeight = $.data(this, 'mousewheel-page-height');
delta *= pageHeight;
deltaY *= pageHeight;
deltaX *= pageHeight;
}
// Store lowest absolute delta to normalize the delta values
absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
if ( !lowestDelta || absDelta < lowestDelta ) {
lowestDelta = absDelta;
// Adjust older deltas if necessary
if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
lowestDelta /= 40;
}
}
// Adjust older deltas if necessary
if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
// Divide all the things by 40!
delta /= 40;
deltaX /= 40;
deltaY /= 40;
}
// Get a whole, normalized value for the deltas
delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
// Add information to the event object
event.deltaX = deltaX;
event.deltaY = deltaY;
event.deltaFactor = lowestDelta;
// Go ahead and set deltaMode to 0 since we converted to pixels
// Although this is a little odd since we overwrite the deltaX/Y
// properties with normalized deltas.
event.deltaMode = 0;
// Add event and delta to the front of the arguments
args.unshift(event, delta, deltaX, deltaY);
// Clearout lowestDelta after sometime to better
// handle multiple device types that give different
// a different lowestDelta
// Ex: trackpad = 3 and mouse wheel = 120
if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
return ($.event.dispatch || $.event.handle).apply(this, args);
}
function nullLowestDelta() {
lowestDelta = null;
}
function shouldAdjustOldDeltas(orgEvent, absDelta) {
// If this is an older event and the delta is divisable by 120,
// then we are assuming that the browser is treating this as an
// older mouse wheel event and that we should divide the deltas
// by 40 to try and get a more usable deltaFactor.
// Side note, this actually impacts the reported scroll distance
// in older browsers and can cause scrolling to be slower than native.
// Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
}
}));

View file

@ -0,0 +1 @@
(function(e){if(typeof define==="function"&&define.amd){define(["jquery"],e)}else if(typeof exports==="object"){module.exports=e}else{e(jQuery)}})(function(e){function a(t){var n=t||window.event,o=r.call(arguments,1),u=0,a=0,c=0,h=0;t=e.event.fix(n);t.type="mousewheel";if("detail"in n){c=n.detail*-1}if("wheelDelta"in n){c=n.wheelDelta}if("wheelDeltaY"in n){c=n.wheelDeltaY}if("wheelDeltaX"in n){a=n.wheelDeltaX*-1}if("axis"in n&&n.axis===n.HORIZONTAL_AXIS){a=c*-1;c=0}u=c===0?a:c;if("deltaY"in n){c=n.deltaY*-1;u=c}if("deltaX"in n){a=n.deltaX;if(c===0){u=a*-1}}if(c===0&&a===0){return}if(n.deltaMode===1){var p=e.data(this,"mousewheel-line-height");u*=p;c*=p;a*=p}else if(n.deltaMode===2){var d=e.data(this,"mousewheel-page-height");u*=d;c*=d;a*=d}h=Math.max(Math.abs(c),Math.abs(a));if(!s||h<s){s=h;if(l(n,h)){s/=40}}if(l(n,h)){u/=40;a/=40;c/=40}u=Math[u>=1?"floor":"ceil"](u/s);a=Math[a>=1?"floor":"ceil"](a/s);c=Math[c>=1?"floor":"ceil"](c/s);t.deltaX=a;t.deltaY=c;t.deltaFactor=s;t.deltaMode=0;o.unshift(t,u,a,c);if(i){clearTimeout(i)}i=setTimeout(f,200);return(e.event.dispatch||e.event.handle).apply(this,o)}function f(){s=null}function l(e,t){return u.settings.adjustOldDeltas&&e.type==="mousewheel"&&t%120===0}var t=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],n="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],r=Array.prototype.slice,i,s;if(e.event.fixHooks){for(var o=t.length;o;){e.event.fixHooks[t[--o]]=e.event.mouseHooks}}var u=e.event.special.mousewheel={version:"3.1.9",setup:function(){if(this.addEventListener){for(var t=n.length;t;){this.addEventListener(n[--t],a,false)}}else{this.onmousewheel=a}e.data(this,"mousewheel-line-height",u.getLineHeight(this));e.data(this,"mousewheel-page-height",u.getPageHeight(this))},teardown:function(){if(this.removeEventListener){for(var e=n.length;e;){this.removeEventListener(n[--e],a,false)}}else{this.onmousewheel=null}},getLineHeight:function(t){var n=e(t)["offsetParent"in e.fn?"offsetParent":"parent"]();if(!n.length){n=e("body")}return parseInt(n.css("fontSize"),10)},getPageHeight:function(t){return e(t).height()},settings:{adjustOldDeltas:true}};e.fn.extend({mousewheel:function(e){return e?this.bind("mousewheel",e):this.trigger("mousewheel")},unmousewheel:function(e){return this.unbind("mousewheel",e)}})})

View file

@ -0,0 +1,156 @@
/* jQuery Notify UI Widget 1.5 by Eric Hynds
* http://www.erichynds.com/jquery/a-jquery-ui-growl-ubuntu-notification-widget/
*
* Depends:
* - jQuery 1.4+
* - jQuery UI 1.8 widget factory
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
(function($){
$.widget("ech.notify", {
options: {
speed: 500,
expires: 5000,
stack: "below",
custom: false,
queue: false
},
_create: function(){
var self = this;
this.templates = {};
this.keys = [];
// build and save templates
this.element.addClass("ui-notify").children().addClass("ui-notify-message ui-notify-message-style").each(function(i){
var key = this.id || i;
self.keys.push(key);
self.templates[key] = $(this).removeAttr("id").wrap("<div></div>").parent().html(); // because $(this).andSelf().html() no workie
}).end().empty().show();
},
create: function(template, msg, opts){
if(typeof template === "object"){
opts = msg;
msg = template;
template = null;
}
var tpl = this.templates[ template || this.keys[0]];
// remove default styling class if rolling w/ custom classes
if(opts && opts.custom){
tpl = $(tpl).removeClass("ui-notify-message-style").wrap("<div></div>").parent().html();
}
this.openNotifications = this.openNotifications || 0;
// return a new notification instance
return new $.ech.notify.instance(this)._create(msg, $.extend({}, this.options, opts), tpl);
}
});
// instance constructor
$.extend($.ech.notify, {
instance: function(widget){
this.__super = widget;
this.isOpen = false;
}
});
// instance methods
$.extend($.ech.notify.instance.prototype, {
_create: function(params, options, template){
this.options = options;
var self = this,
// build html template
html = template.replace(/#(?:\{|%7B)(.*?)(?:\}|%7D)/g, function($1, $2){
return ($2 in params) ? params[$2] : '';
}),
// the actual message
m = (this.element = $(html)),
// close link
closelink = m.find(".ui-notify-close");
// clickable?
if(typeof this.options.click === "function"){
m.addClass("ui-notify-click").bind("click", function(e){
self._trigger("click", e, self);
});
}
// show close link?
if(closelink.length){
closelink.bind("click", function(){
self.close();
return false;
});
}
this.__super.element.queue("notify", function(){
self.open();
// auto expire?
if(typeof options.expires === "number" && options.expires > 0){
setTimeout($.proxy(self.close, self), options.expires);
}
});
if(!this.options.queue || this.__super.openNotifications <= this.options.queue - 1) {
this.__super.element.dequeue("notify");
}
return this;
},
close: function(){
var speed = this.options.speed;
this.element.fadeTo(speed, 0).slideUp(speed, $.proxy(function(){
this._trigger("close");
this.isOpen = false;
this.element.remove();
this.__super.openNotifications -= 1;
this.__super.element.dequeue("notify");
}, this));
return this;
},
open: function(){
if(this.isOpen || this._trigger("beforeopen") === false){
return this;
}
var self = this;
this.__super.openNotifications += 1;
this.element[this.options.stack === "above" ? "prependTo" : "appendTo"](this.__super.element).css({ display:"none", opacity:"" }).fadeIn(this.options.speed, function(){
self._trigger("open");
self.isOpen = true;
});
return this;
},
widget: function(){
return this.element;
},
_trigger: function(type, e, instance){
return this.__super._trigger.call( this, type, e, instance );
}
});
})(jQuery);

View file

@ -0,0 +1,7 @@
/* jQuery Notify UI Widget 1.5 by Eric Hynds
* http://www.erichynds.com/jquery/a-jquery-ui-growl-ubuntu-notification-widget/
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
(function(d){d.widget("ech.notify",{options:{speed:500,expires:5E3,stack:"below",custom:!1,queue:!1},_create:function(){var a=this;this.templates={};this.keys=[];this.element.addClass("ui-notify").children().addClass("ui-notify-message ui-notify-message-style").each(function(b){b=this.id||b;a.keys.push(b);a.templates[b]=d(this).removeAttr("id").wrap("<div></div>").parent().html()}).end().empty().show()},create:function(a,b,c){"object"===typeof a&&(c=b,b=a,a=null);a=this.templates[a||this.keys[0]];c&&c.custom&&(a=d(a).removeClass("ui-notify-message-style").wrap("<div></div>").parent().html());this.openNotifications=this.openNotifications||0;return(new d.ech.notify.instance(this))._create(b,d.extend({},this.options,c),a)}});d.extend(d.ech.notify,{instance:function(a){this.__super=a;this.isOpen=!1}});d.extend(d.ech.notify.instance.prototype,{_create:function(a,b,c){this.options=b;var e=this,c=c.replace(/#(?:\{|%7B)(.*?)(?:\}|%7D)/g,function(b,c){return c in a?a[c]:""}),c=this.element=d(c),f=c.find(".ui-notify-close");"function"===typeof this.options.click&&c.addClass("ui-notify-click").bind("click",function(a){e._trigger("click",a,e)});f.length&&f.bind("click",function(){e.close();return!1});this.__super.element.queue("notify",function(){e.open();"number"===typeof b.expires&&0<b.expires&&setTimeout(d.proxy(e.close,e),b.expires)});(!this.options.queue||this.__super.openNotifications<=this.options.queue-1)&&this.__super.element.dequeue("notify");return this},close:function(){var a=this.options.speed;this.element.fadeTo(a,0).slideUp(a,d.proxy(function(){this._trigger("close");this.isOpen=!1;this.element.remove();this.__super.openNotifications-=1;this.__super.element.dequeue("notify")},this));return this},open:function(){if(this.isOpen||!1===this._trigger("beforeopen"))return this;var a=this;this.__super.openNotifications+=1;this.element["above"===this.options.stack?"prependTo":"appendTo"](this.__super.element).css({display:"none",opacity:""}).fadeIn(this.options.speed,function(){a._trigger("open");a.isOpen=!0});return this},widget:function(){return this.element},_trigger:function(a,b,c){return this.__super._trigger.call(this,a,b,c)}})})(jQuery);

View file

@ -0,0 +1,74 @@
/* jQuery POST/GET redirect method
v.0.1
made by Nemanja Avramovic, www.avramovic.info
*/
(function( $ ){
$.fn.redirect = function( target, values, method ) {
if (method !== undefined)
{
method = method.toUpperCase();
if (method != 'GET')
method = 'POST';
}
else
method = 'POST';
if (values === undefined || values == false)
{
var obj = $().parse_url(target);
target = obj.url;
values = obj.params;
}
var form = $('<form></form');
form.attr('method', method);
form.attr('action', target);
for(var i in values)
{
var input = $('<input />');
input.attr('type', 'hidden');
input.attr('name', i);
input.attr('value', values[i]);
input.appendTo(form);
}
$('body').append(form);
form.submit();
};
$.fn.parse_url = function(url)
{
if (url.indexOf('?') == -1)
return { url: url, params: {} }
var parts = url.split('?');
var url = parts[0];
var query_string = parts[1];
var return_obj = {};
var elems = query_string.split('&');
var obj = {};
for(var i in elems)
{
var elem = elems[i];
var pair = elem.split('=');
obj[pair[0]] = pair[1];
}
return_obj.url = url;
return_obj.params = obj;
return return_obj;
}
})( jQuery );

View file

@ -0,0 +1 @@
(function(d){d.fn.redirect=function(a,b,c){void 0!==c?(c=c.toUpperCase(),"GET"!=c&&(c="POST")):c="POST";if(void 0===b||!1==b)b=d().parse_url(a),a=b.url,b=b.params;var e=d("<form></form");e.attr("method",c);e.attr("action",a);for(var f in b)a=d("<input />"),a.attr("type","hidden"),a.attr("name",f),a.attr("value",b[f]),a.appendTo(e);d("body").append(e);e.submit()};d.fn.parse_url=function(a){if(-1==a.indexOf("?"))return{url:a,params:{}};var b=a.split("?"),a=b[0],c={},b=b[1].split("&"),e={},d;for(d in b){var g= b[d].split("=");e[g[0]]=g[1]}c.url=a;c.params=e;return c}})(jQuery);

View file

@ -0,0 +1,130 @@
// https://civicrm.org/licensing
(function($) {
// Keep track of all header cells.
var cells = [];
// Attach to all headers.
$(document).ready(function() {
$('table thead.sticky').each(function () {
// Make all absolute positioned elements relative to the table.
var height = $(this).parent('table').css('position', 'relative').height();
// Find all header cells.
$('th', this).each(function () {
// Ensure each cell has an element in it.
var html = $(this).html();
if (html == ' ') {
html = '&nbsp;';
}
if ($(this).children().size() == 0) {
html = '<span>'+ html +'</span>';
}
// Clone and wrap cell contents in sticky wrapper that overlaps the cell's padding.
$('<div class="sticky-header" style="position: fixed; display: none; top: 0px;">'+ html +'</div>').prependTo(this);
var div = $('div.sticky-header', this).css({
'marginLeft': '-'+ $(this).css('paddingLeft'),
'marginRight': '-'+ $(this).css('paddingRight'),
'paddingLeft': $(this).css('paddingLeft'),
'paddingTop': $(this).css('paddingTop'),
'paddingRight': $(this).css('paddingRight'),
'paddingBottom': $(this).css('paddingBottom')
})[0];
// Adjust width to fit cell and hide.
//CRM-6467
var length = $(this).width() - $(div).width();
if ( length < 0 ) length = $(div).width() - $(this).width();
$(div).css('paddingRight', parseInt($(div).css('paddingRight')) + length +'px');
cells.push(div);
// Get position.
div.cell = this;
div.table = $(this).parent('table')[0];
div.stickyMax = height;
div.stickyPosition = $(this).y();
});
});
});
// Track scrolling.
var scroll = function() {
$(cells).each(function () {
// Fetch scrolling position.
var scroll = document.documentElement.scrollTop || document.body.scrollTop;
var offset = scroll - this.stickyPosition - 4;
if (offset > 0 && offset < this.stickyMax - 100) {
$(this).css({display:'block'});
}
else {
$(this).css('display', 'none');
}
});
};
$(window).scroll(scroll);
$(document.documentElement).scroll(scroll);
// Track resizing.
var resize = function () {
$(cells).each(function () {
// Get position.
$(this).css({ 'position': 'relative', 'top': '0'});
this.stickyPosition = $(this.cell).y();
this.stickyMax = $(this.table).height();
});
};
$(window).resize(resize);
// Track the element positions
$.fn.x = function(n) {
var result = null;
this.each(function() {
var o = this;
if (n === undefined) {
var x = 0;
if (o.offsetParent) {
while (o.offsetParent) {
x += o.offsetLeft;
o = o.offsetParent;
}
}
if (result === null) {
result = x;
} else {
result = Math.min(result, x);
}
} else {
o.style.left = n + 'px';
}
});
return result;
};
$.fn.y = function(n) {
var result = null;
this.each(function() {
var o = this;
if (n === undefined) {
var y = 0;
if (o.offsetParent) {
while (o.offsetParent) {
y += o.offsetTop;
o = o.offsetParent;
}
}
if (result === null) {
result = y;
} else {
result = Math.min(result, y);
}
} else {
o.style.top = n + 'px';
}
});
return result;
};
})(jQuery);

View file

@ -0,0 +1,931 @@
/* http://keith-wood.name/timeEntry.html
Time entry for jQuery v1.5.2.
Written by Keith Wood (kbwood{at}iinet.com.au) June 2007.
Available under the MIT (https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt) license.
Please attribute the author if you use it. */
/* Turn an input field into an entry point for a time value.
The time can be entered via directly typing the value,
via the arrow keys, or via spinner buttons.
It is configurable to show 12 or 24-hour time, to show or hide seconds,
to enforce a minimum and/or maximum time, to change the spinner image,
and to constrain the time to steps, e.g. only on the quarter hours.
Attach it with $('input selector').timeEntry(); for default settings,
or configure it with options like:
$('input selector').timeEntry(
{spinnerImage: 'spinnerSquare.png', spinnerSize: [20, 20, 0]}); */
(function($) { // Hide scope, no $ conflict
/* TimeEntry manager.
Use the singleton instance of this class, $.timeEntry, to interact with the time entry
functionality. Settings for (groups of) fields are maintained in an instance object,
allowing multiple different settings on the same page. */
function TimeEntry() {
this._disabledInputs = []; // List of time entry inputs that have been disabled
this.regional = []; // Available regional settings, indexed by language code
this.regional[''] = { // Default regional settings
show24Hours: false, // True to use 24 hour time, false for 12 hour (AM/PM)
separator: ':', // The separator between time fields
ampmPrefix: '', // The separator before the AM/PM text
ampmNames: ['AM', 'PM'], // Names of morning/evening markers
spinnerTexts: ['Now', 'Previous field', 'Next field', 'Increment', 'Decrement']
// The popup texts for the spinner image areas
};
this._defaults = {
appendText: '', // Display text following the input box, e.g. showing the format
showSeconds: false, // True to show seconds as well, false for hours/minutes only
timeSteps: [1, 1, 1], // Steps for each of hours/minutes/seconds when incrementing/decrementing
initialField: 0, // The field to highlight initially, 0 = hours, 1 = minutes, ...
noSeparatorEntry: false, // True to move to next sub-field after two digits entry
useMouseWheel: true, // True to use mouse wheel for increment/decrement if possible,
// false to never use it
defaultTime: null, // The time to use if none has been set, leave at null for now
minTime: null, // The earliest selectable time, or null for no limit
maxTime: null, // The latest selectable time, or null for no limit
spinnerImage: 'spinnerDefault.png', // The URL of the images to use for the time spinner
// Seven images packed horizontally for normal, each button pressed, and disabled
spinnerSize: [20, 20, 8], // The width and height of the spinner image,
// and size of centre button for current time
spinnerBigImage: '', // The URL of the images to use for the expanded time spinner
// Seven images packed horizontally for normal, each button pressed, and disabled
spinnerBigSize: [40, 40, 16], // The width and height of the expanded spinner image,
// and size of centre button for current time
spinnerIncDecOnly: false, // True for increment/decrement buttons only, false for all
spinnerRepeat: [500, 250], // Initial and subsequent waits in milliseconds
// for repeats on the spinner buttons
beforeShow: null, // Function that takes an input field and
// returns a set of custom settings for the time entry
beforeSetTime: null // Function that runs before updating the time,
// takes the old and new times, and minimum and maximum times as parameters,
// and returns an adjusted time if necessary
};
$.extend(this._defaults, this.regional['']);
}
$.extend(TimeEntry.prototype, {
/* Class name added to elements to indicate already configured with time entry. */
markerClassName: 'hasTimeEntry',
/* Name of the data property for instance settings. */
propertyName: 'timeEntry',
/* Class name for the appended content. */
_appendClass: 'timeEntry_append',
/* Class name for the time entry control. */
_controlClass: 'timeEntry_control',
/* Class name for the expanded spinner. */
_expandClass: 'timeEntry_expand',
/* Override the default settings for all instances of the time entry.
@param options (object) the new settings to use as defaults (anonymous object)
@return (DateEntry) this object */
setDefaults: function(options) {
$.extend(this._defaults, options || {});
return this;
},
/* Attach the time entry handler to an input field.
@param target (element) the field to attach to
@param options (object) custom settings for this instance */
_attachPlugin: function(target, options) {
var input = $(target);
if (input.hasClass(this.markerClassName)) {
return;
}
var inst = {options: $.extend({}, this._defaults, options), input: input, _field: 0,
_selectedHour: 0, _selectedMinute: 0, _selectedSecond: 0};
input.data(this.propertyName, inst).addClass(this.markerClassName).
bind('focus.' + this.propertyName, this._doFocus).
bind('blur.' + this.propertyName, this._doBlur).
bind('click.' + this.propertyName, this._doClick).
bind('keydown.' + this.propertyName, this._doKeyDown).
bind('keypress.' + this.propertyName, this._doKeyPress).
bind('paste.' + this.propertyName, function(event) { // Check pastes
setTimeout(function() { plugin._parseTime(inst); }, 1);
});
this._optionPlugin(target, options);
},
/* Retrieve or reconfigure the settings for a time entry control.
@param target (element) the control to affect
@param options (object) the new options for this instance or
(string) an individual property name
@param value (any) the individual property value (omit if options
is an object or to retrieve the value of a setting)
@return (any) if retrieving a value */
_optionPlugin: function(target, options, value) {
target = $(target);
var inst = target.data(this.propertyName);
if (!options || (typeof options == 'string' && value == null)) { // Get option
var name = options;
options = (inst || {}).options;
return (options && name ? options[name] : options);
}
if (!target.hasClass(this.markerClassName)) {
return;
}
options = options || {};
if (typeof options == 'string') {
var name = options;
options = {};
options[name] = value;
}
var currentTime = this._extractTime(inst);
$.extend(inst.options, options);
inst._field = 0;
if (currentTime) {
this._setTime(inst, new Date(0, 0, 0, currentTime[0], currentTime[1], currentTime[2]));
}
// Remove stuff dependent on old settings
target.next('span.' + this._appendClass).remove();
target.parent().find('span.' + this._controlClass).remove();
if ($.fn.mousewheel) {
target.unmousewheel();
}
// And re-add if requested
var spinner = (!inst.options.spinnerImage ? null :
$('<span class="' + this._controlClass + '" style="display: inline-block; ' +
'background: url(\'' + inst.options.spinnerImage + '\') 0 0 no-repeat; width: ' +
inst.options.spinnerSize[0] + 'px; height: ' + inst.options.spinnerSize[1] + 'px;"></span>'));
target.after(inst.options.appendText ? '<span class="' + this._appendClass + '">' +
inst.options.appendText + '</span>' : '').after(spinner || '');
// Allow mouse wheel usage
if (inst.options.useMouseWheel && $.fn.mousewheel) {
target.mousewheel(this._doMouseWheel);
}
if (spinner) {
spinner.mousedown(this._handleSpinner).mouseup(this._endSpinner).
mouseover(this._expandSpinner).mouseout(this._endSpinner).
mousemove(this._describeSpinner);
}
},
/* Enable a time entry input and any associated spinner.
@param target (element) single input field */
_enablePlugin: function(target) {
this._enableDisable(target, false);
},
/* Disable a time entry input and any associated spinner.
@param target (element) single input field */
_disablePlugin: function(target) {
this._enableDisable(target, true);
},
/* Enable or disable a time entry input and any associated spinner.
@param target (element) single input field
@param disable (boolean) true to disable, false to enable */
_enableDisable: function(target, disable) {
var inst = $.data(target, this.propertyName);
if (!inst) {
return;
}
target.disabled = disable;
if (target.nextSibling && target.nextSibling.nodeName.toLowerCase() == 'span') {
plugin._changeSpinner(inst, target.nextSibling, (disable ? 5 : -1));
}
plugin._disabledInputs = $.map(plugin._disabledInputs,
function(value) { return (value == target ? null : value); }); // Delete entry
if (disable) {
plugin._disabledInputs.push(target);
}
},
/* Check whether an input field has been disabled.
@param target (element) input field to check
@return (boolean) true if this field has been disabled, false if it is enabled */
_isDisabledPlugin: function(target) {
return $.inArray(target, this._disabledInputs) > -1;
},
/* Remove the time entry functionality from an input.
@param target (element) the control to affect */
_destroyPlugin: function(target) {
target = $(target);
if (!target.hasClass(this.markerClassName)) {
return;
}
target.removeClass(this.markerClassName).removeData(this.propertyName).
unbind('.' + this.propertyName);
if ($.fn.mousewheel) {
target.unmousewheel();
}
this._disabledInputs = $.map(this._disabledInputs,
function(value) { return (value == target[0] ? null : value); }); // Delete entry
target.siblings('.' + this._appendClass + ',.' + this._controlClass).remove();
},
/* Initialise the current time for a time entry input field.
@param target (element) input field to update
@param time (Date) the new time (year/month/day ignored) or null for now */
_setTimePlugin: function(target, time) {
var inst = $.data(target, this.propertyName);
if (inst) {
if (time === null || time === '') {
inst.input.val('');
}
else {
this._setTime(inst, time ? (typeof time == 'object' ?
new Date(time.getTime()) : time) : null);
}
}
},
/* Retrieve the current time for a time entry input field.
@param target (element) input field to examine
@return (Date) current time (year/month/day zero) or null if none */
_getTimePlugin: function(target) {
var inst = $.data(target, this.propertyName);
var currentTime = (inst ? this._extractTime(inst) : null);
return (!currentTime ? null :
new Date(0, 0, 0, currentTime[0], currentTime[1], currentTime[2]));
},
/* Retrieve the millisecond offset for the current time.
@param target (element) input field to examine
@return (number) the time as milliseconds offset or zero if none */
_getOffsetPlugin: function(target) {
var inst = $.data(target, this.propertyName);
var currentTime = (inst ? this._extractTime(inst) : null);
return (!currentTime ? 0 :
(currentTime[0] * 3600 + currentTime[1] * 60 + currentTime[2]) * 1000);
},
/* Initialise time entry.
@param target (element) the input field or
(event) the focus event */
_doFocus: function(target) {
var input = (target.nodeName && target.nodeName.toLowerCase() == 'input' ? target : this);
if (plugin._lastInput == input || plugin._isDisabledPlugin(input)) {
plugin._focussed = false;
return;
}
var inst = $.data(input, plugin.propertyName);
plugin._focussed = true;
plugin._lastInput = input;
plugin._blurredInput = null;
$.extend(inst.options, ($.isFunction(inst.options.beforeShow) ?
inst.options.beforeShow.apply(input, [input]) : {}));
plugin._parseTime(inst);
setTimeout(function() { plugin._showField(inst); }, 10);
},
/* Note that the field has been exited.
@param event (event) the blur event */
_doBlur: function(event) {
plugin._blurredInput = plugin._lastInput;
plugin._lastInput = null;
},
/* Select appropriate field portion on click, if already in the field.
@param event (event) the click event */
_doClick: function(event) {
var input = event.target;
var inst = $.data(input, plugin.propertyName);
var prevField = inst._field;
if (!plugin._focussed) {
var fieldSize = inst.options.separator.length + 2;
inst._field = 0;
if (input.selectionStart != null) { // Use input select range
for (var field = 0; field <= Math.max(1, inst._secondField, inst._ampmField); field++) {
var end = (field != inst._ampmField ? (field * fieldSize) + 2 :
(inst._ampmField * fieldSize) + inst.options.ampmPrefix.length +
inst.options.ampmNames[0].length);
inst._field = field;
if (input.selectionStart < end) {
break;
}
}
}
else if (input.createTextRange) { // Check against bounding boxes
var src = $(event.srcElement);
var range = input.createTextRange();
var convert = function(value) {
return {thin: 2, medium: 4, thick: 6}[value] || value;
};
var offsetX = event.clientX + document.documentElement.scrollLeft -
(src.offset().left + parseInt(convert(src.css('border-left-width')), 10)) -
range.offsetLeft; // Position - left edge - alignment
for (var field = 0; field <= Math.max(1, inst._secondField, inst._ampmField); field++) {
var end = (field != inst._ampmField ? (field * fieldSize) + 2 :
(inst._ampmField * fieldSize) + inst.options.ampmPrefix.length +
inst.options.ampmNames[0].length);
range.collapse();
range.moveEnd('character', end);
inst._field = field;
if (offsetX < range.boundingWidth) { // And compare
break;
}
}
}
}
if (prevField != inst._field) {
inst._lastChr = '';
}
plugin._showField(inst);
plugin._focussed = false;
},
/* Handle keystrokes in the field.
@param event (event) the keydown event
@return (boolean) true to continue, false to stop processing */
_doKeyDown: function(event) {
if (event.keyCode >= 48) { // >= '0'
return true;
}
var inst = $.data(event.target, plugin.propertyName);
switch (event.keyCode) {
case 9: return (event.shiftKey ?
// Move to previous time field, or out if at the beginning
plugin._changeField(inst, -1, true) :
// Move to next time field, or out if at the end
plugin._changeField(inst, +1, true));
case 35: if (event.ctrlKey) { // Clear time on ctrl+end
plugin._setValue(inst, '');
}
else { // Last field on end
inst._field = Math.max(1, inst._secondField, inst._ampmField);
plugin._adjustField(inst, 0);
}
break;
case 36: if (event.ctrlKey) { // Current time on ctrl+home
plugin._setTime(inst);
}
else { // First field on home
inst._field = 0;
plugin._adjustField(inst, 0);
}
break;
case 37: plugin._changeField(inst, -1, false); break; // Previous field on left
case 38: plugin._adjustField(inst, +1); break; // Increment time field on up
case 39: plugin._changeField(inst, +1, false); break; // Next field on right
case 40: plugin._adjustField(inst, -1); break; // Decrement time field on down
case 46: plugin._setValue(inst, ''); break; // Clear time on delete
default: return true;
}
return false;
},
/* Disallow unwanted characters.
@param event (event) the keypress event
@return (boolean) true to continue, false to stop processing */
_doKeyPress: function(event) {
var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
if (chr < ' ') {
return true;
}
var inst = $.data(event.target, plugin.propertyName);
plugin._handleKeyPress(inst, chr);
return false;
},
/* Increment/decrement on mouse wheel activity.
@param event (event) the mouse wheel event
@param delta (number) the amount of change */
_doMouseWheel: function(event, delta) {
if (plugin._isDisabledPlugin(event.target)) {
return;
}
var inst = $.data(event.target, plugin.propertyName);
inst.input.focus();
if (!inst.input.val()) {
plugin._parseTime(inst);
}
plugin._adjustField(inst, delta);
event.preventDefault();
},
/* Expand the spinner, if possible, to make it easier to use.
@param event (event) the mouse over event */
_expandSpinner: function(event) {
var spinner = plugin._getSpinnerTarget(event);
var inst = $.data(plugin._getInput(spinner), plugin.propertyName);
if (plugin._isDisabledPlugin(inst.input[0])) {
return;
}
if (inst.options.spinnerBigImage) {
inst._expanded = true;
var offset = $(spinner).offset();
var relative = null;
$(spinner).parents().each(function() {
var parent = $(this);
if (parent.css('position') == 'relative' ||
parent.css('position') == 'absolute') {
relative = parent.offset();
}
return !relative;
});
$('<div class="' + plugin._expandClass + '" style="position: absolute; left: ' +
(offset.left - (inst.options.spinnerBigSize[0] - inst.options.spinnerSize[0]) / 2 -
(relative ? relative.left : 0)) + 'px; top: ' +
(offset.top - (inst.options.spinnerBigSize[1] - inst.options.spinnerSize[1]) / 2 -
(relative ? relative.top : 0)) + 'px; width: ' +
inst.options.spinnerBigSize[0] + 'px; height: ' +
inst.options.spinnerBigSize[1] + 'px; background: transparent url(' +
inst.options.spinnerBigImage + ') no-repeat 0px 0px; z-index: 10;"></div>').
mousedown(plugin._handleSpinner).mouseup(plugin._endSpinner).
mouseout(plugin._endExpand).mousemove(plugin._describeSpinner).
insertAfter(spinner);
}
},
/* Locate the actual input field from the spinner.
@param spinner (element) the current spinner
@return (element) the corresponding input */
_getInput: function(spinner) {
return $(spinner).siblings('.' + plugin.markerClassName)[0];
},
/* Change the title based on position within the spinner.
@param event (event) the mouse move event */
_describeSpinner: function(event) {
var spinner = plugin._getSpinnerTarget(event);
var inst = $.data(plugin._getInput(spinner), plugin.propertyName);
spinner.title = inst.options.spinnerTexts[plugin._getSpinnerRegion(inst, event)];
},
/* Handle a click on the spinner.
@param event (event) the mouse click event */
_handleSpinner: function(event) {
var spinner = plugin._getSpinnerTarget(event);
var input = plugin._getInput(spinner);
if (plugin._isDisabledPlugin(input)) {
return;
}
if (input == plugin._blurredInput) {
plugin._lastInput = input;
plugin._blurredInput = null;
}
var inst = $.data(input, plugin.propertyName);
plugin._doFocus(input);
var region = plugin._getSpinnerRegion(inst, event);
plugin._changeSpinner(inst, spinner, region);
plugin._actionSpinner(inst, region);
plugin._timer = null;
plugin._handlingSpinner = true;
if (region >= 3 && inst.options.spinnerRepeat[0]) { // Repeat increment/decrement
plugin._timer = setTimeout(
function() { plugin._repeatSpinner(inst, region); },
inst.options.spinnerRepeat[0]);
$(spinner).one('mouseout', plugin._releaseSpinner).
one('mouseup', plugin._releaseSpinner);
}
},
/* Action a click on the spinner.
@param inst (object) the instance settings
@param region (number) the spinner "button" */
_actionSpinner: function(inst, region) {
if (!inst.input.val()) {
plugin._parseTime(inst);
}
switch (region) {
case 0: this._setTime(inst); break;
case 1: this._changeField(inst, -1, false); break;
case 2: this._changeField(inst, +1, false); break;
case 3: this._adjustField(inst, +1); break;
case 4: this._adjustField(inst, -1); break;
}
},
/* Repeat a click on the spinner.
@param inst (object) the instance settings
@param region (number) the spinner "button" */
_repeatSpinner: function(inst, region) {
if (!plugin._timer) {
return;
}
plugin._lastInput = plugin._blurredInput;
this._actionSpinner(inst, region);
this._timer = setTimeout(
function() { plugin._repeatSpinner(inst, region); },
inst.options.spinnerRepeat[1]);
},
/* Stop a spinner repeat.
@param event (event) the mouse event */
_releaseSpinner: function(event) {
clearTimeout(plugin._timer);
plugin._timer = null;
},
/* Tidy up after an expanded spinner.
@param event (event) the mouse event */
_endExpand: function(event) {
plugin._timer = null;
var spinner = plugin._getSpinnerTarget(event);
var input = plugin._getInput(spinner);
var inst = $.data(input, plugin.propertyName);
$(spinner).remove();
inst._expanded = false;
},
/* Tidy up after a spinner click.
@param event (event) the mouse event */
_endSpinner: function(event) {
plugin._timer = null;
var spinner = plugin._getSpinnerTarget(event);
var input = plugin._getInput(spinner);
var inst = $.data(input, plugin.propertyName);
if (!plugin._isDisabledPlugin(input)) {
plugin._changeSpinner(inst, spinner, -1);
}
if (plugin._handlingSpinner) {
plugin._lastInput = plugin._blurredInput;
}
if (plugin._lastInput && plugin._handlingSpinner) {
plugin._showField(inst);
}
plugin._handlingSpinner = false;
},
/* Retrieve the spinner from the event.
@param event (event) the mouse click event
@return (element) the target field */
_getSpinnerTarget: function(event) {
return event.target || event.srcElement;
},
/* Determine which "button" within the spinner was clicked.
@param inst (object) the instance settings
@param event (event) the mouse event
@return (number) the spinner "button" number */
_getSpinnerRegion: function(inst, event) {
var spinner = this._getSpinnerTarget(event);
var pos = $(spinner).offset();
var scrolled = [document.documentElement.scrollLeft || document.body.scrollLeft,
document.documentElement.scrollTop || document.body.scrollTop];
var left = (inst.options.spinnerIncDecOnly ? 99 : event.clientX + scrolled[0] - pos.left);
var top = event.clientY + scrolled[1] - pos.top;
var spinnerSize = inst.options[inst._expanded ? 'spinnerBigSize' : 'spinnerSize'];
var right = (inst.options.spinnerIncDecOnly ? 99 : spinnerSize[0] - 1 - left);
var bottom = spinnerSize[1] - 1 - top;
if (spinnerSize[2] > 0 && Math.abs(left - right) <= spinnerSize[2] &&
Math.abs(top - bottom) <= spinnerSize[2]) {
return 0; // Centre button
}
var min = Math.min(left, top, right, bottom);
return (min == left ? 1 : (min == right ? 2 : (min == top ? 3 : 4))); // Nearest edge
},
/* Change the spinner image depending on button clicked.
@param inst (object) the instance settings
@param spinner (element) the spinner control
@param region (number) the spinner "button" */
_changeSpinner: function(inst, spinner, region) {
$(spinner).css('background-position', '-' + ((region + 1) *
inst.options[inst._expanded ? 'spinnerBigSize' : 'spinnerSize'][0]) + 'px 0px');
},
/* Extract the time value from the input field, or default to now.
@param inst (object) the instance settings */
_parseTime: function(inst) {
var currentTime = this._extractTime(inst);
if (currentTime) {
inst._selectedHour = currentTime[0];
inst._selectedMinute = currentTime[1];
inst._selectedSecond = currentTime[2];
}
else {
var now = this._constrainTime(inst);
inst._selectedHour = now[0];
inst._selectedMinute = now[1];
inst._selectedSecond = (inst.options.showSeconds ? now[2] : 0);
}
inst._secondField = (inst.options.showSeconds ? 2 : -1);
inst._ampmField = (inst.options.show24Hours ? -1 : (inst.options.showSeconds ? 3 : 2));
inst._lastChr = '';
inst._field = Math.max(0, Math.min(
Math.max(1, inst._secondField, inst._ampmField), inst.options.initialField));
if (inst.input.val() != '') {
this._showTime(inst);
}
},
/* Extract the time value from a string as an array of values, or default to null.
@param inst (object) the instance settings
@param value (string) the time value to parse
@return (number[3]) the time components (hours, minutes, seconds)
or null if no value */
_extractTime: function(inst, value) {
value = value || inst.input.val();
var currentTime = value.split(inst.options.separator);
if (inst.options.separator == '' && value != '') {
currentTime[0] = value.substring(0, 2);
currentTime[1] = value.substring(2, 4);
currentTime[2] = value.substring(4, 6);
}
if (currentTime.length >= 2) {
var isAM = !inst.options.show24Hours && (value.indexOf(inst.options.ampmNames[0]) > -1);
var isPM = !inst.options.show24Hours && (value.indexOf(inst.options.ampmNames[1]) > -1);
var hour = parseInt(currentTime[0], 10);
hour = (isNaN(hour) ? 0 : hour);
hour = ((isAM || isPM) && hour == 12 ? 0 : hour) + (isPM ? 12 : 0);
var minute = parseInt(currentTime[1], 10);
minute = (isNaN(minute) ? 0 : minute);
var second = (currentTime.length >= 3 ?
parseInt(currentTime[2], 10) : 0);
second = (isNaN(second) || !inst.options.showSeconds ? 0 : second);
return this._constrainTime(inst, [hour, minute, second]);
}
return null;
},
/* Constrain the given/current time to the time steps.
@param inst (object) the instance settings
@param fields (number[3]) the current time components (hours, minutes, seconds)
@return (number[3]) the constrained time components (hours, minutes, seconds) */
_constrainTime: function(inst, fields) {
var specified = (fields != null);
if (!specified) {
var now = this._determineTime(inst.options.defaultTime, inst) || new Date();
fields = [now.getHours(), now.getMinutes(), now.getSeconds()];
}
var reset = false;
for (var i = 0; i < inst.options.timeSteps.length; i++) {
if (reset) {
fields[i] = 0;
}
else if (inst.options.timeSteps[i] > 1) {
fields[i] = Math.round(fields[i] / inst.options.timeSteps[i]) *
inst.options.timeSteps[i];
reset = true;
}
}
return fields;
},
/* Set the selected time into the input field.
@param inst (object) the instance settings */
_showTime: function(inst) {
var currentTime = (this._formatNumber(inst.options.show24Hours ? inst._selectedHour :
((inst._selectedHour + 11) % 12) + 1) + inst.options.separator +
this._formatNumber(inst._selectedMinute) +
(inst.options.showSeconds ? inst.options.separator +
this._formatNumber(inst._selectedSecond) : '') +
(inst.options.show24Hours ? '' : inst.options.ampmPrefix +
inst.options.ampmNames[(inst._selectedHour < 12 ? 0 : 1)]));
this._setValue(inst, currentTime);
this._showField(inst);
},
/* Highlight the current time field.
@param inst (object) the instance settings */
_showField: function(inst) {
var input = inst.input[0];
if (inst.input.is(':hidden') || plugin._lastInput != input) {
return;
}
var fieldSize = inst.options.separator.length + 2;
var start = (inst._field != inst._ampmField ? (inst._field * fieldSize) :
(inst._ampmField * fieldSize) - inst.options.separator.length +
inst.options.ampmPrefix.length);
var end = start + (inst._field != inst._ampmField ? 2 : inst.options.ampmNames[0].length);
if (input.setSelectionRange) { // Mozilla
input.setSelectionRange(start, end);
}
else if (input.createTextRange) { // IE
var range = input.createTextRange();
range.moveStart('character', start);
range.moveEnd('character', end - inst.input.val().length);
range.select();
}
if (!input.disabled) {
input.focus();
}
},
/* Ensure displayed single number has a leading zero.
@param value (number) current value
@return (string) number with at least two digits */
_formatNumber: function(value) {
return (value < 10 ? '0' : '') + value;
},
/* Update the input field and notify listeners.
@param inst (object) the instance settings
@param value (string) the new value */
_setValue: function(inst, value) {
if (value != inst.input.val()) {
inst.input.val(value).trigger('change');
}
},
/* Move to previous/next field, or out of field altogether if appropriate.
@param inst (object) the instance settings
@param offset (number) the direction of change (-1, +1)
@param moveOut (boolean) true if can move out of the field
@return (boolean) true if exitting the field, false if not */
_changeField: function(inst, offset, moveOut) {
var atFirstLast = (inst.input.val() == '' || inst._field ==
(offset == -1 ? 0 : Math.max(1, inst._secondField, inst._ampmField)));
if (!atFirstLast) {
inst._field += offset;
}
this._showField(inst);
inst._lastChr = '';
return (atFirstLast && moveOut);
},
/* Update the current field in the direction indicated.
@param inst (object) the instance settings
@param offset (number) the amount to change by */
_adjustField: function(inst, offset) {
if (inst.input.val() == '') {
offset = 0;
}
this._setTime(inst, new Date(0, 0, 0,
inst._selectedHour + (inst._field == 0 ? offset * inst.options.timeSteps[0] : 0) +
(inst._field == inst._ampmField ? offset * 12 : 0),
inst._selectedMinute + (inst._field == 1 ? offset * inst.options.timeSteps[1] : 0),
inst._selectedSecond +
(inst._field == inst._secondField ? offset * inst.options.timeSteps[2] : 0)));
},
/* Check against minimum/maximum and display time.
@param inst (object) the instance settings
@param time (Date) an actual time or
(number) offset in seconds from now or
(string) units and periods of offsets from now */
_setTime: function(inst, time) {
time = this._determineTime(time, inst);
var fields = this._constrainTime(inst, time ?
[time.getHours(), time.getMinutes(), time.getSeconds()] : null);
time = new Date(0, 0, 0, fields[0], fields[1], fields[2]);
// Normalise to base date
var time = this._normaliseTime(time);
var minTime = this._normaliseTime(this._determineTime(inst.options.minTime, inst));
var maxTime = this._normaliseTime(this._determineTime(inst.options.maxTime, inst));
// Ensure it is within the bounds set
if (minTime && maxTime && minTime > maxTime) {
if (time < minTime && time > maxTime) {
time = (Math.abs(time - minTime) < Math.abs(time - maxTime) ? minTime : maxTime);
}
}
else {
time = (minTime && time < minTime ? minTime :
(maxTime && time > maxTime ? maxTime : time));
}
// Perform further restrictions if required
if ($.isFunction(inst.options.beforeSetTime)) {
time = inst.options.beforeSetTime.apply(inst.input[0],
[this._getTimePlugin(inst.input[0]), time, minTime, maxTime]);
}
inst._selectedHour = time.getHours();
inst._selectedMinute = time.getMinutes();
inst._selectedSecond = time.getSeconds();
this._showTime(inst);
},
/* A time may be specified as an exact value or a relative one.
@param setting (Date) an actual time or
(number) offset in seconds from now or
(string) units and periods of offsets from now
@param inst (object) the instance settings
@return (Date) the calculated time */
_determineTime: function(setting, inst) {
var offsetNumeric = function(offset) { // E.g. +300, -2
var time = new Date();
time.setTime(time.getTime() + offset * 1000);
return time;
};
var offsetString = function(offset) { // E.g. '+2m', '-4h', '+3h +30m' or '12:34:56PM'
var fields = plugin._extractTime(inst, offset); // Actual time?
var time = new Date();
var hour = (fields ? fields[0] : time.getHours());
var minute = (fields ? fields[1] : time.getMinutes());
var second = (fields ? fields[2] : time.getSeconds());
if (!fields) {
var pattern = /([+-]?[0-9]+)\s*(s|S|m|M|h|H)?/g;
var matches = pattern.exec(offset);
while (matches) {
switch (matches[2] || 's') {
case 's' : case 'S' :
second += parseInt(matches[1], 10); break;
case 'm' : case 'M' :
minute += parseInt(matches[1], 10); break;
case 'h' : case 'H' :
hour += parseInt(matches[1], 10); break;
}
matches = pattern.exec(offset);
}
}
time = new Date(0, 0, 10, hour, minute, second, 0);
if (/^!/.test(offset)) { // No wrapping
if (time.getDate() > 10) {
time = new Date(0, 0, 10, 23, 59, 59);
}
else if (time.getDate() < 10) {
time = new Date(0, 0, 10, 0, 0, 0);
}
}
return time;
};
return (setting ? (typeof setting == 'string' ? offsetString(setting) :
(typeof setting == 'number' ? offsetNumeric(setting) : setting)) : null);
},
/* Normalise time object to a common date.
@param time (Date) the original time
@return (Date) the normalised time */
_normaliseTime: function(time) {
if (!time) {
return null;
}
time.setFullYear(1900);
time.setMonth(0);
time.setDate(0);
return time;
},
/* Update time based on keystroke entered.
@param inst (object) the instance settings
@param chr (ch) the new character */
_handleKeyPress: function(inst, chr) {
if (chr == inst.options.separator) {
this._changeField(inst, +1, false);
}
else if (chr >= '0' && chr <= '9') { // Allow direct entry of time
var key = parseInt(chr, 10);
var value = parseInt(inst._lastChr + chr, 10);
var hour = (inst._field != 0 ? inst._selectedHour :
(inst.options.show24Hours ? (value < 24 ? value : key) :
(value >= 1 && value <= 12 ? value :
(key > 0 ? key : inst._selectedHour)) % 12 +
(inst._selectedHour >= 12 ? 12 : 0)));
var minute = (inst._field != 1 ? inst._selectedMinute :
(value < 60 ? value : key));
var second = (inst._field != inst._secondField ? inst._selectedSecond :
(value < 60 ? value : key));
var fields = this._constrainTime(inst, [hour, minute, second]);
this._setTime(inst, new Date(0, 0, 0, fields[0], fields[1], fields[2]));
if (inst.options.noSeparatorEntry && inst._lastChr) {
this._changeField(inst, +1, false);
}
else {
inst._lastChr = chr;
}
}
else if (!inst.options.show24Hours) { // Set am/pm based on first char of names
chr = chr.toLowerCase();
if ((chr == inst.options.ampmNames[0].substring(0, 1).toLowerCase() &&
inst._selectedHour >= 12) ||
(chr == inst.options.ampmNames[1].substring(0, 1).toLowerCase() &&
inst._selectedHour < 12)) {
var saveField = inst._field;
inst._field = inst._ampmField;
this._adjustField(inst, +1);
inst._field = saveField;
this._showField(inst);
}
}
}
});
// The list of commands that return values and don't permit chaining
var getters = ['getOffset', 'getTime', 'isDisabled'];
/* Determine whether a command is a getter and doesn't permit chaining.
@param command (string, optional) the command to run
@param otherArgs ([], optional) any other arguments for the command
@return true if the command is a getter, false if not */
function isNotChained(command, otherArgs) {
if (command == 'option' && (otherArgs.length == 0 ||
(otherArgs.length == 1 && typeof otherArgs[0] == 'string'))) {
return true;
}
return $.inArray(command, getters) > -1;
}
/* Attach the time entry functionality to a jQuery selection.
@param options (object) the new settings to use for these instances (optional) or
(string) the command to run (optional)
@return (jQuery) for chaining further calls or
(any) getter value */
$.fn.timeEntry = function(options) {
var otherArgs = Array.prototype.slice.call(arguments, 1);
if (isNotChained(options, otherArgs)) {
return plugin['_' + options + 'Plugin'].
apply(plugin, [this[0]].concat(otherArgs));
}
return this.each(function() {
if (typeof options == 'string') {
if (!plugin['_' + options + 'Plugin']) {
throw 'Unknown command: ' + options;
}
plugin['_' + options + 'Plugin'].
apply(plugin, [this].concat(otherArgs));
}
else {
// Check for settings on the control itself
var inlineSettings = ($.fn.metadata ? $(this).metadata() : {});
plugin._attachPlugin(this, $.extend({}, inlineSettings, options || {}));
}
});
};
/* Initialise the time entry functionality. */
var plugin = $.timeEntry = new TimeEntry(); // Singleton instance
})(jQuery);

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,861 @@
/*
* jQuery Plugin: Tokenizing Autocomplete Text Entry
* Version 1.6.0
*
* Copyright (c) 2009 James Smith (http://loopj.com)
* Licensed jointly under the GPL and MIT licenses,
* choose which one suits your project best!
*
*/
(function ($) {
// Default settings
var DEFAULT_SETTINGS = {
// Search settings
method: "GET",
contentType: "json",
queryParam: "name",
searchDelay: 300,
minChars: 1,
propertyToSearch: "name",
jsonContainer: null,
// Display settings
hintText: "Type in a search term",
noResultsText: "No results",
searchingText: "Searching...",
deleteText: "&times;",
animateDropdown: true,
// Tokenization settings
tokenLimit: null,
tokenDelimiter: ",",
preventDuplicates: false,
// Output settings
tokenValue: "id",
// Prepopulation settings
prePopulate: null,
processPrePopulate: false,
// Manipulation settings
idPrefix: "token-input-",
// Formatters
resultsFormatter: function(item){ return "<li>" + item[this.propertyToSearch]+ "</li>" },
tokenFormatter: function(item) { return "<li><p>" + item[this.propertyToSearch] + "</p></li>" },
// Callbacks
onResult: null,
onAdd: null,
onDelete: null,
onReady: null
};
// Default classes to use when theming
var DEFAULT_CLASSES = {
tokenList: "token-input-list",
token: "token-input-token",
tokenDelete: "token-input-delete-token",
selectedToken: "token-input-selected-token",
highlightedToken: "token-input-highlighted-token",
dropdown: "token-input-dropdown",
dropdownItem: "token-input-dropdown-item",
dropdownItem2: "token-input-dropdown-item2",
selectedDropdownItem: "token-input-selected-dropdown-item",
inputToken: "token-input-input-token"
};
// Input box position "enum"
var POSITION = {
BEFORE: 0,
AFTER: 1,
END: 2
};
// Keys "enum"
var KEY = {
BACKSPACE: 8,
TAB: 9,
ENTER: 13,
ESCAPE: 27,
SPACE: 32,
PAGE_UP: 33,
PAGE_DOWN: 34,
END: 35,
HOME: 36,
LEFT: 37,
UP: 38,
RIGHT: 39,
DOWN: 40,
NUMPAD_ENTER: 108,
COMMA: 188
};
// Additional public (exposed) methods
var methods = {
init: function(url_or_data_or_function, options) {
var settings = $.extend({}, DEFAULT_SETTINGS, options || {});
return this.each(function () {
$(this).data("tokenInputObject", new $.TokenList(this, url_or_data_or_function, settings));
});
},
clear: function() {
this.data("tokenInputObject").clear();
return this;
},
add: function(item) {
this.data("tokenInputObject").add(item);
return this;
},
remove: function(item) {
this.data("tokenInputObject").remove(item);
return this;
},
get: function() {
return this.data("tokenInputObject").getTokens();
}
}
// Expose the .tokenInput function to jQuery as a plugin
$.fn.tokenInput = function (method) {
// Method calling and initialization logic
if(methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else {
return methods.init.apply(this, arguments);
}
};
// TokenList class for each input
$.TokenList = function (input, url_or_data, settings) {
//
// Initialization
//
// Configure the data source
if($.type(url_or_data) === "string" || $.type(url_or_data) === "function") {
// Set the url to query against
settings.url = url_or_data;
// If the URL is a function, evaluate it here to do our initalization work
var url = computeURL();
// Make a smart guess about cross-domain if it wasn't explicitly specified
if(settings.crossDomain === undefined) {
if(url.indexOf("://") === -1) {
settings.crossDomain = false;
} else {
settings.crossDomain = (location.href.split(/\/+/g)[1] !== url.split(/\/+/g)[1]);
}
}
} else if(typeof(url_or_data) === "object") {
// Set the local data to search through
settings.local_data = url_or_data;
}
// Build class names
if(settings.classes) {
// Use custom class names
settings.classes = $.extend({}, DEFAULT_CLASSES, settings.classes);
} else if(settings.theme) {
// Use theme-suffixed default class names
settings.classes = {};
$.each(DEFAULT_CLASSES, function(key, value) {
settings.classes[key] = value + "-" + settings.theme;
});
} else {
settings.classes = DEFAULT_CLASSES;
}
// Save the tokens
var saved_tokens = [];
// Keep track of the number of tokens in the list
var token_count = 0;
// Basic cache to save on db hits
var cache = new $.TokenList.Cache();
// Keep track of the timeout, old vals
var timeout;
var input_val;
// Create a new text input an attach keyup events
var input_box = $("<input type=\"text\" autocomplete=\"off\">")
.css({
outline: "none"
})
.attr("id", settings.idPrefix + input.id)
.click(function () {
if (settings.tokenLimit === null || settings.tokenLimit !== token_count) {
show_dropdown_hint();
}
})
.blur(function () {
hide_dropdown();
$(this).val("");
})
.bind("keyup keydown blur update", resize_input)
.keydown(function (event) {
var previous_token;
var next_token;
switch(event.keyCode) {
case KEY.LEFT:
case KEY.RIGHT:
case KEY.UP:
case KEY.DOWN:
if(!$(this).val()) {
previous_token = input_token.prev();
next_token = input_token.next();
if((previous_token.length && previous_token.get(0) === selected_token) || (next_token.length && next_token.get(0) === selected_token)) {
// Check if there is a previous/next token and it is selected
if(event.keyCode === KEY.LEFT || event.keyCode === KEY.UP) {
deselect_token($(selected_token), POSITION.BEFORE);
} else {
deselect_token($(selected_token), POSITION.AFTER);
}
} else if((event.keyCode === KEY.LEFT || event.keyCode === KEY.UP) && previous_token.length) {
// We are moving left, select the previous token if it exists
select_token($(previous_token.get(0)));
} else if((event.keyCode === KEY.RIGHT || event.keyCode === KEY.DOWN) && next_token.length) {
// We are moving right, select the next token if it exists
select_token($(next_token.get(0)));
}
} else {
var dropdown_item = null;
if(event.keyCode === KEY.DOWN || event.keyCode === KEY.RIGHT) {
dropdown_item = $(selected_dropdown_item).next();
} else {
dropdown_item = $(selected_dropdown_item).prev();
}
if(dropdown_item.length) {
select_dropdown_item(dropdown_item);
}
return false;
}
break;
case KEY.BACKSPACE:
previous_token = input_token.prev();
if(!$(this).val().length) {
if(selected_token) {
delete_token($(selected_token));
hidden_input.change();
} else if(previous_token.length) {
select_token($(previous_token.get(0)));
}
return false;
} else if($(this).val().length === 1) {
hide_dropdown();
} else {
// set a timeout just long enough to let this function finish.
setTimeout(function(){do_search();}, 5);
}
break;
case KEY.TAB:
case KEY.ENTER:
case KEY.NUMPAD_ENTER:
// Comma should NOT select token CRM-8488
// case KEY.COMMA:
if(selected_dropdown_item) {
add_token($(selected_dropdown_item).data("tokeninput"));
hidden_input.change();
return false;
}
break;
case KEY.ESCAPE:
hide_dropdown();
return true;
default:
if(String.fromCharCode(event.which)) {
// set a timeout just long enough to let this function finish.
setTimeout(function(){do_search();}, 5);
}
break;
}
});
// Keep a reference to the original input box
var hidden_input = $(input)
.hide()
.val("")
.focus(function () {
input_box.focus();
})
.blur(function () {
input_box.blur();
});
// Keep a reference to the selected token and dropdown item
var selected_token = null;
var selected_token_index = 0;
var selected_dropdown_item = null;
// The list to store the token items in
var token_list = $("<ul />")
.addClass(settings.classes.tokenList)
.click(function (event) {
var li = $(event.target).closest("li");
if(li && li.get(0) && $.data(li.get(0), "tokeninput")) {
toggle_select_token(li);
} else {
// Deselect selected token
if(selected_token) {
deselect_token($(selected_token), POSITION.END);
}
// Focus input box
input_box.focus();
}
})
.mouseover(function (event) {
var li = $(event.target).closest("li");
if(li && selected_token !== this) {
li.addClass(settings.classes.highlightedToken);
}
})
.mouseout(function (event) {
var li = $(event.target).closest("li");
if(li && selected_token !== this) {
li.removeClass(settings.classes.highlightedToken);
}
})
.insertBefore(hidden_input);
// The token holding the input box
var input_token = $("<li />")
.addClass(settings.classes.inputToken)
.appendTo(token_list)
.append(input_box);
// The list to store the dropdown items in
var dropdown = $("<div>")
.addClass(settings.classes.dropdown)
.appendTo("body")
.hide();
// Magic element to help us resize the text input
var input_resizer = $("<tester/>")
.insertAfter(input_box)
.css({
position: "absolute",
top: -9999,
left: -9999,
width: "auto",
fontSize: input_box.css("fontSize"),
fontFamily: input_box.css("fontFamily"),
fontWeight: input_box.css("fontWeight"),
letterSpacing: input_box.css("letterSpacing"),
whiteSpace: "nowrap"
});
// Pre-populate list if items exist
hidden_input.val("");
var li_data = settings.prePopulate || hidden_input.data("pre");
if(settings.processPrePopulate && $.isFunction(settings.onResult)) {
li_data = settings.onResult.call(hidden_input, li_data);
}
if(li_data && li_data.length) {
$.each(li_data, function (index, value) {
insert_token(value);
checkTokenLimit();
});
}
// Initialization is done
if($.isFunction(settings.onReady)) {
settings.onReady.call();
}
//
// Public functions
//
this.clear = function() {
token_list.children("li").each(function() {
if ($(this).children("input").length === 0) {
delete_token($(this));
}
});
}
this.add = function(item) {
add_token(item);
}
this.remove = function(item) {
token_list.children("li").each(function() {
if ($(this).children("input").length === 0) {
var currToken = $(this).data("tokeninput");
var match = true;
for (var prop in item) {
if (item[prop] !== currToken[prop]) {
match = false;
break;
}
}
if (match) {
delete_token($(this));
}
}
});
}
this.getTokens = function() {
return saved_tokens;
}
//
// Private functions
//
function checkTokenLimit() {
if(settings.tokenLimit !== null && token_count >= settings.tokenLimit) {
input_box.hide();
hide_dropdown();
return;
}
}
function resize_input() {
if(input_val === (input_val = input_box.val())) {return;}
// Enter new content into resizer and resize input accordingly
var escaped = input_val.replace(/&/g, '&amp;').replace(/\s/g,' ').replace(/</g, '&lt;').replace(/>/g, '&gt;');
input_resizer.html(escaped);
input_box.width(input_resizer.width() + 30);
}
function is_printable_character(keycode) {
return ((keycode >= 48 && keycode <= 90) || // 0-1a-z
(keycode >= 96 && keycode <= 111) || // numpad 0-9 + - / * .
(keycode >= 186 && keycode <= 192) || // ; = , - . / ^
(keycode >= 219 && keycode <= 222)); // ( \ ) '
}
// Inner function to a token to the list
function insert_token(item) {
var this_token = settings.tokenFormatter(item);
this_token = $(this_token)
.addClass(settings.classes.token)
.insertBefore(input_token);
// The 'delete token' button
$("<span>" + settings.deleteText + "</span>")
.addClass(settings.classes.tokenDelete)
.appendTo(this_token)
.click(function () {
delete_token($(this).parent());
hidden_input.change();
return false;
});
// Store data on the token
var token_data = {"id": item.id};
token_data[settings.propertyToSearch] = item[settings.propertyToSearch];
$.data(this_token.get(0), "tokeninput", item);
// Save this token for duplicate checking
saved_tokens = saved_tokens.slice(0,selected_token_index).concat([token_data]).concat(saved_tokens.slice(selected_token_index));
selected_token_index++;
// Update the hidden input
update_hidden_input(saved_tokens, hidden_input);
token_count += 1;
// Check the token limit
if(settings.tokenLimit !== null && token_count >= settings.tokenLimit) {
input_box.hide();
hide_dropdown();
}
return this_token;
}
// Add a token to the token list based on user input
function add_token (item) {
var callback = settings.onAdd;
// See if the token already exists and select it if we don't want duplicates
if(token_count > 0 && settings.preventDuplicates) {
var found_existing_token = null;
token_list.children().each(function () {
var existing_token = $(this);
var existing_data = $.data(existing_token.get(0), "tokeninput");
if(existing_data && existing_data.id === item.id) {
found_existing_token = existing_token;
return false;
}
});
if(found_existing_token) {
select_token(found_existing_token);
input_token.insertAfter(found_existing_token);
//input_box.focus();
return;
}
}
// Insert the new tokens
if(settings.tokenLimit == null || token_count < settings.tokenLimit) {
insert_token(item);
checkTokenLimit();
}
// Clear input box
input_box.val("");
// Don't show the help dropdown, they've got the idea
hide_dropdown();
// Execute the onAdd callback if defined
if($.isFunction(callback)) {
callback.call(hidden_input,item);
}
}
// Select a token in the token list
function select_token (token) {
token.addClass(settings.classes.selectedToken);
selected_token = token.get(0);
// Hide input box
input_box.val("");
// Hide dropdown if it is visible (eg if we clicked to select token)
hide_dropdown();
}
// Deselect a token in the token list
function deselect_token (token, position) {
token.removeClass(settings.classes.selectedToken);
selected_token = null;
if(position === POSITION.BEFORE) {
input_token.insertBefore(token);
selected_token_index--;
} else if(position === POSITION.AFTER) {
input_token.insertAfter(token);
selected_token_index++;
} else {
input_token.appendTo(token_list);
selected_token_index = token_count;
}
// Show the input box and give it focus again
input_box.focus();
}
// Toggle selection of a token in the token list
function toggle_select_token(token) {
var previous_selected_token = selected_token;
if(selected_token) {
deselect_token($(selected_token), POSITION.END);
}
if(previous_selected_token === token.get(0)) {
deselect_token(token, POSITION.END);
} else {
select_token(token);
}
}
// Delete a token from the token list
function delete_token (token) {
// Remove the id from the saved list
var token_data = $.data(token.get(0), "tokeninput");
var callback = settings.onDelete;
var index = token.prevAll().length;
if(index > selected_token_index) index--;
// Delete the token
token.remove();
selected_token = null;
// Show the input box and give it focus again
input_box.focus();
// Remove this token from the saved list
saved_tokens = saved_tokens.slice(0,index).concat(saved_tokens.slice(index+1));
if(index < selected_token_index) selected_token_index--;
// Update the hidden input
update_hidden_input(saved_tokens, hidden_input);
token_count -= 1;
if(settings.tokenLimit !== null) {
input_box
.show()
.val("")
.focus();
}
// Execute the onDelete callback if defined
if($.isFunction(callback)) {
callback.call(hidden_input,token_data);
}
}
// Update the hidden input box value
function update_hidden_input(saved_tokens, hidden_input) {
var token_values = $.map(saved_tokens, function (el) {
return el[settings.tokenValue];
});
hidden_input.val(token_values.join(settings.tokenDelimiter));
}
// Hide and clear the results dropdown
function hide_dropdown () {
dropdown.hide().empty();
selected_dropdown_item = null;
}
function show_dropdown() {
dropdown
.css({
position: "absolute",
top: $(token_list).offset().top + $(token_list).outerHeight(),
left: $(token_list).offset().left,
zindex: 999
})
.show();
}
function show_dropdown_searching () {
if(settings.searchingText) {
dropdown.html("<p>"+settings.searchingText+"</p>");
show_dropdown();
}
}
function show_dropdown_hint () {
if(settings.hintText) {
dropdown.html("<p>"+settings.hintText+"</p>");
show_dropdown();
}
}
// Highlight the query part of the search term
function highlight_term(value, term) {
return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<b>$1</b>");
}
function find_value_and_highlight_term(template, value, term) {
return template.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + value + ")(?![^<>]*>)(?![^&;]+;)", "g"), highlight_term(value, term));
}
// Populate the results dropdown with some results
function populate_dropdown (query, results) {
if(results && results.length) {
dropdown.empty();
var dropdown_ul = $("<ul>")
.appendTo(dropdown)
.mouseover(function (event) {
select_dropdown_item($(event.target).closest("li"));
})
.mousedown(function (event) {
add_token($(event.target).closest("li").data("tokeninput"));
hidden_input.change();
return false;
})
.hide();
$.each(results, function(index, value) {
var this_li = settings.resultsFormatter(value);
this_li = find_value_and_highlight_term(this_li ,value[settings.propertyToSearch], query);
this_li = $(this_li).appendTo(dropdown_ul);
if(index % 2) {
this_li.addClass(settings.classes.dropdownItem);
} else {
this_li.addClass(settings.classes.dropdownItem2);
}
if(index === 0) {
select_dropdown_item(this_li);
}
$.data(this_li.get(0), "tokeninput", value);
});
show_dropdown();
if(settings.animateDropdown) {
dropdown_ul.slideDown("fast");
} else {
dropdown_ul.show();
}
} else {
if(settings.noResultsText) {
dropdown.html("<p>"+settings.noResultsText+"</p>");
show_dropdown();
}
}
}
// Highlight an item in the results dropdown
function select_dropdown_item (item) {
if(item) {
if(selected_dropdown_item) {
deselect_dropdown_item($(selected_dropdown_item));
}
item.addClass(settings.classes.selectedDropdownItem);
selected_dropdown_item = item.get(0);
}
}
// Remove highlighting from an item in the results dropdown
function deselect_dropdown_item (item) {
item.removeClass(settings.classes.selectedDropdownItem);
selected_dropdown_item = null;
}
// Do a search and show the "searching" dropdown if the input is longer
// than settings.minChars
function do_search() {
var query = input_box.val().toLowerCase();
if(query && query.length) {
if(selected_token) {
deselect_token($(selected_token), POSITION.AFTER);
}
if(query.length >= settings.minChars) {
show_dropdown_searching();
clearTimeout(timeout);
timeout = setTimeout(function(){
run_search(query);
}, settings.searchDelay);
} else {
hide_dropdown();
}
}
}
// Do the actual search
function run_search(query) {
var cache_key = query + computeURL();
var cached_results = cache.get(cache_key);
if(cached_results) {
populate_dropdown(query, cached_results);
} else {
// Are we doing an ajax search or local data search?
if(settings.url) {
var url = computeURL();
// Extract exisiting get params
var ajax_params = {};
ajax_params.data = {};
if(url.indexOf("?") > -1) {
var parts = url.split("?");
ajax_params.url = parts[0];
var param_array = parts[1].split("&");
$.each(param_array, function (index, value) {
var kv = value.split("=");
ajax_params.data[kv[0]] = kv[1];
});
} else {
ajax_params.url = url;
}
// Prepare the request
ajax_params.data[settings.queryParam] = query;
ajax_params.type = settings.method;
ajax_params.dataType = settings.contentType;
if(settings.crossDomain) {
ajax_params.dataType = "jsonp";
}
// Attach the success callback
ajax_params.success = function(results) {
if($.isFunction(settings.onResult)) {
results = settings.onResult.call(hidden_input, results);
}
cache.add(cache_key, settings.jsonContainer ? results[settings.jsonContainer] : results);
// only populate the dropdown if the results are associated with the active search query
if(input_box.val().toLowerCase() === query) {
populate_dropdown(query, settings.jsonContainer ? results[settings.jsonContainer] : results);
}
};
// Make the request
$.ajax(ajax_params);
} else if(settings.local_data) {
// Do the search through local data
var results = $.grep(settings.local_data, function (row) {
return row[settings.propertyToSearch].toLowerCase().indexOf(query.toLowerCase()) > -1;
});
if($.isFunction(settings.onResult)) {
results = settings.onResult.call(hidden_input, results);
}
cache.add(cache_key, results);
populate_dropdown(query, results);
}
}
}
// compute the dynamic URL
function computeURL() {
var url = settings.url;
if(typeof settings.url == 'function') {
url = settings.url.call();
}
return url;
}
};
// Really basic cache for the results
$.TokenList.Cache = function (options) {
var settings = $.extend({
max_size: 500
}, options);
var data = {};
var size = 0;
var flush = function () {
data = {};
size = 0;
};
this.add = function (query, results) {
if(size > settings.max_size) {
flush();
}
if(!data[query]) {
size += 1;
}
data[query] = results;
};
this.get = function (query) {
return data[query];
};
};
}(jQuery));

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,200 @@
/* Datepicker Validation 1.0.1 for jQuery UI Datepicker 1.8.6.
Requires Jörn Zaefferer's Validation plugin (http://plugins.jquery.com/project/validate).
Written by Keith Wood (kbwood{at}iinet.com.au).
Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
Please attribute the author if you use it. */
(function($) { // Hide the namespace
/* Add validation methods if validation plugin available. */
if ($.fn.validate) {
$.datepicker._selectDate2 = $.datepicker._selectDate;
$.extend($.datepicker.regional[''], {
validateDate: 'Please enter a valid date',
validateDateMin: 'Please enter a date on or after {0}',
validateDateMax: 'Please enter a date on or before {0}',
validateDateMinMax: 'Please enter a date between {0} and {1}',
validateDateCompare: 'Please enter a date {0} {1}',
validateDateToday: 'today',
validateDateOther: 'the other date',
validateDateEQ: 'equal to',
validateDateNE: 'not equal to',
validateDateLT: 'before',
validateDateGT: 'after',
validateDateLE: 'not after',
validateDateGE: 'not before'
});
$.extend($.datepicker._defaults, $.datepicker.regional['']);
$.extend($.datepicker, {
/* Trigger a validation after updating the input field with the selected date.
@param id (string) the ID of the target field
@param dateStr (string) the chosen date */
_selectDate: function(id, dateStr) {
this._selectDate2(id, dateStr);
var input = $(id);
var inst = this._getInst(input[0]);
if (!inst.inline && $.fn.validate)
input.parents('form').validate().element(input);
},
/* Correct error placement for validation errors - after (before if R-T-L) any trigger.
@param error (jQuery) the error message
@param element (jQuery) the field in error */
errorPlacement: function(error, element) {
var trigger = element.next('.' + $.datepicker._triggerClass);
var before = false;
if (trigger.length == 0) {
trigger = element.prev('.' + $.datepicker._triggerClass);
before = (trigger.length > 0);
}
error[before ? 'insertBefore' : 'insertAfter'](trigger.length > 0 ? trigger : element);
},
/* Format a validation error message involving dates.
@param message (string) the error message
@param params (Date[]) the dates
@return (string) the formatted message */
errorFormat: function(inst, message, params) {
var format = $.datepicker._get(inst, 'dateFormat');
$.each(params, function(i, v) {
message = message.replace(new RegExp('\\{' + i + '\\}', 'g'),
$.datepicker.formatDate(format, v) || 'nothing');
});
return message;
}
});
var lastElement = null;
/* Validate date field. */
$.validator.addMethod('dpDate', function(value, element, params) {
lastElement = element;
var inst = $.datepicker._getInst(element);
var dateFormat = $.datepicker._get(inst, 'dateFormat');
try {
var date = $.datepicker.parseDate(dateFormat, value, $.datepicker._getFormatConfig(inst));
var minDate = $.datepicker._determineDate(inst, $.datepicker._get(inst, 'minDate'), null);
var maxDate = $.datepicker._determineDate(inst, $.datepicker._get(inst, 'maxDate'), null);
var beforeShowDay = $.datepicker._get(inst, 'beforeShowDay');
return this.optional(element) || !date ||
((!minDate || date >= minDate) && (!maxDate || date <= maxDate) &&
(!beforeShowDay || beforeShowDay.apply(element, [date])[0]));
}
catch (e) {
return false;
}
}, function(params) {
var inst = $.datepicker._getInst(lastElement);
var minDate = $.datepicker._determineDate(inst, $.datepicker._get(inst, 'minDate'), null);
var maxDate = $.datepicker._determineDate(inst, $.datepicker._get(inst, 'maxDate'), null);
var messages = $.datepicker._defaults;
return (minDate && maxDate ?
$.datepicker.errorFormat(inst, messages.validateDateMinMax, [minDate, maxDate]) :
(minDate ? $.datepicker.errorFormat(inst, messages.validateDateMin, [minDate]) :
(maxDate ? $.datepicker.errorFormat(inst, messages.validateDateMax, [maxDate]) :
messages.validateDate)));
});
/* And allow as a class rule. */
$.validator.addClassRules('dpDate', {dpDate: true});
var comparisons = {equal: 'eq', same: 'eq', notEqual: 'ne', notSame: 'ne',
lessThan: 'lt', before: 'lt', greaterThan: 'gt', after: 'gt',
notLessThan: 'ge', notBefore: 'ge', notGreaterThan: 'le', notAfter: 'le'};
/* Cross-validate date fields.
params should be an array with [0] comparison type eq/ne/lt/gt/le/ge or synonyms,
[1] 'today' or date string or Date or other field selector/element/jQuery OR
an object with one attribute with name eq/ne/lt/gt/le/ge or synonyms
and value 'today' or date string or Date or other field selector/element/jQuery OR
a string with eq/ne/lt/gt/le/ge or synonyms followed by 'today' or date string or jQuery selector */
$.validator.addMethod('dpCompareDate', function(value, element, params) {
if (this.optional(element)) {
return true;
}
params = normaliseParams(params);
var thisDate = $(element).datepicker('getDate');
var thatDate = extractOtherDate(element, params[1]);
if (!thisDate || !thatDate) {
return true;
}
lastElement = element;
var result = true;
switch (comparisons[params[0]] || params[0]) {
case 'eq': result = (thisDate.getTime() == thatDate.getTime()); break;
case 'ne': result = (thisDate.getTime() != thatDate.getTime()); break;
case 'lt': result = (thisDate.getTime() < thatDate.getTime()); break;
case 'gt': result = (thisDate.getTime() > thatDate.getTime()); break;
case 'le': result = (thisDate.getTime() <= thatDate.getTime()); break;
case 'ge': result = (thisDate.getTime() >= thatDate.getTime()); break;
default: result = true;
}
return result;
},
function(params) {
var inst = $.datepicker._getInst(lastElement);
var messages = $.datepicker._defaults;
params = normaliseParams(params);
var thatDate = extractOtherDate(lastElement, params[1], true);
thatDate = (params[1] == 'today' ? messages.validateDateToday : (thatDate ?
$.datepicker.formatDate($.datepicker._get(inst, 'dateFormat'), thatDate,
$.datepicker._getFormatConfig(inst)) : messages.validateDateOther));
return messages.validateDateCompare.replace(/\{0\}/,
messages['validateDate' + (comparisons[params[0]] || params[0]).toUpperCase()]).
replace(/\{1\}/, thatDate);
});
/* Normalise the comparison parameters to an array.
@param params (array or object or string) the original parameters
@return (array) the normalised parameters */
function normaliseParams(params) {
if (typeof params == 'string') {
params = params.split(' ');
}
else if (!$.isArray(params)) {
var opts = [];
for (var name in params) {
opts[0] = name;
opts[1] = params[name];
}
params = opts;
}
return params;
}
/* Determine the comparison date.
@param element (element) the current datepicker element
@param source (string or Date or jQuery or element) the source of the other date
@param noOther (boolean) true to not get the date from another field
@return (Date) the date for comparison */
function extractOtherDate(element, source, noOther) {
if (source.constructor == Date) {
return source;
}
var inst = $.datepicker._getInst(element);
var thatDate = null;
try {
if (typeof source == 'string' && source != 'today') {
thatDate = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
source, $.datepicker._getFormatConfig(inst));
}
}
catch (e) {
// Ignore
}
thatDate = (thatDate ? thatDate : (source == 'today' ? new Date() :
(noOther ? null : $(source).datepicker('getDate'))));
if (thatDate) {
thatDate.setHours(0, 0, 0, 0);
}
return thatDate;
}
}
})(jQuery);

View file

@ -0,0 +1,7 @@
/* Datepicker Validation 1.0.1 for jQuery UI Datepicker 1.8.6.
Requires Jörn Zaefferer's Validation plugin (http://plugins.jquery.com/project/validate).
Written by Keith Wood (kbwood{at}iinet.com.au).
Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
Please attribute the author if you use it. */
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(5($){7($.U.B){$.2.V=$.2.W;$.C($.2.X[\'\'],{D:\'q r a 1m m\',Y:\'q r a m Z 10 t {0}\',11:\'q r a m Z 10 u {0}\',12:\'q r a m 1n {0} 1o {1}\',13:\'q r a m {0} {1}\',14:\'w\',15:\'1p 1q m\',1r:\'E 16\',1s:\'F E 16\',1t:\'u\',1u:\'t\',1v:\'F t\',1w:\'F u\'});$.C($.2.G,$.2.X[\'\']);$.C($.2,{W:5(a,b){x.V(a,b);3 c=$(a);3 d=x.s(c[0]);7(!d.1x&&$.U.B)c.1y(\'1z\').B().1A(c)},1B:5(a,b){3 c=b.1C(\'.\'+$.2.17);3 d=18;7(c.H==0){c=b.1D(\'.\'+$.2.17);d=(c.H>0)}a[d?\'1E\':\'1F\'](c.H>0?c:b)},y:5(a,b,c){3 d=$.2.8(a,\'z\');$.1G(c,5(i,v){b=b.I(19 1H(\'\\\\{\'+i+\'\\\\}\',\'g\'),$.2.1a(d,v)||\'1I\')});6 b}});3 k=9;$.J.1b(\'K\',5(a,b,c){k=b;3 d=$.2.s(b);3 f=$.2.8(d,\'z\');1c{3 g=$.2.1d(f,a,$.2.L(d));3 h=$.2.A(d,$.2.8(d,\'1e\'),9);3 i=$.2.A(d,$.2.8(d,\'1f\'),9);3 j=$.2.8(d,\'1J\');6 x.1g(b)||!g||((!h||g>=h)&&(!i||g<=i)&&(!j||j.1K(b,[g])[0]))}1h(e){6 18}},5(a){3 b=$.2.s(k);3 c=$.2.A(b,$.2.8(b,\'1e\'),9);3 d=$.2.A(b,$.2.8(b,\'1f\'),9);3 e=$.2.G;6(c&&d?$.2.y(b,e.12,[c,d]):(c?$.2.y(b,e.Y,[c]):(d?$.2.y(b,e.11,[d]):e.D)))});$.J.1L(\'K\',{K:n});3 l={E:\'M\',1M:\'M\',1N:\'N\',1O:\'N\',1P:\'O\',u:\'O\',1Q:\'P\',t:\'P\',1R:\'Q\',1S:\'Q\',1T:\'R\',1U:\'R\'};$.J.1b(\'1V\',5(a,b,c){7(x.1g(b)){6 n}c=S(c);3 d=$(b).2(\'1i\');3 e=T(b,c[1]);7(!d||!e){6 n}k=b;3 f=n;1W(l[c[0]]||c[0]){o\'M\':f=(d.4()==e.4());p;o\'N\':f=(d.4()!=e.4());p;o\'O\':f=(d.4()<e.4());p;o\'P\':f=(d.4()>e.4());p;o\'R\':f=(d.4()<=e.4());p;o\'Q\':f=(d.4()>=e.4());p;1X:f=n}6 f},5(a){3 b=$.2.s(k);3 c=$.2.G;a=S(a);3 d=T(k,a[1],n);d=(a[1]==\'w\'?c.14:(d?$.2.1a($.2.8(b,\'z\'),d,$.2.L(b)):c.15));6 c.13.I(/\\{0\\}/,c[\'D\'+(l[a[0]]||a[0]).1Y()]).I(/\\{1\\}/,d)});5 S(a){7(1j a==\'1k\'){a=a.1Z(\' \')}20 7(!$.21(a)){3 b=[];22(3 c 23 a){b[0]=c;b[1]=a[c]}a=b}6 a}5 T(a,b,c){7(b.24==1l){6 b}3 d=$.2.s(a);3 f=9;1c{7(1j b==\'1k\'&&b!=\'w\'){f=$.2.1d($.2.8(d,\'z\'),b,$.2.L(d))}}1h(e){}f=(f?f:(b==\'w\'?19 1l():(c?9:$(b).2(\'1i\'))));7(f){f.25(0,0,0,0)}6 f}}})(26);',62,131,'||datepicker|var|getTime|function|return|if|_get|null|||||||||||||date|true|case|break|Please|enter|_getInst|after|before||today|this|errorFormat|dateFormat|_determineDate|validate|extend|validateDate|equal|not|_defaults|length|replace|validator|dpDate|_getFormatConfig|eq|ne|lt|gt|ge|le|normaliseParams|extractOtherDate|fn|_selectDate2|_selectDate|regional|validateDateMin|on|or|validateDateMax|validateDateMinMax|validateDateCompare|validateDateToday|validateDateOther|to|_triggerClass|false|new|formatDate|addMethod|try|parseDate|minDate|maxDate|optional|catch|getDate|typeof|string|Date|valid|between|and|the|other|validateDateEQ|validateDateNE|validateDateLT|validateDateGT|validateDateLE|validateDateGE|inline|parents|form|element|errorPlacement|next|prev|insertBefore|insertAfter|each|RegExp|nothing|beforeShowDay|apply|addClassRules|same|notEqual|notSame|lessThan|greaterThan|notLessThan|notBefore|notGreaterThan|notAfter|dpCompareDate|switch|default|toUpperCase|split|else|isArray|for|in|constructor|setHours|jQuery'.split('|'),0,{}))

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

View file

@ -0,0 +1,77 @@
/*
* jsTree classic theme 1.0
* Supported features: dots/no-dots, icons/no-icons, focused, loading
* Supported plugins: ui (hovered, clicked), checkbox, contextmenu, search
*/
.jstree-classic li,
.jstree-classic ins { background-image:url("d.png"); background-repeat:no-repeat; background-color:transparent; }
.jstree-classic li { background-position:-90px 0; background-repeat:repeat-y; }
.jstree-classic li.jstree-last { background:transparent; }
.jstree-classic .jstree-open > ins { background-position:-72px 0; }
.jstree-classic .jstree-closed > ins { background-position:-54px 0; }
.jstree-classic .jstree-leaf > ins { background-position:-36px 0; }
.jstree-classic .jstree-hovered { background:#e7f4f9; border:1px solid #e7f4f9; padding:0 2px 0 1px; }
.jstree-classic .jstree-clicked { background:navy; border:1px solid navy; padding:0 2px 0 1px; color:white; }
.jstree-classic a .jstree-icon { background-position:-56px -19px; }
.jstree-classic .jstree-open > a .jstree-icon { background-position:-56px -36px; }
.jstree-classic a.jstree-loading .jstree-icon { background:url("throbber.gif") center center no-repeat !important; }
.jstree-classic.jstree-focused { background:white; }
.jstree-classic .jstree-no-dots li,
.jstree-classic .jstree-no-dots .jstree-leaf > ins { background:transparent; }
.jstree-classic .jstree-no-dots .jstree-open > ins { background-position:-18px 0; }
.jstree-classic .jstree-no-dots .jstree-closed > ins { background-position:0 0; }
.jstree-classic .jstree-no-icons a .jstree-icon { display:none; }
.jstree-classic .jstree-search { font-style:italic; }
.jstree-classic .jstree-no-icons .jstree-checkbox { display:inline-block; }
.jstree-classic .jstree-no-checkboxes .jstree-checkbox { display:none !important; }
.jstree-classic .jstree-checked > a > .jstree-checkbox { background-position:-38px -19px; }
.jstree-classic .jstree-unchecked > a > .jstree-checkbox { background-position:-2px -19px; }
.jstree-classic .jstree-undetermined > a > .jstree-checkbox { background-position:-20px -19px; }
.jstree-classic .jstree-checked > a > .jstree-checkbox:hover { background-position:-38px -37px; }
.jstree-classic .jstree-unchecked > a > .jstree-checkbox:hover { background-position:-2px -37px; }
.jstree-classic .jstree-undetermined > a > .jstree-checkbox:hover { background-position:-20px -37px; }
#vakata-dragged.jstree-classic ins { background:transparent !important; }
#vakata-dragged.jstree-classic .jstree-ok { background:url("d.png") -2px -53px no-repeat !important; }
#vakata-dragged.jstree-classic .jstree-invalid { background:url("d.png") -18px -53px no-repeat !important; }
#jstree-marker.jstree-classic { background:url("d.png") -41px -57px no-repeat !important; text-indent:-100px; }
.jstree-classic a.jstree-search { color:aqua; }
.jstree-classic .jstree-locked a { color:silver; cursor:default; }
#vakata-contextmenu.jstree-classic-context,
#vakata-contextmenu.jstree-classic-context li ul { background:#f0f0f0; border:1px solid #979797; -moz-box-shadow: 1px 1px 2px #999; -webkit-box-shadow: 1px 1px 2px #999; box-shadow: 1px 1px 2px #999; }
#vakata-contextmenu.jstree-classic-context li { }
#vakata-contextmenu.jstree-classic-context a { color:black; }
#vakata-contextmenu.jstree-classic-context a:hover,
#vakata-contextmenu.jstree-classic-context .vakata-hover > a { padding:0 5px; background:#e8eff7; border:1px solid #aecff7; color:black; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; }
#vakata-contextmenu.jstree-classic-context li.jstree-contextmenu-disabled a,
#vakata-contextmenu.jstree-classic-context li.jstree-contextmenu-disabled a:hover { color:silver; background:transparent; border:0; padding:1px 4px; }
#vakata-contextmenu.jstree-classic-context li.vakata-separator { background:white; border-top:1px solid #e0e0e0; margin:0; }
#vakata-contextmenu.jstree-classic-context li ul { margin-left:-4px; }
/* IE6 BEGIN */
.jstree-classic li,
.jstree-classic ins,
#vakata-dragged.jstree-classic .jstree-invalid,
#vakata-dragged.jstree-classic .jstree-ok,
#jstree-marker.jstree-classic { _background-image:url("d.gif"); }
.jstree-classic .jstree-open ins { _background-position:-72px 0; }
.jstree-classic .jstree-closed ins { _background-position:-54px 0; }
.jstree-classic .jstree-leaf ins { _background-position:-36px 0; }
.jstree-classic .jstree-open a ins.jstree-icon { _background-position:-56px -36px; }
.jstree-classic .jstree-closed a ins.jstree-icon { _background-position:-56px -19px; }
.jstree-classic .jstree-leaf a ins.jstree-icon { _background-position:-56px -19px; }
#vakata-contextmenu.jstree-classic-context ins { _display:none; }
#vakata-contextmenu.jstree-classic-context li { _zoom:1; }
.jstree-classic .jstree-undetermined a .jstree-checkbox { _background-position:-20px -19px; }
.jstree-classic .jstree-checked a .jstree-checkbox { _background-position:-38px -19px; }
.jstree-classic .jstree-unchecked a .jstree-checkbox { _background-position:-2px -19px; }
/* IE6 END */

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View file

@ -0,0 +1,74 @@
/*
* jsTree default theme 1.0
* Supported features: dots/no-dots, icons/no-icons, focused, loading
* Supported plugins: ui (hovered, clicked), checkbox, contextmenu, search
*/
.jstree-default li,
.jstree-default ins { background-image:url("d.png"); background-repeat:no-repeat; background-color:transparent; }
.jstree-default li { background-position:-90px 0; background-repeat:repeat-y; }
.jstree-default li.jstree-last { background:transparent; }
.jstree-default .jstree-open > ins { background-position:-72px 0; }
.jstree-default .jstree-closed > ins { background-position:-54px 0; }
.jstree-default .jstree-leaf > ins { background-position:-36px 0; }
.jstree-default .jstree-hovered { background:#e7f4f9; border:1px solid #d8f0fa; padding:0 2px 0 1px; }
.jstree-default .jstree-clicked { background:#beebff; border:1px solid #99defd; padding:0 2px 0 1px; }
.jstree-default a .jstree-icon { background-position:-56px -19px; }
.jstree-default a.jstree-loading .jstree-icon { background:url("throbber.gif") center center no-repeat !important; }
.jstree-default.jstree-focused { background:#ffffee; }
.jstree-default .jstree-no-dots li,
.jstree-default .jstree-no-dots .jstree-leaf > ins { background:transparent; }
.jstree-default .jstree-no-dots .jstree-open > ins { background-position:-18px 0; }
.jstree-default .jstree-no-dots .jstree-closed > ins { background-position:0 0; }
.jstree-default .jstree-no-icons a .jstree-icon { display:none; }
.jstree-default .jstree-search { font-style:italic; }
.jstree-default .jstree-no-icons .jstree-checkbox { display:inline-block; }
.jstree-default .jstree-no-checkboxes .jstree-checkbox { display:none !important; }
.jstree-default .jstree-checked > a > .jstree-checkbox { background-position:-38px -19px; }
.jstree-default .jstree-unchecked > a > .jstree-checkbox { background-position:-2px -19px; }
.jstree-default .jstree-undetermined > a > .jstree-checkbox { background-position:-20px -19px; }
.jstree-default .jstree-checked > a > .jstree-checkbox:hover { background-position:-38px -37px; }
.jstree-default .jstree-unchecked > a > .jstree-checkbox:hover { background-position:-2px -37px; }
.jstree-default .jstree-undetermined > a > .jstree-checkbox:hover { background-position:-20px -37px; }
#vakata-dragged.jstree-default ins { background:transparent !important; }
#vakata-dragged.jstree-default .jstree-ok { background:url("d.png") -2px -53px no-repeat !important; }
#vakata-dragged.jstree-default .jstree-invalid { background:url("d.png") -18px -53px no-repeat !important; }
#jstree-marker.jstree-default { background:url("d.png") -41px -57px no-repeat !important; text-indent:-100px; }
.jstree-default a.jstree-search { color:aqua; }
.jstree-default .jstree-locked a { color:silver; cursor:default; }
#vakata-contextmenu.jstree-default-context,
#vakata-contextmenu.jstree-default-context li ul { background:#f0f0f0; border:1px solid #979797; -moz-box-shadow: 1px 1px 2px #999; -webkit-box-shadow: 1px 1px 2px #999; box-shadow: 1px 1px 2px #999; }
#vakata-contextmenu.jstree-default-context li { }
#vakata-contextmenu.jstree-default-context a { color:black; }
#vakata-contextmenu.jstree-default-context a:hover,
#vakata-contextmenu.jstree-default-context .vakata-hover > a { padding:0 5px; background:#e8eff7; border:1px solid #aecff7; color:black; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; }
#vakata-contextmenu.jstree-default-context li.jstree-contextmenu-disabled a,
#vakata-contextmenu.jstree-default-context li.jstree-contextmenu-disabled a:hover { color:silver; background:transparent; border:0; padding:1px 4px; }
#vakata-contextmenu.jstree-default-context li.vakata-separator { background:white; border-top:1px solid #e0e0e0; margin:0; }
#vakata-contextmenu.jstree-default-context li ul { margin-left:-4px; }
/* IE6 BEGIN */
.jstree-default li,
.jstree-default ins,
#vakata-dragged.jstree-default .jstree-invalid,
#vakata-dragged.jstree-default .jstree-ok,
#jstree-marker.jstree-default { _background-image:url("d.gif"); }
.jstree-default .jstree-open ins { _background-position:-72px 0; }
.jstree-default .jstree-closed ins { _background-position:-54px 0; }
.jstree-default .jstree-leaf ins { _background-position:-36px 0; }
.jstree-default a ins.jstree-icon { _background-position:-56px -19px; }
#vakata-contextmenu.jstree-default-context ins { _display:none; }
#vakata-contextmenu.jstree-default-context li { _zoom:1; }
.jstree-default .jstree-undetermined a .jstree-checkbox { _background-position:-20px -19px; }
.jstree-default .jstree-checked a .jstree-checkbox { _background-position:-38px -19px; }
.jstree-default .jstree-unchecked a .jstree-checkbox { _background-position:-2px -19px; }
/* IE6 END */

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View file

@ -0,0 +1,44 @@
/* LOCKED */
.tree-default .locked li a { color:gray; }
/* DOTS */
.tree-default ul { background-position:6px 1px; background-repeat:repeat-y; background-image:url("dot.gif"); }
.tree-default li { background-position:7px 8px; background-repeat:no-repeat; background-image:url("li.gif"); }
.tree-default li.last { background-position:5px top; background-repeat:no-repeat; background-image:url("lastli.gif"); }
/* DOTS - RIGHT TO LEFT */
.tree-default .rtl, .tree-default .rtl ul { background-position:right 1px; }
.tree-default .rtl li { background-position:right 8px; }
.tree-default .rtl li.last { background-image:url("lastli_rtl.gif"); background-position:right top; }
/* NO DOTS */
.tree-default .no_dots, .tree-default .no_dots ul { background:transparent; }
.tree-default .no_dots li.leaf { background-image:none; background-color:transparent; }
/* OPEN or CLOSED */
.tree-default li.open { background:url("fminus.gif") 4px 6px no-repeat; }
.tree-default li.closed, #jstree-dragged.tree-default li li.open { background:url("fplus.gif") 5px 5px no-repeat; }
/* RIGHT TO LEFT */
.tree-default .rtl li { margin-right:1px; }
.tree-default .rtl li.last { margin-right:0; padding-right:16px; }
.tree-default .rtl li.open { background:url("fminus_rtl.gif") right 6px no-repeat; margin-right:0; padding-right:16px; }
.tree-default .rtl li.closed, #jstree-dragged.tree-default .rtl li li.open { background:url("fplus_rtl.gif") right 4px no-repeat; margin-right:0; padding-right:16px; }
/* DEFAULT, HOVER, CLICKED, LOADING STATES */
.tree-default li a, .tree-default li span { background-color:transparent; background-repeat:no-repeat; background-position:4px 1px; padding:1px 4px 1px 23px; background-image:url("f.png"); border-radius:3px; -moz-border-radius:3px; -webkit-border-radius:3px; }
.tree-default li a:hover, .tree-default li a.hover { background-color: #e7f4f9; border:1px solid #d8f0fa; padding:0px 3px 0px 22px; background-position:3px 0px; }
.tree-default li a.clicked, .tree-default li a.clicked:hover, .tree-default li span.clicked { background-color: #beebff; border:1px solid #99defd; padding:0px 3px 0px 22px; background-position:3px 0px; }
.tree-default li span.clicked { padding:0px 3px 0px 20px; }
.tree-default li a.loading { background-image:url("throbber.gif"); }
/* DEFAULT, HOVER, CLICKED, LOADING STATES - RIGHT TO LEFT */
.tree-default .rtl li a, .tree-default .rtl li span { padding:1px 23px 1px 4px; background-position:right 1px; margin-right:1px; }
.tree-default .rtl li a:hover, .tree-default .rtl li a.hover { padding:0px 23px 0px 3px; background-position:right 0px; margin-right:0px; }
.tree-default .rtl li a.clicked, .tree-default .rtl li a.clicked:hover, .tree-default .rtl li span.clicked { padding:0px 23px 0px 3px; background-position:right 0px; margin-right:0px; }
.tree-default .rtl li span.clicked { padding:0px 21px 0px 3px; }
/* CONTEXT MENU */
.tree-default-context { width:160px; background:#F0F0F0 url("context.gif") 22px 0 repeat-y; border:1px solid silver; position:absolute; }
.tree-default-context a, .tree-default-context a.disabled:hover { display:block; text-decoration:none; color:black; line-height:20px; background-repeat: no-repeat; background-position:2px center; padding:1px 0 1px 25px; background-color:transparent; border:1px solid #f0f0f0; border-width:0 1px; margin:0; }
.tree-default-context a:hover { background-color:#e7f4f9; border:1px solid #d8f0fa; padding:0 0 0 25px; margin:0; }
.tree-default-context a.disabled, .tree-default-context a.disabled:hover { color:silver; opacity:0.5; -ms-filter:'alpha(opacity=50)'; filter:alpha(opacity=50); zoom:1; }
.tree-default-context .separator { background:#FFFFFF;border-top:1px solid #E0E0E0;font-size:1px;height:1px;line-height:1px;margin:0 2px 0 24px;min-height:1px;display:block; }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B