mirror of https://github.com/sipwise/www_admin.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4546 lines
94 KiB
4546 lines
94 KiB
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 / Tooltip Slide Effect
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/tooltip/slide.html
|
|
*
|
|
* Since: September 2009
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
|
|
// version number
|
|
var t = $.tools.tooltip;
|
|
|
|
// extend global configuragion with effect specific defaults
|
|
$.extend(t.conf, {
|
|
direction: 'up', // down, left, right
|
|
bounce: false,
|
|
slideOffset: 10,
|
|
slideInSpeed: 200,
|
|
slideOutSpeed: 200,
|
|
slideFade: !$.browser.msie
|
|
});
|
|
|
|
// directions for slide effect
|
|
var dirs = {
|
|
up: ['-', 'top'],
|
|
down: ['+', 'top'],
|
|
left: ['-', 'left'],
|
|
right: ['+', 'left']
|
|
};
|
|
|
|
/* default effect: "slide" */
|
|
t.addEffect("slide",
|
|
|
|
// show effect
|
|
function(done) {
|
|
|
|
// variables
|
|
var conf = this.getConf(),
|
|
tip = this.getTip(),
|
|
params = conf.slideFade ? {opacity: conf.opacity} : {},
|
|
dir = dirs[conf.direction] || dirs.up;
|
|
|
|
// direction
|
|
params[dir[1]] = dir[0] +'='+ conf.slideOffset;
|
|
|
|
// perform animation
|
|
if (conf.slideFade) { tip.css({opacity:0}); }
|
|
tip.show().animate(params, conf.slideInSpeed, done);
|
|
},
|
|
|
|
// hide effect
|
|
function(done) {
|
|
|
|
// variables
|
|
var conf = this.getConf(),
|
|
offset = conf.slideOffset,
|
|
params = conf.slideFade ? {opacity: 0} : {},
|
|
dir = dirs[conf.direction] || dirs.up;
|
|
|
|
// direction
|
|
var sign = "" + dir[0];
|
|
if (conf.bounce) { sign = sign == '+' ? '-' : '+'; }
|
|
params[dir[1]] = sign +'='+ offset;
|
|
|
|
// perform animation
|
|
this.getTip().animate(params, conf.slideOutSpeed, function() {
|
|
$(this).hide();
|
|
done.call();
|
|
});
|
|
}
|
|
);
|
|
|
|
})(jQuery);
|
|
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 Tooltip - UI essentials
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/tooltip/
|
|
*
|
|
* Since: November 2008
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
// static constructs
|
|
$.tools = $.tools || {version: '1.2.5'};
|
|
|
|
$.tools.tooltip = {
|
|
|
|
conf: {
|
|
|
|
// default effect variables
|
|
effect: 'toggle',
|
|
fadeOutSpeed: "fast",
|
|
predelay: 0,
|
|
delay: 30,
|
|
opacity: 1,
|
|
tip: 0,
|
|
|
|
// 'top', 'bottom', 'right', 'left', 'center'
|
|
position: ['top', 'center'],
|
|
offset: [0, 0],
|
|
relative: false,
|
|
cancelDefault: true,
|
|
|
|
// type to event mapping
|
|
events: {
|
|
def: "mouseenter,mouseleave",
|
|
input: "focus,blur",
|
|
widget: "focus mouseenter,blur mouseleave",
|
|
tooltip: "mouseenter,mouseleave"
|
|
},
|
|
|
|
// 1.2
|
|
layout: '<div/>',
|
|
tipClass: 'tooltip'
|
|
},
|
|
|
|
addEffect: function(name, loadFn, hideFn) {
|
|
effects[name] = [loadFn, hideFn];
|
|
}
|
|
};
|
|
|
|
|
|
var effects = {
|
|
toggle: [
|
|
function(done) {
|
|
var conf = this.getConf(), tip = this.getTip(), o = conf.opacity;
|
|
if (o < 1) { tip.css({opacity: o}); }
|
|
tip.show();
|
|
done.call();
|
|
},
|
|
|
|
function(done) {
|
|
this.getTip().hide();
|
|
done.call();
|
|
}
|
|
],
|
|
|
|
fade: [
|
|
function(done) {
|
|
var conf = this.getConf();
|
|
this.getTip().fadeTo(conf.fadeInSpeed, conf.opacity, done);
|
|
},
|
|
function(done) {
|
|
this.getTip().fadeOut(this.getConf().fadeOutSpeed, done);
|
|
}
|
|
]
|
|
};
|
|
|
|
|
|
/* calculate tip position relative to the trigger */
|
|
function getPosition(trigger, tip, conf) {
|
|
|
|
|
|
// get origin top/left position
|
|
var top = conf.relative ? trigger.position().top : trigger.offset().top,
|
|
left = conf.relative ? trigger.position().left : trigger.offset().left,
|
|
pos = conf.position[0];
|
|
|
|
top -= tip.outerHeight() - conf.offset[0];
|
|
left += trigger.outerWidth() + conf.offset[1];
|
|
|
|
// iPad position fix
|
|
if (/iPad/i.test(navigator.userAgent)) {
|
|
top -= $(window).scrollTop();
|
|
}
|
|
|
|
// adjust Y
|
|
var height = tip.outerHeight() + trigger.outerHeight();
|
|
if (pos == 'center') { top += height / 2; }
|
|
if (pos == 'bottom') { top += height; }
|
|
|
|
|
|
// adjust X
|
|
pos = conf.position[1];
|
|
var width = tip.outerWidth() + trigger.outerWidth();
|
|
if (pos == 'center') { left -= width / 2; }
|
|
if (pos == 'left') { left -= width; }
|
|
|
|
return {top: top, left: left};
|
|
}
|
|
|
|
|
|
|
|
function Tooltip(trigger, conf) {
|
|
|
|
var self = this,
|
|
fire = trigger.add(self),
|
|
tip,
|
|
timer = 0,
|
|
pretimer = 0,
|
|
title = trigger.attr("title"),
|
|
tipAttr = trigger.attr("data-tooltip"),
|
|
effect = effects[conf.effect],
|
|
shown,
|
|
|
|
// get show/hide configuration
|
|
isInput = trigger.is(":input"),
|
|
isWidget = isInput && trigger.is(":checkbox, :radio, select, :button, :submit"),
|
|
type = trigger.attr("type"),
|
|
evt = conf.events[type] || conf.events[isInput ? (isWidget ? 'widget' : 'input') : 'def'];
|
|
|
|
|
|
// check that configuration is sane
|
|
if (!effect) { throw "Nonexistent effect \"" + conf.effect + "\""; }
|
|
|
|
evt = evt.split(/,\s*/);
|
|
if (evt.length != 2) { throw "Tooltip: bad events configuration for " + type; }
|
|
|
|
|
|
// trigger --> show
|
|
trigger.bind(evt[0], function(e) {
|
|
|
|
clearTimeout(timer);
|
|
if (conf.predelay) {
|
|
pretimer = setTimeout(function() { self.show(e); }, conf.predelay);
|
|
|
|
} else {
|
|
self.show(e);
|
|
}
|
|
|
|
// trigger --> hide
|
|
}).bind(evt[1], function(e) {
|
|
clearTimeout(pretimer);
|
|
if (conf.delay) {
|
|
timer = setTimeout(function() { self.hide(e); }, conf.delay);
|
|
|
|
} else {
|
|
self.hide(e);
|
|
}
|
|
|
|
});
|
|
|
|
|
|
// remove default title
|
|
if (title && conf.cancelDefault) {
|
|
trigger.removeAttr("title");
|
|
trigger.data("title", title);
|
|
}
|
|
|
|
$.extend(self, {
|
|
|
|
show: function(e) {
|
|
|
|
// tip not initialized yet
|
|
if (!tip) {
|
|
|
|
// data-tooltip
|
|
if (tipAttr) {
|
|
tip = $(tipAttr);
|
|
|
|
// single tip element for all
|
|
} else if (conf.tip) {
|
|
tip = $(conf.tip).eq(0);
|
|
|
|
// autogenerated tooltip
|
|
} else if (title) {
|
|
tip = $(conf.layout).addClass(conf.tipClass).appendTo(document.body)
|
|
.hide().append(title);
|
|
|
|
// manual tooltip
|
|
} else {
|
|
tip = trigger.next();
|
|
if (!tip.length) { tip = trigger.parent().next(); }
|
|
}
|
|
|
|
if (!tip.length) { throw "Cannot find tooltip for " + trigger; }
|
|
}
|
|
|
|
if (self.isShown()) { return self; }
|
|
|
|
// stop previous animation
|
|
tip.stop(true, true);
|
|
|
|
// get position
|
|
var pos = getPosition(trigger, tip, conf);
|
|
|
|
// restore title for single tooltip element
|
|
if (conf.tip) {
|
|
tip.html(trigger.data("title"));
|
|
}
|
|
|
|
// onBeforeShow
|
|
e = e || $.Event();
|
|
e.type = "onBeforeShow";
|
|
fire.trigger(e, [pos]);
|
|
if (e.isDefaultPrevented()) { return self; }
|
|
|
|
|
|
// onBeforeShow may have altered the configuration
|
|
pos = getPosition(trigger, tip, conf);
|
|
|
|
// set position
|
|
tip.css({position:'absolute', top: pos.top, left: pos.left});
|
|
|
|
shown = true;
|
|
|
|
// invoke effect
|
|
effect[0].call(self, function() {
|
|
e.type = "onShow";
|
|
shown = 'full';
|
|
fire.trigger(e);
|
|
});
|
|
|
|
|
|
// tooltip events
|
|
var event = conf.events.tooltip.split(/,\s*/);
|
|
|
|
if (!tip.data("__set")) {
|
|
|
|
tip.bind(event[0], function() {
|
|
clearTimeout(timer);
|
|
clearTimeout(pretimer);
|
|
});
|
|
|
|
if (event[1] && !trigger.is("input:not(:checkbox, :radio), textarea")) {
|
|
tip.bind(event[1], function(e) {
|
|
|
|
// being moved to the trigger element
|
|
if (e.relatedTarget != trigger[0]) {
|
|
trigger.trigger(evt[1].split(" ")[0]);
|
|
}
|
|
});
|
|
}
|
|
|
|
tip.data("__set", true);
|
|
}
|
|
|
|
return self;
|
|
},
|
|
|
|
hide: function(e) {
|
|
|
|
if (!tip || !self.isShown()) { return self; }
|
|
|
|
// onBeforeHide
|
|
e = e || $.Event();
|
|
e.type = "onBeforeHide";
|
|
fire.trigger(e);
|
|
if (e.isDefaultPrevented()) { return; }
|
|
|
|
shown = false;
|
|
|
|
effects[conf.effect][1].call(self, function() {
|
|
e.type = "onHide";
|
|
fire.trigger(e);
|
|
});
|
|
|
|
return self;
|
|
},
|
|
|
|
isShown: function(fully) {
|
|
return fully ? shown == 'full' : shown;
|
|
},
|
|
|
|
getConf: function() {
|
|
return conf;
|
|
},
|
|
|
|
getTip: function() {
|
|
return tip;
|
|
},
|
|
|
|
getTrigger: function() {
|
|
return trigger;
|
|
}
|
|
|
|
});
|
|
|
|
// callbacks
|
|
$.each("onHide,onBeforeShow,onShow,onBeforeHide".split(","), function(i, name) {
|
|
|
|
// configuration
|
|
if ($.isFunction(conf[name])) {
|
|
$(self).bind(name, conf[name]);
|
|
}
|
|
|
|
// API
|
|
self[name] = function(fn) {
|
|
if (fn) { $(self).bind(name, fn); }
|
|
return self;
|
|
};
|
|
});
|
|
|
|
}
|
|
|
|
|
|
// jQuery plugin implementation
|
|
$.fn.tooltip = function(conf) {
|
|
|
|
// return existing instance
|
|
var api = this.data("tooltip");
|
|
if (api) { return api; }
|
|
|
|
conf = $.extend(true, {}, $.tools.tooltip.conf, conf);
|
|
|
|
// position can also be given as string
|
|
if (typeof conf.position == 'string') {
|
|
conf.position = conf.position.split(/,?\s/);
|
|
}
|
|
|
|
// install tooltip for each entry in jQuery object
|
|
this.each(function() {
|
|
api = new Tooltip($(this), conf);
|
|
$(this).data("tooltip", api);
|
|
});
|
|
|
|
return conf.api ? api: this;
|
|
};
|
|
|
|
}) (jQuery);
|
|
|
|
|
|
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 / Tooltip Dynamic Positioning
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/tooltip/dynamic.html
|
|
*
|
|
* Since: July 2009
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
|
|
// version number
|
|
var t = $.tools.tooltip;
|
|
|
|
t.dynamic = {
|
|
conf: {
|
|
classNames: "top right bottom left"
|
|
}
|
|
};
|
|
|
|
/*
|
|
* See if element is on the viewport. Returns an boolean array specifying which
|
|
* edges are hidden. Edges are in following order:
|
|
*
|
|
* [top, right, bottom, left]
|
|
*
|
|
* For example following return value means that top and right edges are hidden
|
|
*
|
|
* [true, true, false, false]
|
|
*
|
|
*/
|
|
function getCropping(el) {
|
|
|
|
var w = $(window);
|
|
var right = w.width() + w.scrollLeft();
|
|
var bottom = w.height() + w.scrollTop();
|
|
|
|
return [
|
|
el.offset().top <= w.scrollTop(), // top
|
|
right <= el.offset().left + el.width(), // right
|
|
bottom <= el.offset().top + el.height(), // bottom
|
|
w.scrollLeft() >= el.offset().left // left
|
|
];
|
|
}
|
|
|
|
/*
|
|
Returns true if all edges of an element are on viewport. false if not
|
|
|
|
@param crop the cropping array returned by getCropping function
|
|
*/
|
|
function isVisible(crop) {
|
|
var i = crop.length;
|
|
while (i--) {
|
|
if (crop[i]) { return false; }
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// dynamic plugin
|
|
$.fn.dynamic = function(conf) {
|
|
|
|
if (typeof conf == 'number') { conf = {speed: conf}; }
|
|
|
|
conf = $.extend({}, t.dynamic.conf, conf);
|
|
|
|
var cls = conf.classNames.split(/\s/), orig;
|
|
|
|
this.each(function() {
|
|
|
|
var api = $(this).tooltip().onBeforeShow(function(e, pos) {
|
|
|
|
// get nessessary variables
|
|
var tip = this.getTip(), tipConf = this.getConf();
|
|
|
|
/*
|
|
We store the original configuration and use it to restore back to the original state.
|
|
*/
|
|
if (!orig) {
|
|
orig = [
|
|
tipConf.position[0],
|
|
tipConf.position[1],
|
|
tipConf.offset[0],
|
|
tipConf.offset[1],
|
|
$.extend({}, tipConf)
|
|
];
|
|
}
|
|
|
|
/*
|
|
display tip in it's default position and by setting visibility to hidden.
|
|
this way we can check whether it will be on the viewport
|
|
*/
|
|
$.extend(tipConf, orig[4]);
|
|
tipConf.position = [orig[0], orig[1]];
|
|
tipConf.offset = [orig[2], orig[3]];
|
|
|
|
tip.css({
|
|
visibility: 'hidden',
|
|
position: 'absolute',
|
|
top: pos.top,
|
|
left: pos.left
|
|
}).show();
|
|
|
|
// now let's see for hidden edges
|
|
var crop = getCropping(tip);
|
|
|
|
// possibly alter the configuration
|
|
if (!isVisible(crop)) {
|
|
|
|
// change the position and add class
|
|
if (crop[2]) { $.extend(tipConf, conf.top); tipConf.position[0] = 'top'; tip.addClass(cls[0]); }
|
|
if (crop[3]) { $.extend(tipConf, conf.right); tipConf.position[1] = 'right'; tip.addClass(cls[1]); }
|
|
if (crop[0]) { $.extend(tipConf, conf.bottom); tipConf.position[0] = 'bottom'; tip.addClass(cls[2]); }
|
|
if (crop[1]) { $.extend(tipConf, conf.left); tipConf.position[1] = 'left'; tip.addClass(cls[3]); }
|
|
|
|
// vertical offset
|
|
if (crop[0] || crop[2]) { tipConf.offset[0] *= -1; }
|
|
|
|
// horizontal offset
|
|
if (crop[1] || crop[3]) { tipConf.offset[1] *= -1; }
|
|
}
|
|
|
|
tip.css({visibility: 'visible'}).hide();
|
|
|
|
});
|
|
|
|
// restore positioning as soon as possible
|
|
api.onBeforeShow(function() {
|
|
var c = this.getConf(), tip = this.getTip();
|
|
setTimeout(function() {
|
|
c.position = [orig[0], orig[1]];
|
|
c.offset = [orig[2], orig[3]];
|
|
}, 0);
|
|
});
|
|
|
|
// remove custom class names and restore original effect
|
|
api.onHide(function() {
|
|
var tip = this.getTip();
|
|
tip.removeClass(conf.classNames);
|
|
});
|
|
|
|
ret = api;
|
|
|
|
});
|
|
|
|
return conf.api ? ret : this;
|
|
};
|
|
|
|
}) (jQuery);
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 Rangeinput - HTML5 <input type="range" /> for humans
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/rangeinput/
|
|
*
|
|
* Since: Mar 2010
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
|
|
$.tools = $.tools || {version: '1.2.5'};
|
|
|
|
var tool;
|
|
|
|
tool = $.tools.rangeinput = {
|
|
|
|
conf: {
|
|
min: 0,
|
|
max: 100, // as defined in the standard
|
|
step: 'any', // granularity of the value. a non-zero float or int (or "any")
|
|
steps: 0,
|
|
value: 0,
|
|
precision: undefined,
|
|
vertical: 0,
|
|
keyboard: true,
|
|
progress: false,
|
|
speed: 100,
|
|
|
|
// set to null if not needed
|
|
css: {
|
|
input: 'range',
|
|
slider: 'slider',
|
|
progress: 'progress',
|
|
handle: 'handle'
|
|
}
|
|
|
|
}
|
|
};
|
|
|
|
//{{{ fn.drag
|
|
|
|
/*
|
|
FULL featured drag and drop. 0.7 kb minified, 0.3 gzipped. done.
|
|
Who told d'n'd is rocket science? Usage:
|
|
|
|
$(".myelement").drag({y: false}).bind("drag", function(event, x, y) {
|
|
// do your custom thing
|
|
});
|
|
|
|
Configuration:
|
|
x: true, // enable horizontal drag
|
|
y: true, // enable vertical drag
|
|
drag: true // true = perform drag, false = only fire events
|
|
|
|
Events: dragStart, drag, dragEnd.
|
|
*/
|
|
var doc, draggable;
|
|
|
|
$.fn.drag = function(conf) {
|
|
|
|
// disable IE specialities
|
|
document.ondragstart = function () { return false; };
|
|
|
|
conf = $.extend({x: true, y: true, drag: true}, conf);
|
|
|
|
doc = doc || $(document).bind("mousedown mouseup", function(e) {
|
|
|
|
var el = $(e.target);
|
|
|
|
// start
|
|
if (e.type == "mousedown" && el.data("drag")) {
|
|
|
|
var offset = el.position(),
|
|
x0 = e.pageX - offset.left,
|
|
y0 = e.pageY - offset.top,
|
|
start = true;
|
|
|
|
doc.bind("mousemove.drag", function(e) {
|
|
var x = e.pageX -x0,
|
|
y = e.pageY -y0,
|
|
props = {};
|
|
|
|
if (conf.x) { props.left = x; }
|
|
if (conf.y) { props.top = y; }
|
|
|
|
if (start) {
|
|
el.trigger("dragStart");
|
|
start = false;
|
|
}
|
|
if (conf.drag) { el.css(props); }
|
|
el.trigger("drag", [y, x]);
|
|
draggable = el;
|
|
});
|
|
|
|
e.preventDefault();
|
|
|
|
} else {
|
|
|
|
try {
|
|
if (draggable) {
|
|
draggable.trigger("dragEnd");
|
|
}
|
|
} finally {
|
|
doc.unbind("mousemove.drag");
|
|
draggable = null;
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
return this.data("drag", true);
|
|
};
|
|
|
|
//}}}
|
|
|
|
|
|
|
|
function round(value, precision) {
|
|
var n = Math.pow(10, precision);
|
|
return Math.round(value * n) / n;
|
|
}
|
|
|
|
// get hidden element's width or height even though it's hidden
|
|
function dim(el, key) {
|
|
var v = parseInt(el.css(key), 10);
|
|
if (v) { return v; }
|
|
var s = el[0].currentStyle;
|
|
return s && s.width && parseInt(s.width, 10);
|
|
}
|
|
|
|
function hasEvent(el) {
|
|
var e = el.data("events");
|
|
return e && e.onSlide;
|
|
}
|
|
|
|
function RangeInput(input, conf) {
|
|
|
|
// private variables
|
|
var self = this,
|
|
css = conf.css,
|
|
root = $("<div><div/><a href='#'/></div>").data("rangeinput", self),
|
|
vertical,
|
|
value, // current value
|
|
origo, // handle's start point
|
|
len, // length of the range
|
|
pos; // current position of the handle
|
|
|
|
// create range
|
|
input.before(root);
|
|
|
|
var handle = root.addClass(css.slider).find("a").addClass(css.handle),
|
|
progress = root.find("div").addClass(css.progress);
|
|
|
|
// get (HTML5) attributes into configuration
|
|
$.each("min,max,step,value".split(","), function(i, key) {
|
|
var val = input.attr(key);
|
|
if (parseFloat(val)) {
|
|
conf[key] = parseFloat(val, 10);
|
|
}
|
|
});
|
|
|
|
var range = conf.max - conf.min,
|
|
step = conf.step == 'any' ? 0 : conf.step,
|
|
precision = conf.precision;
|
|
|
|
if (precision === undefined) {
|
|
try {
|
|
precision = step.toString().split(".")[1].length;
|
|
} catch (err) {
|
|
precision = 0;
|
|
}
|
|
}
|
|
|
|
// Replace built-in range input (type attribute cannot be changed)
|
|
if (input.attr("type") == 'range') {
|
|
var tmp = $("<input/>");
|
|
$.each("class,disabled,id,maxlength,name,readonly,required,size,style,tabindex,title,value".split(","), function(i, attr) {
|
|
tmp.attr(attr, input.attr(attr));
|
|
});
|
|
tmp.val(conf.value);
|
|
input.replaceWith(tmp);
|
|
input = tmp;
|
|
}
|
|
|
|
input.addClass(css.input);
|
|
|
|
var fire = $(self).add(input), fireOnSlide = true;
|
|
|
|
|
|
/**
|
|
The flesh and bone of this tool. All sliding is routed trough this.
|
|
|
|
@param evt types include: click, keydown, blur and api (setValue call)
|
|
@param isSetValue when called trough setValue() call (keydown, blur, api)
|
|
|
|
vertical configuration gives additional complexity.
|
|
*/
|
|
function slide(evt, x, val, isSetValue) {
|
|
|
|
// calculate value based on slide position
|
|
if (val === undefined) {
|
|
val = x / len * range;
|
|
|
|
// x is calculated based on val. we need to strip off min during calculation
|
|
} else if (isSetValue) {
|
|
val -= conf.min;
|
|
}
|
|
|
|
// increment in steps
|
|
if (step) {
|
|
val = Math.round(val / step) * step;
|
|
}
|
|
|
|
// count x based on value or tweak x if stepping is done
|
|
if (x === undefined || step) {
|
|
x = val * len / range;
|
|
}
|
|
|
|
// crazy value?
|
|
if (isNaN(val)) { return self; }
|
|
|
|
// stay within range
|
|
x = Math.max(0, Math.min(x, len));
|
|
val = x / len * range;
|
|
|
|
if (isSetValue || !vertical) {
|
|
val += conf.min;
|
|
}
|
|
|
|
// in vertical ranges value rises upwards
|
|
if (vertical) {
|
|
if (isSetValue) {
|
|
x = len -x;
|
|
} else {
|
|
val = conf.max - val;
|
|
}
|
|
}
|
|
|
|
// precision
|
|
val = round(val, precision);
|
|
|
|
// onSlide
|
|
var isClick = evt.type == "click";
|
|
if (fireOnSlide && value !== undefined && !isClick) {
|
|
evt.type = "onSlide";
|
|
fire.trigger(evt, [val, x]);
|
|
if (evt.isDefaultPrevented()) { return self; }
|
|
}
|
|
|
|
// speed & callback
|
|
var speed = isClick ? conf.speed : 0,
|
|
callback = isClick ? function() {
|
|
evt.type = "change";
|
|
fire.trigger(evt, [val]);
|
|
} : null;
|
|
|
|
if (vertical) {
|
|
handle.animate({top: x}, speed, callback);
|
|
if (conf.progress) {
|
|
progress.animate({height: len - x + handle.width() / 2}, speed);
|
|
}
|
|
|
|
} else {
|
|
handle.animate({left: x}, speed, callback);
|
|
if (conf.progress) {
|
|
progress.animate({width: x + handle.width() / 2}, speed);
|
|
}
|
|
}
|
|
|
|
// store current value
|
|
value = val;
|
|
pos = x;
|
|
|
|
// se input field's value
|
|
input.val(val);
|
|
|
|
return self;
|
|
}
|
|
|
|
|
|
$.extend(self, {
|
|
|
|
getValue: function() {
|
|
return value;
|
|
},
|
|
|
|
setValue: function(val, e) {
|
|
init();
|
|
return slide(e || $.Event("api"), undefined, val, true);
|
|
},
|
|
|
|
getConf: function() {
|
|
return conf;
|
|
},
|
|
|
|
getProgress: function() {
|
|
return progress;
|
|
},
|
|
|
|
getHandle: function() {
|
|
return handle;
|
|
},
|
|
|
|
getInput: function() {
|
|
return input;
|
|
},
|
|
|
|
step: function(am, e) {
|
|
e = e || $.Event();
|
|
var step = conf.step == 'any' ? 1 : conf.step;
|
|
self.setValue(value + step * (am || 1), e);
|
|
},
|
|
|
|
// HTML5 compatible name
|
|
stepUp: function(am) {
|
|
return self.step(am || 1);
|
|
},
|
|
|
|
// HTML5 compatible name
|
|
stepDown: function(am) {
|
|
return self.step(-am || -1);
|
|
}
|
|
|
|
});
|
|
|
|
// callbacks
|
|
$.each("onSlide,change".split(","), function(i, name) {
|
|
|
|
// from configuration
|
|
if ($.isFunction(conf[name])) {
|
|
$(self).bind(name, conf[name]);
|
|
}
|
|
|
|
// API methods
|
|
self[name] = function(fn) {
|
|
if (fn) { $(self).bind(name, fn); }
|
|
return self;
|
|
};
|
|
});
|
|
|
|
|
|
// dragging
|
|
handle.drag({drag: false}).bind("dragStart", function() {
|
|
|
|
/* do some pre- calculations for seek() function. improves performance */
|
|
init();
|
|
|
|
// avoid redundant event triggering (= heavy stuff)
|
|
fireOnSlide = hasEvent($(self)) || hasEvent(input);
|
|
|
|
|
|
}).bind("drag", function(e, y, x) {
|
|
|
|
if (input.is(":disabled")) { return false; }
|
|
slide(e, vertical ? y : x);
|
|
|
|
}).bind("dragEnd", function(e) {
|
|
if (!e.isDefaultPrevented()) {
|
|
e.type = "change";
|
|
fire.trigger(e, [value]);
|
|
}
|
|
|
|
}).click(function(e) {
|
|
return e.preventDefault();
|
|
});
|
|
|
|
// clicking
|
|
root.click(function(e) {
|
|
if (input.is(":disabled") || e.target == handle[0]) {
|
|
return e.preventDefault();
|
|
}
|
|
init();
|
|
var fix = handle.width() / 2;
|
|
slide(e, vertical ? len-origo-fix + e.pageY : e.pageX -origo -fix);
|
|
});
|
|
|
|
if (conf.keyboard) {
|
|
|
|
input.keydown(function(e) {
|
|
|
|
if (input.attr("readonly")) { return; }
|
|
|
|
var key = e.keyCode,
|
|
up = $([75, 76, 38, 33, 39]).index(key) != -1,
|
|
down = $([74, 72, 40, 34, 37]).index(key) != -1;
|
|
|
|
if ((up || down) && !(e.shiftKey || e.altKey || e.ctrlKey)) {
|
|
|
|
// UP: k=75, l=76, up=38, pageup=33, right=39
|
|
if (up) {
|
|
self.step(key == 33 ? 10 : 1, e);
|
|
|
|
// DOWN: j=74, h=72, down=40, pagedown=34, left=37
|
|
} else if (down) {
|
|
self.step(key == 34 ? -10 : -1, e);
|
|
}
|
|
return e.preventDefault();
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
input.blur(function(e) {
|
|
var val = $(this).val();
|
|
if (val !== value) {
|
|
self.setValue(val, e);
|
|
}
|
|
});
|
|
|
|
|
|
// HTML5 DOM methods
|
|
$.extend(input[0], { stepUp: self.stepUp, stepDown: self.stepDown});
|
|
|
|
|
|
// calculate all dimension related stuff
|
|
function init() {
|
|
vertical = conf.vertical || dim(root, "height") > dim(root, "width");
|
|
|
|
if (vertical) {
|
|
len = dim(root, "height") - dim(handle, "height");
|
|
origo = root.offset().top + len;
|
|
|
|
} else {
|
|
len = dim(root, "width") - dim(handle, "width");
|
|
origo = root.offset().left;
|
|
}
|
|
}
|
|
|
|
function begin() {
|
|
init();
|
|
self.setValue(conf.value !== undefined ? conf.value : conf.min);
|
|
}
|
|
begin();
|
|
|
|
// some browsers cannot get dimensions upon initialization
|
|
if (!len) {
|
|
$(window).load(begin);
|
|
}
|
|
}
|
|
|
|
$.expr[':'].range = function(el) {
|
|
var type = el.getAttribute("type");
|
|
return type && type == 'range' || !!$(el).filter("input").data("rangeinput");
|
|
};
|
|
|
|
|
|
// jQuery plugin implementation
|
|
$.fn.rangeinput = function(conf) {
|
|
|
|
// already installed
|
|
if (this.data("rangeinput")) { return this; }
|
|
|
|
// extend configuration with globals
|
|
conf = $.extend(true, {}, tool.conf, conf);
|
|
|
|
var els;
|
|
|
|
this.each(function() {
|
|
var el = new RangeInput($(this), $.extend(true, {}, conf));
|
|
var input = el.getInput().data("rangeinput", el);
|
|
els = els ? els.add(input) : input;
|
|
});
|
|
|
|
return els ? els : this;
|
|
};
|
|
|
|
|
|
}) (jQuery);
|
|
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 History "Back button for AJAX apps"
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/toolbox/history.html
|
|
*
|
|
* Since: Mar 2010
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
|
|
var hash, iframe, links, inited;
|
|
|
|
$.tools = $.tools || {version: '1.2.5'};
|
|
|
|
$.tools.history = {
|
|
|
|
init: function(els) {
|
|
|
|
if (inited) { return; }
|
|
|
|
// IE
|
|
if ($.browser.msie && $.browser.version < '8') {
|
|
|
|
// create iframe that is constantly checked for hash changes
|
|
if (!iframe) {
|
|
iframe = $("<iframe/>").attr("src", "javascript:false;").hide().get(0);
|
|
$("body").append(iframe);
|
|
|
|
setInterval(function() {
|
|
var idoc = iframe.contentWindow.document,
|
|
h = idoc.location.hash;
|
|
|
|
if (hash !== h) {
|
|
$.event.trigger("hash", h);
|
|
}
|
|
}, 100);
|
|
|
|
setIframeLocation(location.hash || '#');
|
|
}
|
|
|
|
|
|
// other browsers scans for location.hash changes directly without iframe hack
|
|
} else {
|
|
setInterval(function() {
|
|
var h = location.hash;
|
|
if (h !== hash) {
|
|
$.event.trigger("hash", h);
|
|
}
|
|
}, 100);
|
|
}
|
|
|
|
links = !links ? els : links.add(els);
|
|
|
|
els.click(function(e) {
|
|
var href = $(this).attr("href");
|
|
if (iframe) { setIframeLocation(href); }
|
|
|
|
// handle non-anchor links
|
|
if (href.slice(0, 1) != "#") {
|
|
location.href = "#" + href;
|
|
return e.preventDefault();
|
|
}
|
|
|
|
});
|
|
|
|
inited = true;
|
|
}
|
|
};
|
|
|
|
|
|
function setIframeLocation(h) {
|
|
if (h) {
|
|
var doc = iframe.contentWindow.document;
|
|
doc.open().close();
|
|
doc.location.hash = h;
|
|
}
|
|
}
|
|
|
|
// global histroy change listener
|
|
$(window).bind("hash", function(e, h) {
|
|
if (h) {
|
|
links.filter(function() {
|
|
var href = $(this).attr("href");
|
|
return href == h || href == h.replace("#", "");
|
|
}).trigger("history", [h]);
|
|
} else {
|
|
links.eq(0).trigger("history", [h]);
|
|
}
|
|
|
|
hash = h;
|
|
|
|
});
|
|
|
|
|
|
// jQuery plugin implementation
|
|
$.fn.history = function(fn) {
|
|
|
|
$.tools.history.init(this);
|
|
|
|
// return jQuery
|
|
return this.bind("history", fn);
|
|
};
|
|
|
|
})(jQuery);
|
|
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 Mousewheel
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/toolbox/mousewheel.html
|
|
*
|
|
* based on jquery.event.wheel.js ~ rev 1 ~
|
|
* Copyright (c) 2008, Three Dub Media
|
|
* http://threedubmedia.com
|
|
*
|
|
* Since: Mar 2010
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
|
|
$.fn.mousewheel = function( fn ){
|
|
return this[ fn ? "bind" : "trigger" ]( "wheel", fn );
|
|
};
|
|
|
|
// special event config
|
|
$.event.special.wheel = {
|
|
setup: function() {
|
|
$.event.add( this, wheelEvents, wheelHandler, {} );
|
|
},
|
|
teardown: function(){
|
|
$.event.remove( this, wheelEvents, wheelHandler );
|
|
}
|
|
};
|
|
|
|
// events to bind ( browser sniffed... )
|
|
var wheelEvents = !$.browser.mozilla ? "mousewheel" : // IE, opera, safari
|
|
"DOMMouseScroll"+( $.browser.version<"1.9" ? " mousemove" : "" ); // firefox
|
|
|
|
// shared event handler
|
|
function wheelHandler( event ) {
|
|
|
|
switch ( event.type ) {
|
|
|
|
// FF2 has incorrect event positions
|
|
case "mousemove":
|
|
return $.extend( event.data, { // store the correct properties
|
|
clientX: event.clientX, clientY: event.clientY,
|
|
pageX: event.pageX, pageY: event.pageY
|
|
});
|
|
|
|
// firefox
|
|
case "DOMMouseScroll":
|
|
$.extend( event, event.data ); // fix event properties in FF2
|
|
event.delta = -event.detail / 3; // normalize delta
|
|
break;
|
|
|
|
// IE, opera, safari
|
|
case "mousewheel":
|
|
event.delta = event.wheelDelta / 120;
|
|
break;
|
|
}
|
|
|
|
event.type = "wheel"; // hijack the event
|
|
return $.event.handle.call( this, event, event.delta );
|
|
}
|
|
|
|
})(jQuery);
|
|
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 / Flashembed - New wave Flash embedding
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/toolbox/flashembed.html
|
|
*
|
|
* Since : March 2008
|
|
* Date : Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function() {
|
|
|
|
var IE = document.all,
|
|
URL = 'http://www.adobe.com/go/getflashplayer',
|
|
JQUERY = typeof jQuery == 'function',
|
|
RE = /(\d+)[^\d]+(\d+)[^\d]*(\d*)/,
|
|
GLOBAL_OPTS = {
|
|
// very common opts
|
|
width: '100%',
|
|
height: '100%',
|
|
id: "_" + ("" + Math.random()).slice(9),
|
|
|
|
// flashembed defaults
|
|
allowfullscreen: true,
|
|
allowscriptaccess: 'always',
|
|
quality: 'high',
|
|
|
|
// flashembed specific options
|
|
version: [3, 0],
|
|
onFail: null,
|
|
expressInstall: null,
|
|
w3c: false,
|
|
cachebusting: false
|
|
};
|
|
|
|
// version 9 bugfix: (http://blog.deconcept.com/2006/07/28/swfobject-143-released/)
|
|
if (window.attachEvent) {
|
|
window.attachEvent("onbeforeunload", function() {
|
|
__flash_unloadHandler = function() {};
|
|
__flash_savedUnloadHandler = function() {};
|
|
});
|
|
}
|
|
|
|
// simple extend
|
|
function extend(to, from) {
|
|
if (from) {
|
|
for (var key in from) {
|
|
if (from.hasOwnProperty(key)) {
|
|
to[key] = from[key];
|
|
}
|
|
}
|
|
}
|
|
return to;
|
|
}
|
|
|
|
// used by asString method
|
|
function map(arr, func) {
|
|
var newArr = [];
|
|
for (var i in arr) {
|
|
if (arr.hasOwnProperty(i)) {
|
|
newArr[i] = func(arr[i]);
|
|
}
|
|
}
|
|
return newArr;
|
|
}
|
|
|
|
window.flashembed = function(root, opts, conf) {
|
|
|
|
// root must be found / loaded
|
|
if (typeof root == 'string') {
|
|
root = document.getElementById(root.replace("#", ""));
|
|
}
|
|
|
|
// not found
|
|
if (!root) { return; }
|
|
|
|
if (typeof opts == 'string') {
|
|
opts = {src: opts};
|
|
}
|
|
|
|
return new Flash(root, extend(extend({}, GLOBAL_OPTS), opts), conf);
|
|
};
|
|
|
|
// flashembed "static" API
|
|
var f = extend(window.flashembed, {
|
|
|
|
conf: GLOBAL_OPTS,
|
|
|
|
getVersion: function() {
|
|
var fo, ver;
|
|
|
|
try {
|
|
ver = navigator.plugins["Shockwave Flash"].description.slice(16);
|
|
} catch(e) {
|
|
|
|
try {
|
|
fo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
|
|
ver = fo && fo.GetVariable("$version");
|
|
|
|
} catch(err) {
|
|
try {
|
|
fo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
|
|
ver = fo && fo.GetVariable("$version");
|
|
} catch(err2) { }
|
|
}
|
|
}
|
|
|
|
ver = RE.exec(ver);
|
|
return ver ? [ver[1], ver[3]] : [0, 0];
|
|
},
|
|
|
|
asString: function(obj) {
|
|
|
|
if (obj === null || obj === undefined) { return null; }
|
|
var type = typeof obj;
|
|
if (type == 'object' && obj.push) { type = 'array'; }
|
|
|
|
switch (type){
|
|
|
|
case 'string':
|
|
obj = obj.replace(new RegExp('(["\\\\])', 'g'), '\\$1');
|
|
|
|
// flash does not handle %- characters well. transforms "50%" to "50pct" (a dirty hack, I admit)
|
|
obj = obj.replace(/^\s?(\d+\.?\d+)%/, "$1pct");
|
|
return '"' +obj+ '"';
|
|
|
|
case 'array':
|
|
return '['+ map(obj, function(el) {
|
|
return f.asString(el);
|
|
}).join(',') +']';
|
|
|
|
case 'function':
|
|
return '"function()"';
|
|
|
|
case 'object':
|
|
var str = [];
|
|
for (var prop in obj) {
|
|
if (obj.hasOwnProperty(prop)) {
|
|
str.push('"'+prop+'":'+ f.asString(obj[prop]));
|
|
}
|
|
}
|
|
return '{'+str.join(',')+'}';
|
|
}
|
|
|
|
// replace ' --> " and remove spaces
|
|
return String(obj).replace(/\s/g, " ").replace(/\'/g, "\"");
|
|
},
|
|
|
|
getHTML: function(opts, conf) {
|
|
|
|
opts = extend({}, opts);
|
|
|
|
/******* OBJECT tag and it's attributes *******/
|
|
var html = '<object width="' + opts.width +
|
|
'" height="' + opts.height +
|
|
'" id="' + opts.id +
|
|
'" name="' + opts.id + '"';
|
|
|
|
if (opts.cachebusting) {
|
|
opts.src += ((opts.src.indexOf("?") != -1 ? "&" : "?") + Math.random());
|
|
}
|
|
|
|
if (opts.w3c || !IE) {
|
|
html += ' data="' +opts.src+ '" type="application/x-shockwave-flash"';
|
|
} else {
|
|
html += ' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';
|
|
}
|
|
|
|
html += '>';
|
|
|
|
/******* nested PARAM tags *******/
|
|
if (opts.w3c || IE) {
|
|
html += '<param name="movie" value="' +opts.src+ '" />';
|
|
}
|
|
|
|
// not allowed params
|
|
opts.width = opts.height = opts.id = opts.w3c = opts.src = null;
|
|
opts.onFail = opts.version = opts.expressInstall = null;
|
|
|
|
for (var key in opts) {
|
|
if (opts[key]) {
|
|
html += '<param name="'+ key +'" value="'+ opts[key] +'" />';
|
|
}
|
|
}
|
|
|
|
/******* FLASHVARS *******/
|
|
var vars = "";
|
|
|
|
if (conf) {
|
|
for (var k in conf) {
|
|
if (conf[k]) {
|
|
var val = conf[k];
|
|
vars += k +'='+ (/function|object/.test(typeof val) ? f.asString(val) : val) + '&';
|
|
}
|
|
}
|
|
vars = vars.slice(0, -1);
|
|
html += '<param name="flashvars" value=\'' + vars + '\' />';
|
|
}
|
|
|
|
html += "</object>";
|
|
|
|
return html;
|
|
},
|
|
|
|
isSupported: function(ver) {
|
|
return VERSION[0] > ver[0] || VERSION[0] == ver[0] && VERSION[1] >= ver[1];
|
|
}
|
|
|
|
});
|
|
|
|
var VERSION = f.getVersion();
|
|
|
|
function Flash(root, opts, conf) {
|
|
|
|
// version is ok
|
|
if (f.isSupported(opts.version)) {
|
|
root.innerHTML = f.getHTML(opts, conf);
|
|
|
|
// express install
|
|
} else if (opts.expressInstall && f.isSupported([6, 65])) {
|
|
root.innerHTML = f.getHTML(extend(opts, {src: opts.expressInstall}), {
|
|
MMredirectURL: location.href,
|
|
MMplayerType: 'PlugIn',
|
|
MMdoctitle: document.title
|
|
});
|
|
|
|
} else {
|
|
|
|
// fail #2.1 custom content inside container
|
|
if (!root.innerHTML.replace(/\s/g, '')) {
|
|
root.innerHTML =
|
|
"<h2>Flash version " + opts.version + " or greater is required</h2>" +
|
|
"<h3>" +
|
|
(VERSION[0] > 0 ? "Your version is " + VERSION : "You have no flash plugin installed") +
|
|
"</h3>" +
|
|
|
|
(root.tagName == 'A' ? "<p>Click here to download latest version</p>" :
|
|
"<p>Download latest version from <a href='" + URL + "'>here</a></p>");
|
|
|
|
if (root.tagName == 'A') {
|
|
root.onclick = function() {
|
|
location.href = URL;
|
|
};
|
|
}
|
|
}
|
|
|
|
// onFail
|
|
if (opts.onFail) {
|
|
var ret = opts.onFail.call(this);
|
|
if (typeof ret == 'string') { root.innerHTML = ret; }
|
|
}
|
|
}
|
|
|
|
// http://flowplayer.org/forum/8/18186#post-18593
|
|
if (IE) {
|
|
window[opts.id] = document.getElementById(opts.id);
|
|
}
|
|
|
|
// API methods for callback
|
|
extend(this, {
|
|
|
|
getRoot: function() {
|
|
return root;
|
|
},
|
|
|
|
getOptions: function() {
|
|
return opts;
|
|
},
|
|
|
|
|
|
getConf: function() {
|
|
return conf;
|
|
},
|
|
|
|
getApi: function() {
|
|
return root.firstChild;
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
// setup jquery support
|
|
if (JQUERY) {
|
|
|
|
// tools version number
|
|
jQuery.tools = jQuery.tools || {version: '1.2.5'};
|
|
|
|
jQuery.tools.flashembed = {
|
|
conf: GLOBAL_OPTS
|
|
};
|
|
|
|
jQuery.fn.flashembed = function(opts, conf) {
|
|
return this.each(function() {
|
|
$(this).data("flashembed", flashembed(this, opts, conf));
|
|
});
|
|
};
|
|
}
|
|
|
|
})();
|
|
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 / Expose - Dim the lights
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/toolbox/expose.html
|
|
*
|
|
* Since: Mar 2010
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
|
|
// static constructs
|
|
$.tools = $.tools || {version: '1.2.5'};
|
|
|
|
var tool;
|
|
|
|
tool = $.tools.expose = {
|
|
|
|
conf: {
|
|
maskId: 'exposeMask',
|
|
loadSpeed: 'slow',
|
|
closeSpeed: 'fast',
|
|
closeOnClick: true,
|
|
closeOnEsc: true,
|
|
|
|
// css settings
|
|
zIndex: 9998,
|
|
opacity: 0.8,
|
|
startOpacity: 0,
|
|
color: '#fff',
|
|
|
|
// callbacks
|
|
onLoad: null,
|
|
onClose: null
|
|
}
|
|
};
|
|
|
|
/* one of the greatest headaches in the tool. finally made it */
|
|
function viewport() {
|
|
|
|
// the horror case
|
|
if ($.browser.msie) {
|
|
|
|
// if there are no scrollbars then use window.height
|
|
var d = $(document).height(), w = $(window).height();
|
|
|
|
return [
|
|
window.innerWidth || // ie7+
|
|
document.documentElement.clientWidth || // ie6
|
|
document.body.clientWidth, // ie6 quirks mode
|
|
d - w < 20 ? w : d
|
|
];
|
|
}
|
|
|
|
// other well behaving browsers
|
|
return [$(document).width(), $(document).height()];
|
|
}
|
|
|
|
function call(fn) {
|
|
if (fn) { return fn.call($.mask); }
|
|
}
|
|
|
|
var mask, exposed, loaded, config, overlayIndex;
|
|
|
|
|
|
$.mask = {
|
|
|
|
load: function(conf, els) {
|
|
|
|
// already loaded ?
|
|
if (loaded) { return this; }
|
|
|
|
// configuration
|
|
if (typeof conf == 'string') {
|
|
conf = {color: conf};
|
|
}
|
|
|
|
// use latest config
|
|
conf = conf || config;
|
|
|
|
config = conf = $.extend($.extend({}, tool.conf), conf);
|
|
|
|
// get the mask
|
|
mask = $("#" + conf.maskId);
|
|
|
|
// or create it
|
|
if (!mask.length) {
|
|
mask = $('<div/>').attr("id", conf.maskId);
|
|
$("body").append(mask);
|
|
}
|
|
|
|
// set position and dimensions
|
|
var size = viewport();
|
|
|
|
mask.css({
|
|
position:'absolute',
|
|
top: 0,
|
|
left: 0,
|
|
width: size[0],
|
|
height: size[1],
|
|
display: 'none',
|
|
opacity: conf.startOpacity,
|
|
zIndex: conf.zIndex
|
|
});
|
|
|
|
if (conf.color) {
|
|
mask.css("backgroundColor", conf.color);
|
|
}
|
|
|
|
// onBeforeLoad
|
|
if (call(conf.onBeforeLoad) === false) {
|
|
return this;
|
|
}
|
|
|
|
// esc button
|
|
if (conf.closeOnEsc) {
|
|
$(document).bind("keydown.mask", function(e) {
|
|
if (e.keyCode == 27) {
|
|
$.mask.close(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
// mask click closes
|
|
if (conf.closeOnClick) {
|
|
mask.bind("click.mask", function(e) {
|
|
$.mask.close(e);
|
|
});
|
|
}
|
|
|
|
// resize mask when window is resized
|
|
$(window).bind("resize.mask", function() {
|
|
$.mask.fit();
|
|
});
|
|
|
|
// exposed elements
|
|
if (els && els.length) {
|
|
|
|
overlayIndex = els.eq(0).css("zIndex");
|
|
|
|
// make sure element is positioned absolutely or relatively
|
|
$.each(els, function() {
|
|
var el = $(this);
|
|
if (!/relative|absolute|fixed/i.test(el.css("position"))) {
|
|
el.css("position", "relative");
|
|
}
|
|
});
|
|
|
|
// make elements sit on top of the mask
|
|
exposed = els.css({ zIndex: Math.max(conf.zIndex + 1, overlayIndex == 'auto' ? 0 : overlayIndex)});
|
|
}
|
|
|
|
// reveal mask
|
|
mask.css({display: 'block'}).fadeTo(conf.loadSpeed, conf.opacity, function() {
|
|
$.mask.fit();
|
|
call(conf.onLoad);
|
|
loaded = "full";
|
|
});
|
|
|
|
loaded = true;
|
|
return this;
|
|
},
|
|
|
|
close: function() {
|
|
if (loaded) {
|
|
|
|
// onBeforeClose
|
|
if (call(config.onBeforeClose) === false) { return this; }
|
|
|
|
mask.fadeOut(config.closeSpeed, function() {
|
|
call(config.onClose);
|
|
if (exposed) {
|
|
exposed.css({zIndex: overlayIndex});
|
|
}
|
|
loaded = false;
|
|
});
|
|
|
|
// unbind various event listeners
|
|
$(document).unbind("keydown.mask");
|
|
mask.unbind("click.mask");
|
|
$(window).unbind("resize.mask");
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
fit: function() {
|
|
if (loaded) {
|
|
var size = viewport();
|
|
mask.css({width: size[0], height: size[1]});
|
|
}
|
|
},
|
|
|
|
getMask: function() {
|
|
return mask;
|
|
},
|
|
|
|
isLoaded: function(fully) {
|
|
return fully ? loaded == 'full' : loaded;
|
|
},
|
|
|
|
getConf: function() {
|
|
return config;
|
|
},
|
|
|
|
getExposed: function() {
|
|
return exposed;
|
|
}
|
|
};
|
|
|
|
$.fn.mask = function(conf) {
|
|
$.mask.load(conf);
|
|
return this;
|
|
};
|
|
|
|
$.fn.expose = function(conf) {
|
|
$.mask.load(conf, this);
|
|
return this;
|
|
};
|
|
|
|
|
|
})(jQuery);
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 Dateinput - <input type="date" /> for humans
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/form/dateinput/
|
|
*
|
|
* Since: Mar 2010
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
|
|
/* TODO:
|
|
preserve today highlighted
|
|
*/
|
|
|
|
$.tools = $.tools || {version: '1.2.5'};
|
|
|
|
var instances = [],
|
|
tool,
|
|
|
|
// h=72, j=74, k=75, l=76, down=40, left=37, up=38, right=39
|
|
KEYS = [75, 76, 38, 39, 74, 72, 40, 37],
|
|
LABELS = {};
|
|
|
|
tool = $.tools.dateinput = {
|
|
|
|
conf: {
|
|
format: 'mm/dd/yy',
|
|
selectors: false,
|
|
yearRange: [-5, 5],
|
|
lang: 'en',
|
|
offset: [0, 0],
|
|
speed: 0,
|
|
firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
|
|
min: undefined,
|
|
max: undefined,
|
|
trigger: false,
|
|
|
|
css: {
|
|
|
|
prefix: 'cal',
|
|
input: 'date',
|
|
|
|
// ids
|
|
root: 0,
|
|
head: 0,
|
|
title: 0,
|
|
prev: 0,
|
|
next: 0,
|
|
month: 0,
|
|
year: 0,
|
|
days: 0,
|
|
|
|
body: 0,
|
|
weeks: 0,
|
|
today: 0,
|
|
current: 0,
|
|
|
|
// classnames
|
|
week: 0,
|
|
off: 0,
|
|
sunday: 0,
|
|
focus: 0,
|
|
disabled: 0,
|
|
trigger: 0
|
|
}
|
|
},
|
|
|
|
localize: function(language, labels) {
|
|
$.each(labels, function(key, val) {
|
|
labels[key] = val.split(",");
|
|
});
|
|
LABELS[language] = labels;
|
|
}
|
|
|
|
};
|
|
|
|
tool.localize("en", {
|
|
months: 'January,February,March,April,May,June,July,August,September,October,November,December',
|
|
shortMonths: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec',
|
|
days: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday',
|
|
shortDays: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'
|
|
});
|
|
|
|
|
|
//{{{ private functions
|
|
|
|
|
|
// @return amount of days in certain month
|
|
function dayAm(year, month) {
|
|
return 32 - new Date(year, month, 32).getDate();
|
|
}
|
|
|
|
function zeropad(val, len) {
|
|
val = '' + val;
|
|
len = len || 2;
|
|
while (val.length < len) { val = "0" + val; }
|
|
return val;
|
|
}
|
|
|
|
// thanks: http://stevenlevithan.com/assets/misc/date.format.js
|
|
var Re = /d{1,4}|m{1,4}|yy(?:yy)?|"[^"]*"|'[^']*'/g, tmpTag = $("<a/>");
|
|
|
|
function format(date, fmt, lang) {
|
|
|
|
var d = date.getDate(),
|
|
D = date.getDay(),
|
|
m = date.getMonth(),
|
|
y = date.getFullYear(),
|
|
|
|
flags = {
|
|
d: d,
|
|
dd: zeropad(d),
|
|
ddd: LABELS[lang].shortDays[D],
|
|
dddd: LABELS[lang].days[D],
|
|
m: m + 1,
|
|
mm: zeropad(m + 1),
|
|
mmm: LABELS[lang].shortMonths[m],
|
|
mmmm: LABELS[lang].months[m],
|
|
yy: String(y).slice(2),
|
|
yyyy: y
|
|
};
|
|
|
|
var ret = fmt.replace(Re, function ($0) {
|
|
return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
|
|
});
|
|
|
|
// a small trick to handle special characters
|
|
return tmpTag.html(ret).html();
|
|
|
|
}
|
|
|
|
function integer(val) {
|
|
return parseInt(val, 10);
|
|
}
|
|
|
|
function isSameDay(d1, d2) {
|
|
return d1.getFullYear() === d2.getFullYear() &&
|
|
d1.getMonth() == d2.getMonth() &&
|
|
d1.getDate() == d2.getDate();
|
|
}
|
|
|
|
function parseDate(val) {
|
|
|
|
if (!val) { return; }
|
|
if (val.constructor == Date) { return val; }
|
|
|
|
if (typeof val == 'string') {
|
|
|
|
// rfc3339?
|
|
var els = val.split("-");
|
|
if (els.length == 3) {
|
|
return new Date(integer(els[0]), integer(els[1]) -1, integer(els[2]));
|
|
}
|
|
|
|
// invalid offset
|
|
if (!/^-?\d+$/.test(val)) { return; }
|
|
|
|
// convert to integer
|
|
val = integer(val);
|
|
}
|
|
|
|
var date = new Date();
|
|
date.setDate(date.getDate() + val);
|
|
return date;
|
|
}
|
|
|
|
//}}}
|
|
|
|
|
|
function Dateinput(input, conf) {
|
|
|
|
// variables
|
|
var self = this,
|
|
now = new Date(),
|
|
css = conf.css,
|
|
labels = LABELS[conf.lang],
|
|
root = $("#" + css.root),
|
|
title = root.find("#" + css.title),
|
|
trigger,
|
|
pm, nm,
|
|
currYear, currMonth, currDay,
|
|
value = input.attr("data-value") || conf.value || input.val(),
|
|
min = input.attr("min") || conf.min,
|
|
max = input.attr("max") || conf.max,
|
|
opened;
|
|
|
|
// zero min is not undefined
|
|
if (min === 0) { min = "0"; }
|
|
|
|
// use sane values for value, min & max
|
|
value = parseDate(value) || now;
|
|
min = parseDate(min || conf.yearRange[0] * 365);
|
|
max = parseDate(max || conf.yearRange[1] * 365);
|
|
|
|
|
|
// check that language exists
|
|
if (!labels) { throw "Dateinput: invalid language: " + conf.lang; }
|
|
|
|
// Replace built-in date input: NOTE: input.attr("type", "text") throws exception by the browser
|
|
if (input.attr("type") == 'date') {
|
|
var tmp = $("<input/>");
|
|
|
|
$.each("class,disabled,id,maxlength,name,readonly,required,size,style,tabindex,title,value".split(","), function(i, attr) {
|
|
tmp.attr(attr, input.attr(attr));
|
|
});
|
|
input.replaceWith(tmp);
|
|
input = tmp;
|
|
}
|
|
input.addClass(css.input);
|
|
|
|
var fire = input.add(self);
|
|
|
|
// construct layout
|
|
if (!root.length) {
|
|
|
|
// root
|
|
root = $('<div><div><a/><div/><a/></div><div><div/><div/></div></div>')
|
|
.hide().css({position: 'absolute'}).attr("id", css.root);
|
|
|
|
// elements
|
|
root.children()
|
|
.eq(0).attr("id", css.head).end()
|
|
.eq(1).attr("id", css.body).children()
|
|
.eq(0).attr("id", css.days).end()
|
|
.eq(1).attr("id", css.weeks).end().end().end()
|
|
.find("a").eq(0).attr("id", css.prev).end().eq(1).attr("id", css.next);
|
|
|
|
// title
|
|
title = root.find("#" + css.head).find("div").attr("id", css.title);
|
|
|
|
// year & month selectors
|
|
if (conf.selectors) {
|
|
var monthSelector = $("<select/>").attr("id", css.month),
|
|
yearSelector = $("<select/>").attr("id", css.year);
|
|
title.html(monthSelector.add(yearSelector));
|
|
}
|
|
|
|
// day titles
|
|
var days = root.find("#" + css.days);
|
|
|
|
// days of the week
|
|
for (var d = 0; d < 7; d++) {
|
|
days.append($("<span/>").text(labels.shortDays[(d + conf.firstDay) % 7]));
|
|
}
|
|
|
|
$("body").append(root);
|
|
}
|
|
|
|
|
|
// trigger icon
|
|
if (conf.trigger) {
|
|
trigger = $("<a/>").attr("href", "#").addClass(css.trigger).click(function(e) {
|
|
self.show();
|
|
return e.preventDefault();
|
|
}).insertAfter(input);
|
|
}
|
|
|
|
|
|
// layout elements
|
|
var weeks = root.find("#" + css.weeks);
|
|
yearSelector = root.find("#" + css.year);
|
|
monthSelector = root.find("#" + css.month);
|
|
|
|
|
|
//{{{ pick
|
|
|
|
function select(date, conf, e) {
|
|
|
|
// current value
|
|
value = date;
|
|
currYear = date.getFullYear();
|
|
currMonth = date.getMonth();
|
|
currDay = date.getDate();
|
|
|
|
|
|
// change
|
|
e = e || $.Event("api");
|
|
e.type = "change";
|
|
|
|
fire.trigger(e, [date]);
|
|
if (e.isDefaultPrevented()) { return; }
|
|
|
|
// formatting
|
|
input.val(format(date, conf.format, conf.lang));
|
|
|
|
// store value into input
|
|
input.data("date", date);
|
|
|
|
self.hide(e);
|
|
}
|
|
//}}}
|
|
|
|
|
|
//{{{ onShow
|
|
|
|
function onShow(ev) {
|
|
|
|
ev.type = "onShow";
|
|
fire.trigger(ev);
|
|
|
|
$(document).bind("keydown.d", function(e) {
|
|
|
|
if (e.ctrlKey) { return true; }
|
|
var key = e.keyCode;
|
|
|
|
// backspace clears the value
|
|
if (key == 8) {
|
|
input.val("");
|
|
return self.hide(e);
|
|
}
|
|
|
|
// esc key
|
|
if (key == 27) { return self.hide(e); }
|
|
|
|
if ($(KEYS).index(key) >= 0) {
|
|
|
|
if (!opened) {
|
|
self.show(e);
|
|
return e.preventDefault();
|
|
}
|
|
|
|
var days = $("#" + css.weeks + " a"),
|
|
el = $("." + css.focus),
|
|
index = days.index(el);
|
|
|
|
el.removeClass(css.focus);
|
|
|
|
if (key == 74 || key == 40) { index += 7; }
|
|
else if (key == 75 || key == 38) { index -= 7; }
|
|
else if (key == 76 || key == 39) { index += 1; }
|
|
else if (key == 72 || key == 37) { index -= 1; }
|
|
|
|
|
|
if (index > 41) {
|
|
self.addMonth();
|
|
el = $("#" + css.weeks + " a:eq(" + (index-42) + ")");
|
|
} else if (index < 0) {
|
|
self.addMonth(-1);
|
|
el = $("#" + css.weeks + " a:eq(" + (index+42) + ")");
|
|
} else {
|
|
el = days.eq(index);
|
|
}
|
|
|
|
el.addClass(css.focus);
|
|
return e.preventDefault();
|
|
|
|
}
|
|
|
|
// pageUp / pageDown
|
|
if (key == 34) { return self.addMonth(); }
|
|
if (key == 33) { return self.addMonth(-1); }
|
|
|
|
// home
|
|
if (key == 36) { return self.today(); }
|
|
|
|
// enter
|
|
if (key == 13) {
|
|
if (!$(e.target).is("select")) {
|
|
$("." + css.focus).click();
|
|
}
|
|
}
|
|
|
|
return $([16, 17, 18, 9]).index(key) >= 0;
|
|
});
|
|
|
|
|
|
// click outside dateinput
|
|
$(document).bind("click.d", function(e) {
|
|
var el = e.target;
|
|
|
|
if (!$(el).parents("#" + css.root).length && el != input[0] && (!trigger || el != trigger[0])) {
|
|
self.hide(e);
|
|
}
|
|
|
|
});
|
|
}
|
|
//}}}
|
|
|
|
|
|
$.extend(self, {
|
|
|
|
//{{{ show
|
|
|
|
show: function(e) {
|
|
|
|
if (input.attr("readonly") || input.attr("disabled") || opened) { return; }
|
|
|
|
// onBeforeShow
|
|
e = e || $.Event();
|
|
e.type = "onBeforeShow";
|
|
fire.trigger(e);
|
|
if (e.isDefaultPrevented()) { return; }
|
|
|
|
$.each(instances, function() {
|
|
this.hide();
|
|
});
|
|
|
|
opened = true;
|
|
|
|
// month selector
|
|
monthSelector.unbind("change").change(function() {
|
|
self.setValue(yearSelector.val(), $(this).val());
|
|
});
|
|
|
|
// year selector
|
|
yearSelector.unbind("change").change(function() {
|
|
self.setValue($(this).val(), monthSelector.val());
|
|
});
|
|
|
|
// prev / next month
|
|
pm = root.find("#" + css.prev).unbind("click").click(function(e) {
|
|
if (!pm.hasClass(css.disabled)) {
|
|
self.addMonth(-1);
|
|
}
|
|
return false;
|
|
});
|
|
|
|
nm = root.find("#" + css.next).unbind("click").click(function(e) {
|
|
if (!nm.hasClass(css.disabled)) {
|
|
self.addMonth();
|
|
}
|
|
return false;
|
|
});
|
|
|
|
// set date
|
|
self.setValue(value);
|
|
|
|
// show calendar
|
|
var pos = input.offset();
|
|
|
|
// iPad position fix
|
|
if (/iPad/i.test(navigator.userAgent)) {
|
|
pos.top -= $(window).scrollTop();
|
|
}
|
|
|
|
root.css({
|
|
top: pos.top + input.outerHeight({margins: true}) + conf.offset[0],
|
|
left: pos.left + conf.offset[1]
|
|
});
|
|
|
|
if (conf.speed) {
|
|
root.show(conf.speed, function() {
|
|
onShow(e);
|
|
});
|
|
} else {
|
|
root.show();
|
|
onShow(e);
|
|
}
|
|
|
|
return self;
|
|
},
|
|
//}}}
|
|
|
|
|
|
//{{{ setValue
|
|
|
|
setValue: function(year, month, day) {
|
|
|
|
var date = integer(month) >= -1 ?
|
|
new Date(integer(year), integer(month), integer(day || 1)) : year || value
|
|
;
|
|
|
|
if (date < min) { date = min; }
|
|
else if (date > max) { date = max; }
|
|
|
|
year = date.getFullYear();
|
|
month = date.getMonth();
|
|
day = date.getDate();
|
|
|
|
|
|
// roll year & month
|
|
if (month == -1) {
|
|
month = 11;
|
|
year--;
|
|
} else if (month == 12) {
|
|
month = 0;
|
|
year++;
|
|
}
|
|
|
|
if (!opened) {
|
|
select(date, conf);
|
|
return self;
|
|
}
|
|
|
|
currMonth = month;
|
|
currYear = year;
|
|
|
|
// variables
|
|
var tmp = new Date(year, month, 1 - conf.firstDay), begin = tmp.getDay(),
|
|
days = dayAm(year, month),
|
|
prevDays = dayAm(year, month - 1),
|
|
week;
|
|
|
|
// selectors
|
|
if (conf.selectors) {
|
|
|
|
// month selector
|
|
monthSelector.empty();
|
|
$.each(labels.months, function(i, m) {
|
|
if (min < new Date(year, i + 1, -1) && max > new Date(year, i, 0)) {
|
|
monthSelector.append($("<option/>").html(m).attr("value", i));
|
|
}
|
|
});
|
|
|
|
// year selector
|
|
yearSelector.empty();
|
|
var yearNow = now.getFullYear();
|
|
|
|
for (var i = yearNow + conf.yearRange[0]; i < yearNow + conf.yearRange[1]; i++) {
|
|
if (min <= new Date(i + 1, -1, 1) && max > new Date(i, 0, 0)) {
|
|
yearSelector.append($("<option/>").text(i));
|
|
}
|
|
}
|
|
|
|
monthSelector.val(month);
|
|
yearSelector.val(year);
|
|
|
|
// title
|
|
} else {
|
|
title.html(labels.months[month] + " " + year);
|
|
}
|
|
|
|
// populate weeks
|
|
weeks.empty();
|
|
pm.add(nm).removeClass(css.disabled);
|
|
|
|
// !begin === "sunday"
|
|
for (var j = !begin ? -7 : 0, a, num; j < (!begin ? 35 : 42); j++) {
|
|
|
|
a = $("<a/>");
|
|
|
|
if (j % 7 === 0) {
|
|
week = $("<div/>").addClass(css.week);
|
|
weeks.append(week);
|
|
}
|
|
|
|
if (j < begin) {
|
|
a.addClass(css.off);
|
|
num = prevDays - begin + j + 1;
|
|
date = new Date(year, month-1, num);
|
|
|
|
} else if (j >= begin + days) {
|
|
a.addClass(css.off);
|
|
num = j - days - begin + 1;
|
|
date = new Date(year, month+1, num);
|
|
|
|
} else {
|
|
num = j - begin + 1;
|
|
date = new Date(year, month, num);
|
|
|
|
// current date
|
|
if (isSameDay(value, date)) {
|
|
a.attr("id", css.current).addClass(css.focus);
|
|
|
|
// today
|
|
} else if (isSameDay(now, date)) {
|
|
a.attr("id", css.today);
|
|
}
|
|
}
|
|
|
|
// disabled
|
|
if (min && date < min) {
|
|
a.add(pm).addClass(css.disabled);
|
|
}
|
|
|
|
if (max && date > max) {
|
|
a.add(nm).addClass(css.disabled);
|
|
}
|
|
|
|
a.attr("href", "#" + num).text(num).data("date", date);
|
|
|
|
week.append(a);
|
|
}
|
|
|
|
// date picking
|
|
weeks.find("a").click(function(e) {
|
|
var el = $(this);
|
|
if (!el.hasClass(css.disabled)) {
|
|
$("#" + css.current).removeAttr("id");
|
|
el.attr("id", css.current);
|
|
select(el.data("date"), conf, e);
|
|
}
|
|
return false;
|
|
});
|
|
|
|
// sunday
|
|
if (css.sunday) {
|
|
weeks.find(css.week).each(function() {
|
|
var beg = conf.firstDay ? 7 - conf.firstDay : 0;
|
|
$(this).children().slice(beg, beg + 1).addClass(css.sunday);
|
|
});
|
|
}
|
|
|
|
return self;
|
|
},
|
|
//}}}
|
|
|
|
setMin: function(val, fit) {
|
|
min = parseDate(val);
|
|
if (fit && value < min) { self.setValue(min); }
|
|
return self;
|
|
},
|
|
|
|
setMax: function(val, fit) {
|
|
max = parseDate(val);
|
|
if (fit && value > max) { self.setValue(max); }
|
|
return self;
|
|
},
|
|
|
|
today: function() {
|
|
return self.setValue(now);
|
|
},
|
|
|
|
addDay: function(amount) {
|
|
return this.setValue(currYear, currMonth, currDay + (amount || 1));
|
|
},
|
|
|
|
addMonth: function(amount) {
|
|
return this.setValue(currYear, currMonth + (amount || 1), currDay);
|
|
},
|
|
|
|
addYear: function(amount) {
|
|
return this.setValue(currYear + (amount || 1), currMonth, currDay);
|
|
},
|
|
|
|
hide: function(e) {
|
|
|
|
if (opened) {
|
|
|
|
// onHide
|
|
e = $.Event();
|
|
e.type = "onHide";
|
|
fire.trigger(e);
|
|
|
|
$(document).unbind("click.d").unbind("keydown.d");
|
|
|
|
// cancelled ?
|
|
if (e.isDefaultPrevented()) { return; }
|
|
|
|
// do the hide
|
|
root.hide();
|
|
opened = false;
|
|
}
|
|
|
|
return self;
|
|
},
|
|
|
|
getConf: function() {
|
|
return conf;
|
|
},
|
|
|
|
getInput: function() {
|
|
return input;
|
|
},
|
|
|
|
getCalendar: function() {
|
|
return root;
|
|
},
|
|
|
|
getValue: function(dateFormat) {
|
|
return dateFormat ? format(value, dateFormat, conf.lang) : value;
|
|
},
|
|
|
|
isOpen: function() {
|
|
return opened;
|
|
}
|
|
|
|
});
|
|
|
|
// callbacks
|
|
$.each(['onBeforeShow','onShow','change','onHide'], function(i, name) {
|
|
|
|
// configuration
|
|
if ($.isFunction(conf[name])) {
|
|
$(self).bind(name, conf[name]);
|
|
}
|
|
|
|
// API methods
|
|
self[name] = function(fn) {
|
|
if (fn) { $(self).bind(name, fn); }
|
|
return self;
|
|
};
|
|
});
|
|
|
|
|
|
// show dateinput & assign keyboard shortcuts
|
|
input.bind("focus click", self.show).keydown(function(e) {
|
|
|
|
var key = e.keyCode;
|
|
|
|
// open dateinput with navigation keyw
|
|
if (!opened && $(KEYS).index(key) >= 0) {
|
|
self.show(e);
|
|
return e.preventDefault();
|
|
}
|
|
|
|
// allow tab
|
|
return e.shiftKey || e.ctrlKey || e.altKey || key == 9 ? true : e.preventDefault();
|
|
|
|
});
|
|
|
|
// initial value
|
|
if (parseDate(input.val())) {
|
|
select(value, conf);
|
|
}
|
|
|
|
}
|
|
|
|
$.expr[':'].date = function(el) {
|
|
var type = el.getAttribute("type");
|
|
return type && type == 'date' || !!$(el).data("dateinput");
|
|
};
|
|
|
|
|
|
$.fn.dateinput = function(conf) {
|
|
|
|
// already instantiated
|
|
if (this.data("dateinput")) { return this; }
|
|
|
|
// configuration
|
|
conf = $.extend(true, {}, tool.conf, conf);
|
|
|
|
// CSS prefix
|
|
$.each(conf.css, function(key, val) {
|
|
if (!val && key != 'prefix') {
|
|
conf.css[key] = (conf.css.prefix || '') + (val || key);
|
|
}
|
|
});
|
|
|
|
var els;
|
|
|
|
this.each(function() {
|
|
var el = new Dateinput($(this), conf);
|
|
instances.push(el);
|
|
var input = el.getInput().data("dateinput", el);
|
|
els = els ? els.add(input) : input;
|
|
});
|
|
|
|
return els ? els : this;
|
|
};
|
|
|
|
|
|
}) (jQuery);
|
|
|
|
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 Tabs- The basics of UI design.
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/tabs/
|
|
*
|
|
* Since: November 2008
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
|
|
// static constructs
|
|
$.tools = $.tools || {version: '1.2.5'};
|
|
|
|
$.tools.tabs = {
|
|
|
|
conf: {
|
|
tabs: 'a',
|
|
current: 'current',
|
|
onBeforeClick: null,
|
|
onClick: null,
|
|
effect: 'default',
|
|
initialIndex: 0,
|
|
event: 'click',
|
|
rotate: false,
|
|
|
|
// 1.2
|
|
history: false
|
|
},
|
|
|
|
addEffect: function(name, fn) {
|
|
effects[name] = fn;
|
|
}
|
|
|
|
};
|
|
|
|
var effects = {
|
|
|
|
// simple "toggle" effect
|
|
'default': function(i, done) {
|
|
this.getPanes().hide().eq(i).show();
|
|
done.call();
|
|
},
|
|
|
|
/*
|
|
configuration:
|
|
- fadeOutSpeed (positive value does "crossfading")
|
|
- fadeInSpeed
|
|
*/
|
|
fade: function(i, done) {
|
|
|
|
var conf = this.getConf(),
|
|
speed = conf.fadeOutSpeed,
|
|
panes = this.getPanes();
|
|
|
|
if (speed) {
|
|
panes.fadeOut(speed);
|
|
} else {
|
|
panes.hide();
|
|
}
|
|
|
|
panes.eq(i).fadeIn(conf.fadeInSpeed, done);
|
|
},
|
|
|
|
// for basic accordions
|
|
slide: function(i, done) {
|
|
this.getPanes().slideUp(200);
|
|
this.getPanes().eq(i).slideDown(400, done);
|
|
},
|
|
|
|
/**
|
|
* AJAX effect
|
|
*/
|
|
ajax: function(i, done) {
|
|
this.getPanes().eq(0).load(this.getTabs().eq(i).attr("href"), done);
|
|
}
|
|
};
|
|
|
|
var w;
|
|
|
|
/**
|
|
* Horizontal accordion
|
|
*
|
|
* @deprecated will be replaced with a more robust implementation
|
|
*/
|
|
$.tools.tabs.addEffect("horizontal", function(i, done) {
|
|
|
|
// store original width of a pane into memory
|
|
if (!w) { w = this.getPanes().eq(0).width(); }
|
|
|
|
// set current pane's width to zero
|
|
this.getCurrentPane().animate({width: 0}, function() { $(this).hide(); });
|
|
|
|
// grow opened pane to it's original width
|
|
this.getPanes().eq(i).animate({width: w}, function() {
|
|
$(this).show();
|
|
done.call();
|
|
});
|
|
|
|
});
|
|
|
|
|
|
function Tabs(root, paneSelector, conf) {
|
|
|
|
var self = this,
|
|
trigger = root.add(this),
|
|
tabs = root.find(conf.tabs),
|
|
panes = paneSelector.jquery ? paneSelector : root.children(paneSelector),
|
|
current;
|
|
|
|
|
|
// make sure tabs and panes are found
|
|
if (!tabs.length) { tabs = root.children(); }
|
|
if (!panes.length) { panes = root.parent().find(paneSelector); }
|
|
if (!panes.length) { panes = $(paneSelector); }
|
|
|
|
|
|
// public methods
|
|
$.extend(this, {
|
|
click: function(i, e) {
|
|
|
|
var tab = tabs.eq(i);
|
|
|
|
if (typeof i == 'string' && i.replace("#", "")) {
|
|
tab = tabs.filter("[href*=" + i.replace("#", "") + "]");
|
|
i = Math.max(tabs.index(tab), 0);
|
|
}
|
|
|
|
if (conf.rotate) {
|
|
var last = tabs.length -1;
|
|
if (i < 0) { return self.click(last, e); }
|
|
if (i > last) { return self.click(0, e); }
|
|
}
|
|
|
|
if (!tab.length) {
|
|
if (current >= 0) { return self; }
|
|
i = conf.initialIndex;
|
|
tab = tabs.eq(i);
|
|
}
|
|
|
|
// current tab is being clicked
|
|
if (i === current) { return self; }
|
|
|
|
// possibility to cancel click action
|
|
e = e || $.Event();
|
|
e.type = "onBeforeClick";
|
|
trigger.trigger(e, [i]);
|
|
if (e.isDefaultPrevented()) { return; }
|
|
|
|
// call the effect
|
|
effects[conf.effect].call(self, i, function() {
|
|
|
|
// onClick callback
|
|
e.type = "onClick";
|
|
trigger.trigger(e, [i]);
|
|
});
|
|
|
|
// default behaviour
|
|
current = i;
|
|
tabs.removeClass(conf.current);
|
|
tab.addClass(conf.current);
|
|
|
|
return self;
|
|
},
|
|
|
|
getConf: function() {
|
|
return conf;
|
|
},
|
|
|
|
getTabs: function() {
|
|
return tabs;
|
|
},
|
|
|
|
getPanes: function() {
|
|
return panes;
|
|
},
|
|
|
|
getCurrentPane: function() {
|
|
return panes.eq(current);
|
|
},
|
|
|
|
getCurrentTab: function() {
|
|
return tabs.eq(current);
|
|
},
|
|
|
|
getIndex: function() {
|
|
return current;
|
|
},
|
|
|
|
next: function() {
|
|
return self.click(current + 1);
|
|
},
|
|
|
|
prev: function() {
|
|
return self.click(current - 1);
|
|
},
|
|
|
|
destroy: function() {
|
|
tabs.unbind(conf.event).removeClass(conf.current);
|
|
panes.find("a[href^=#]").unbind("click.T");
|
|
return self;
|
|
}
|
|
|
|
});
|
|
|
|
// callbacks
|
|
$.each("onBeforeClick,onClick".split(","), function(i, name) {
|
|
|
|
// configuration
|
|
if ($.isFunction(conf[name])) {
|
|
$(self).bind(name, conf[name]);
|
|
}
|
|
|
|
// API
|
|
self[name] = function(fn) {
|
|
if (fn) { $(self).bind(name, fn); }
|
|
return self;
|
|
};
|
|
});
|
|
|
|
|
|
if (conf.history && $.fn.history) {
|
|
$.tools.history.init(tabs);
|
|
conf.event = 'history';
|
|
}
|
|
|
|
// setup click actions for each tab
|
|
tabs.each(function(i) {
|
|
$(this).bind(conf.event, function(e) {
|
|
self.click(i, e);
|
|
return e.preventDefault();
|
|
});
|
|
});
|
|
|
|
// cross tab anchor link
|
|
panes.find("a[href^=#]").bind("click.T", function(e) {
|
|
self.click($(this).attr("href"), e);
|
|
});
|
|
|
|
// open initial tab
|
|
if (location.hash && conf.tabs == "a" && root.find("[href=" +location.hash+ "]").length) {
|
|
self.click(location.hash);
|
|
|
|
} else {
|
|
if (conf.initialIndex === 0 || conf.initialIndex > 0) {
|
|
self.click(conf.initialIndex);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// jQuery plugin implementation
|
|
$.fn.tabs = function(paneSelector, conf) {
|
|
|
|
// return existing instance
|
|
var el = this.data("tabs");
|
|
if (el) {
|
|
el.destroy();
|
|
this.removeData("tabs");
|
|
}
|
|
|
|
if ($.isFunction(conf)) {
|
|
conf = {onBeforeClick: conf};
|
|
}
|
|
|
|
// setup conf
|
|
conf = $.extend({}, $.tools.tabs.conf, conf);
|
|
|
|
|
|
this.each(function() {
|
|
el = new Tabs($(this), paneSelector, conf);
|
|
$(this).data("tabs", el);
|
|
});
|
|
|
|
return conf.api ? el: this;
|
|
};
|
|
|
|
}) (jQuery);
|
|
|
|
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 Slideshow - Extend it.
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/tabs/slideshow.html
|
|
*
|
|
* Since: September 2009
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
|
|
var tool;
|
|
|
|
tool = $.tools.tabs.slideshow = {
|
|
|
|
conf: {
|
|
next: '.forward',
|
|
prev: '.backward',
|
|
disabledClass: 'disabled',
|
|
autoplay: false,
|
|
autopause: true,
|
|
interval: 3000,
|
|
clickable: true,
|
|
api: false
|
|
}
|
|
};
|
|
|
|
function Slideshow(root, conf) {
|
|
|
|
var self = this,
|
|
fire = root.add(this),
|
|
tabs = root.data("tabs"),
|
|
timer,
|
|
stopped = true;
|
|
|
|
|
|
// next / prev buttons
|
|
function find(query) {
|
|
var el = $(query);
|
|
return el.length < 2 ? el : root.parent().find(query);
|
|
}
|
|
|
|
var nextButton = find(conf.next).click(function() {
|
|
tabs.next();
|
|
});
|
|
|
|
var prevButton = find(conf.prev).click(function() {
|
|
tabs.prev();
|
|
});
|
|
|
|
|
|
// extend the Tabs API with slideshow methods
|
|
$.extend(self, {
|
|
|
|
// return tabs API
|
|
getTabs: function() {
|
|
return tabs;
|
|
},
|
|
|
|
getConf: function() {
|
|
return conf;
|
|
},
|
|
|
|
play: function() {
|
|
|
|
// do not start additional timer if already exists
|
|
if (timer) { return self; }
|
|
|
|
// onBeforePlay
|
|
var e = $.Event("onBeforePlay");
|
|
fire.trigger(e);
|
|
if (e.isDefaultPrevented()) { return self; }
|
|
|
|
|
|
// construct new timer
|
|
timer = setInterval(tabs.next, conf.interval);
|
|
stopped = false;
|
|
|
|
// onPlay
|
|
fire.trigger("onPlay");
|
|
|
|
return self;
|
|
},
|
|
|
|
pause: function() {
|
|
|
|
if (!timer) { return self; }
|
|
|
|
// onBeforePause
|
|
var e = $.Event("onBeforePause");
|
|
fire.trigger(e);
|
|
if (e.isDefaultPrevented()) { return self; }
|
|
|
|
timer = clearInterval(timer);
|
|
|
|
// onPause
|
|
fire.trigger("onPause");
|
|
|
|
return self;
|
|
},
|
|
|
|
// when stopped - mouseover won't restart
|
|
stop: function() {
|
|
self.pause();
|
|
stopped = true;
|
|
}
|
|
|
|
});
|
|
|
|
// callbacks
|
|
$.each("onBeforePlay,onPlay,onBeforePause,onPause".split(","), function(i, name) {
|
|
|
|
// configuration
|
|
if ($.isFunction(conf[name])) {
|
|
$(self).bind(name, conf[name]);
|
|
}
|
|
|
|
// API methods
|
|
self[name] = function(fn) {
|
|
return $(self).bind(name, fn);
|
|
};
|
|
});
|
|
|
|
|
|
/* when mouse enters, slideshow stops */
|
|
if (conf.autopause) {
|
|
tabs.getTabs().add(nextButton).add(prevButton).add(tabs.getPanes()).hover(self.pause, function() {
|
|
if (!stopped) { self.play(); }
|
|
});
|
|
}
|
|
|
|
if (conf.autoplay) {
|
|
self.play();
|
|
}
|
|
|
|
if (conf.clickable) {
|
|
tabs.getPanes().click(function() {
|
|
tabs.next();
|
|
});
|
|
}
|
|
|
|
// manage disabling of next/prev buttons
|
|
if (!tabs.getConf().rotate) {
|
|
|
|
var disabled = conf.disabledClass;
|
|
|
|
if (!tabs.getIndex()) {
|
|
prevButton.addClass(disabled);
|
|
}
|
|
|
|
tabs.onBeforeClick(function(e, i) {
|
|
prevButton.toggleClass(disabled, !i);
|
|
nextButton.toggleClass(disabled, i == tabs.getTabs().length -1);
|
|
});
|
|
}
|
|
}
|
|
|
|
// jQuery plugin implementation
|
|
$.fn.slideshow = function(conf) {
|
|
|
|
// return existing instance
|
|
var el = this.data("slideshow");
|
|
if (el) { return el; }
|
|
|
|
conf = $.extend({}, tool.conf, conf);
|
|
|
|
this.each(function() {
|
|
el = new Slideshow($(this), conf);
|
|
$(this).data("slideshow", el);
|
|
});
|
|
|
|
return conf.api ? el : this;
|
|
};
|
|
|
|
})(jQuery);
|
|
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 / Scrollable Navigator
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/scrollable/navigator.html
|
|
*
|
|
* Since: September 2009
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
|
|
var t = $.tools.scrollable;
|
|
|
|
t.navigator = {
|
|
|
|
conf: {
|
|
navi: '.navi',
|
|
naviItem: null,
|
|
activeClass: 'active',
|
|
indexed: false,
|
|
idPrefix: null,
|
|
|
|
// 1.2
|
|
history: false
|
|
}
|
|
};
|
|
|
|
function find(root, query) {
|
|
var el = $(query);
|
|
return el.length < 2 ? el : root.parent().find(query);
|
|
}
|
|
|
|
// jQuery plugin implementation
|
|
$.fn.navigator = function(conf) {
|
|
|
|
// configuration
|
|
if (typeof conf == 'string') { conf = {navi: conf}; }
|
|
conf = $.extend({}, t.navigator.conf, conf);
|
|
|
|
var ret;
|
|
|
|
this.each(function() {
|
|
|
|
var api = $(this).data("scrollable"),
|
|
navi = conf.navi.jquery ? conf.navi : find(api.getRoot(), conf.navi),
|
|
buttons = api.getNaviButtons(),
|
|
cls = conf.activeClass,
|
|
history = conf.history && $.fn.history;
|
|
|
|
// @deprecated stuff
|
|
if (api) { ret = api; }
|
|
|
|
api.getNaviButtons = function() {
|
|
return buttons.add(navi);
|
|
};
|
|
|
|
|
|
function doClick(el, i, e) {
|
|
api.seekTo(i);
|
|
if (history) {
|
|
if (location.hash) {
|
|
location.hash = el.attr("href").replace("#", "");
|
|
}
|
|
} else {
|
|
return e.preventDefault();
|
|
}
|
|
}
|
|
|
|
function els() {
|
|
return navi.find(conf.naviItem || '> *');
|
|
}
|
|
|
|
function addItem(i) {
|
|
|
|
var item = $("<" + (conf.naviItem || 'a') + "/>").click(function(e) {
|
|
doClick($(this), i, e);
|
|
|
|
}).attr("href", "#" + i);
|
|
|
|
// index number / id attribute
|
|
if (i === 0) { item.addClass(cls); }
|
|
if (conf.indexed) { item.text(i + 1); }
|
|
if (conf.idPrefix) { item.attr("id", conf.idPrefix + i); }
|
|
|
|
return item.appendTo(navi);
|
|
}
|
|
|
|
|
|
// generate navigator
|
|
if (els().length) {
|
|
els().each(function(i) {
|
|
$(this).click(function(e) {
|
|
doClick($(this), i, e);
|
|
});
|
|
});
|
|
|
|
} else {
|
|
$.each(api.getItems(), function(i) {
|
|
addItem(i);
|
|
});
|
|
}
|
|
|
|
// activate correct entry
|
|
api.onBeforeSeek(function(e, index) {
|
|
setTimeout(function() {
|
|
if (!e.isDefaultPrevented()) {
|
|
var el = els().eq(index);
|
|
if (!e.isDefaultPrevented() && el.length) {
|
|
els().removeClass(cls).eq(index).addClass(cls);
|
|
}
|
|
}
|
|
}, 1);
|
|
});
|
|
|
|
function doHistory(evt, hash) {
|
|
var el = els().eq(hash.replace("#", ""));
|
|
if (!el.length) {
|
|
el = els().filter("[href=" + hash + "]");
|
|
}
|
|
el.click();
|
|
}
|
|
|
|
// new item being added
|
|
api.onAddItem(function(e, item) {
|
|
item = addItem(api.getItems().index(item));
|
|
if (history) { item.history(doHistory); }
|
|
});
|
|
|
|
if (history) { els().history(doHistory); }
|
|
|
|
});
|
|
|
|
return conf.api ? ret : this;
|
|
|
|
};
|
|
|
|
})(jQuery);
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 Scrollable - New wave UI design
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/scrollable.html
|
|
*
|
|
* Since: March 2008
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
|
|
// static constructs
|
|
$.tools = $.tools || {version: '1.2.5'};
|
|
|
|
$.tools.scrollable = {
|
|
|
|
conf: {
|
|
activeClass: 'active',
|
|
circular: false,
|
|
clonedClass: 'cloned',
|
|
disabledClass: 'disabled',
|
|
easing: 'swing',
|
|
initialIndex: 0,
|
|
item: null,
|
|
items: '.items',
|
|
keyboard: true,
|
|
mousewheel: false,
|
|
next: '.next',
|
|
prev: '.prev',
|
|
speed: 400,
|
|
vertical: false,
|
|
touch: true,
|
|
wheelSpeed: 0
|
|
}
|
|
};
|
|
|
|
// get hidden element's width or height even though it's hidden
|
|
function dim(el, key) {
|
|
var v = parseInt(el.css(key), 10);
|
|
if (v) { return v; }
|
|
var s = el[0].currentStyle;
|
|
return s && s.width && parseInt(s.width, 10);
|
|
}
|
|
|
|
function find(root, query) {
|
|
var el = $(query);
|
|
return el.length < 2 ? el : root.parent().find(query);
|
|
}
|
|
|
|
var current;
|
|
|
|
// constructor
|
|
function Scrollable(root, conf) {
|
|
|
|
// current instance
|
|
var self = this,
|
|
fire = root.add(self),
|
|
itemWrap = root.children(),
|
|
index = 0,
|
|
vertical = conf.vertical;
|
|
|
|
if (!current) { current = self; }
|
|
if (itemWrap.length > 1) { itemWrap = $(conf.items, root); }
|
|
|
|
// methods
|
|
$.extend(self, {
|
|
|
|
getConf: function() {
|
|
return conf;
|
|
},
|
|
|
|
getIndex: function() {
|
|
return index;
|
|
},
|
|
|
|
getSize: function() {
|
|
return self.getItems().size();
|
|
},
|
|
|
|
getNaviButtons: function() {
|
|
return prev.add(next);
|
|
},
|
|
|
|
getRoot: function() {
|
|
return root;
|
|
},
|
|
|
|
getItemWrap: function() {
|
|
return itemWrap;
|
|
},
|
|
|
|
getItems: function() {
|
|
return itemWrap.children(conf.item).not("." + conf.clonedClass);
|
|
},
|
|
|
|
move: function(offset, time) {
|
|
return self.seekTo(index + offset, time);
|
|
},
|
|
|
|
next: function(time) {
|
|
return self.move(1, time);
|
|
},
|
|
|
|
prev: function(time) {
|
|
return self.move(-1, time);
|
|
},
|
|
|
|
begin: function(time) {
|
|
return self.seekTo(0, time);
|
|
},
|
|
|
|
end: function(time) {
|
|
return self.seekTo(self.getSize() -1, time);
|
|
},
|
|
|
|
focus: function() {
|
|
current = self;
|
|
return self;
|
|
},
|
|
|
|
addItem: function(item) {
|
|
item = $(item);
|
|
|
|
if (!conf.circular) {
|
|
itemWrap.append(item);
|
|
} else {
|
|
itemWrap.children("." + conf.clonedClass + ":last").before(item);
|
|
itemWrap.children("." + conf.clonedClass + ":first").replaceWith(item.clone().addClass(conf.clonedClass));
|
|
}
|
|
|
|
fire.trigger("onAddItem", [item]);
|
|
return self;
|
|
},
|
|
|
|
|
|
/* all seeking functions depend on this */
|
|
seekTo: function(i, time, fn) {
|
|
|
|
// ensure numeric index
|
|
if (!i.jquery) { i *= 1; }
|
|
|
|
// avoid seeking from end clone to the beginning
|
|
if (conf.circular && i === 0 && index == -1 && time !== 0) { return self; }
|
|
|
|
// check that index is sane
|
|
if (!conf.circular && i < 0 || i > self.getSize() || i < -1) { return self; }
|
|
|
|
var item = i;
|
|
|
|
if (i.jquery) {
|
|
i = self.getItems().index(i);
|
|
|
|
} else {
|
|
item = self.getItems().eq(i);
|
|
}
|
|
|
|
// onBeforeSeek
|
|
var e = $.Event("onBeforeSeek");
|
|
if (!fn) {
|
|
fire.trigger(e, [i, time]);
|
|
if (e.isDefaultPrevented() || !item.length) { return self; }
|
|
}
|
|
|
|
var props = vertical ? {top: -item.position().top} : {left: -item.position().left};
|
|
|
|
index = i;
|
|
current = self;
|
|
if (time === undefined) { time = conf.speed; }
|
|
|
|
itemWrap.animate(props, time, conf.easing, fn || function() {
|
|
fire.trigger("onSeek", [i]);
|
|
});
|
|
|
|
return self;
|
|
}
|
|
|
|
});
|
|
|
|
// callbacks
|
|
$.each(['onBeforeSeek', 'onSeek', 'onAddItem'], function(i, name) {
|
|
|
|
// configuration
|
|
if ($.isFunction(conf[name])) {
|
|
$(self).bind(name, conf[name]);
|
|
}
|
|
|
|
self[name] = function(fn) {
|
|
if (fn) { $(self).bind(name, fn); }
|
|
return self;
|
|
};
|
|
});
|
|
|
|
// circular loop
|
|
if (conf.circular) {
|
|
|
|
var cloned1 = self.getItems().slice(-1).clone().prependTo(itemWrap),
|
|
cloned2 = self.getItems().eq(1).clone().appendTo(itemWrap);
|
|
|
|
cloned1.add(cloned2).addClass(conf.clonedClass);
|
|
|
|
self.onBeforeSeek(function(e, i, time) {
|
|
|
|
|
|
if (e.isDefaultPrevented()) { return; }
|
|
|
|
/*
|
|
1. animate to the clone without event triggering
|
|
2. seek to correct position with 0 speed
|
|
*/
|
|
if (i == -1) {
|
|
self.seekTo(cloned1, time, function() {
|
|
self.end(0);
|
|
});
|
|
return e.preventDefault();
|
|
|
|
} else if (i == self.getSize()) {
|
|
self.seekTo(cloned2, time, function() {
|
|
self.begin(0);
|
|
});
|
|
}
|
|
|
|
});
|
|
|
|
// seek over the cloned item
|
|
self.seekTo(0, 0, function() {});
|
|
}
|
|
|
|
// next/prev buttons
|
|
var prev = find(root, conf.prev).click(function() { self.prev(); }),
|
|
next = find(root, conf.next).click(function() { self.next(); });
|
|
|
|
if (!conf.circular && self.getSize() > 1) {
|
|
|
|
self.onBeforeSeek(function(e, i) {
|
|
setTimeout(function() {
|
|
if (!e.isDefaultPrevented()) {
|
|
prev.toggleClass(conf.disabledClass, i <= 0);
|
|
next.toggleClass(conf.disabledClass, i >= self.getSize() -1);
|
|
}
|
|
}, 1);
|
|
});
|
|
|
|
if (!conf.initialIndex) {
|
|
prev.addClass(conf.disabledClass);
|
|
}
|
|
}
|
|
|
|
// mousewheel support
|
|
if (conf.mousewheel && $.fn.mousewheel) {
|
|
root.mousewheel(function(e, delta) {
|
|
if (conf.mousewheel) {
|
|
self.move(delta < 0 ? 1 : -1, conf.wheelSpeed || 50);
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
// touch event
|
|
if (conf.touch) {
|
|
var touch = {};
|
|
|
|
itemWrap[0].ontouchstart = function(e) {
|
|
var t = e.touches[0];
|
|
touch.x = t.clientX;
|
|
touch.y = t.clientY;
|
|
};
|
|
|
|
itemWrap[0].ontouchmove = function(e) {
|
|
|
|
// only deal with one finger
|
|
if (e.touches.length == 1 && !itemWrap.is(":animated")) {
|
|
var t = e.touches[0],
|
|
deltaX = touch.x - t.clientX,
|
|
deltaY = touch.y - t.clientY;
|
|
|
|
self[vertical && deltaY > 0 || !vertical && deltaX > 0 ? 'next' : 'prev']();
|
|
e.preventDefault();
|
|
}
|
|
};
|
|
}
|
|
|
|
if (conf.keyboard) {
|
|
|
|
$(document).bind("keydown.scrollable", function(evt) {
|
|
|
|
// skip certain conditions
|
|
if (!conf.keyboard || evt.altKey || evt.ctrlKey || $(evt.target).is(":input")) { return; }
|
|
|
|
// does this instance have focus?
|
|
if (conf.keyboard != 'static' && current != self) { return; }
|
|
|
|
var key = evt.keyCode;
|
|
|
|
if (vertical && (key == 38 || key == 40)) {
|
|
self.move(key == 38 ? -1 : 1);
|
|
return evt.preventDefault();
|
|
}
|
|
|
|
if (!vertical && (key == 37 || key == 39)) {
|
|
self.move(key == 37 ? -1 : 1);
|
|
return evt.preventDefault();
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
// initial index
|
|
if (conf.initialIndex) {
|
|
self.seekTo(conf.initialIndex, 0, function() {});
|
|
}
|
|
}
|
|
|
|
|
|
// jQuery plugin implementation
|
|
$.fn.scrollable = function(conf) {
|
|
|
|
// already constructed --> return API
|
|
var el = this.data("scrollable");
|
|
if (el) { return el; }
|
|
|
|
conf = $.extend({}, $.tools.scrollable.conf, conf);
|
|
|
|
this.each(function() {
|
|
el = new Scrollable($(this), conf);
|
|
$(this).data("scrollable", el);
|
|
});
|
|
|
|
return conf.api ? el: this;
|
|
|
|
};
|
|
|
|
|
|
})(jQuery);
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 / Scrollable Autoscroll
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/scrollable/autoscroll.html
|
|
*
|
|
* Since: September 2009
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
|
|
var t = $.tools.scrollable;
|
|
|
|
t.autoscroll = {
|
|
|
|
conf: {
|
|
autoplay: true,
|
|
interval: 3000,
|
|
autopause: true
|
|
}
|
|
};
|
|
|
|
// jQuery plugin implementation
|
|
$.fn.autoscroll = function(conf) {
|
|
|
|
if (typeof conf == 'number') {
|
|
conf = {interval: conf};
|
|
}
|
|
|
|
var opts = $.extend({}, t.autoscroll.conf, conf), ret;
|
|
|
|
this.each(function() {
|
|
|
|
var api = $(this).data("scrollable");
|
|
if (api) { ret = api; }
|
|
|
|
// interval stuff
|
|
var timer, stopped = true;
|
|
|
|
api.play = function() {
|
|
|
|
// do not start additional timer if already exists
|
|
if (timer) { return; }
|
|
|
|
stopped = false;
|
|
|
|
// construct new timer
|
|
timer = setInterval(function() {
|
|
api.next();
|
|
}, opts.interval);
|
|
|
|
};
|
|
|
|
api.pause = function() {
|
|
timer = clearInterval(timer);
|
|
};
|
|
|
|
// when stopped - mouseover won't restart
|
|
api.stop = function() {
|
|
api.pause();
|
|
stopped = true;
|
|
};
|
|
|
|
/* when mouse enters, autoscroll stops */
|
|
if (opts.autopause) {
|
|
api.getRoot().add(api.getNaviButtons()).hover(api.pause, api.play);
|
|
}
|
|
|
|
if (opts.autoplay) {
|
|
api.play();
|
|
}
|
|
|
|
});
|
|
|
|
return opts.api ? ret : this;
|
|
|
|
};
|
|
|
|
})(jQuery);
|
|
/**
|
|
* @license
|
|
* jQuery Tools Validator 1.2.5 - HTML5 is here. Now use it.
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/form/validator/
|
|
*
|
|
* Since: Mar 2010
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
/*jslint evil: true */
|
|
(function($) {
|
|
|
|
$.tools = $.tools || {version: '1.2.5'};
|
|
|
|
// globals
|
|
var typeRe = /\[type=([a-z]+)\]/,
|
|
numRe = /^-?[0-9]*(\.[0-9]+)?$/,
|
|
dateInput = $.tools.dateinput,
|
|
|
|
// http://net.tutsplus.com/tutorials/other/8-regular-expressions-you-should-know/
|
|
emailRe = /^([a-z0-9_\.\-\+]+)@([\da-z\.\-]+)\.([a-z\.]{2,6})$/i,
|
|
urlRe = /^(https?:\/\/)?[\da-z\.\-]+\.[a-z\.]{2,6}[#&+_\?\/\w \.\-=]*$/i,
|
|
v;
|
|
|
|
v = $.tools.validator = {
|
|
|
|
conf: {
|
|
grouped: false, // show all error messages at once inside the container
|
|
effect: 'default', // show/hide effect for error message. only 'default' is built-in
|
|
errorClass: 'invalid', // input field class name in case of validation error
|
|
|
|
// when to check for validity?
|
|
inputEvent: null, // change, blur, keyup, null
|
|
errorInputEvent: 'keyup', // change, blur, keyup, null
|
|
formEvent: 'submit', // submit, null
|
|
|
|
lang: 'en', // default language for error messages
|
|
message: '<div/>',
|
|
messageAttr: 'data-message', // name of the attribute for overridden error message
|
|
messageClass: 'error', // error message element's class name
|
|
offset: [0, 0],
|
|
position: 'center right',
|
|
singleError: false, // validate all inputs at once
|
|
speed: 'normal' // message's fade-in speed
|
|
},
|
|
|
|
|
|
/* The Error Messages */
|
|
messages: {
|
|
"*": { en: "Please correct this value" }
|
|
},
|
|
|
|
localize: function(lang, messages) {
|
|
$.each(messages, function(key, msg) {
|
|
v.messages[key] = v.messages[key] || {};
|
|
v.messages[key][lang] = msg;
|
|
});
|
|
},
|
|
|
|
localizeFn: function(key, messages) {
|
|
v.messages[key] = v.messages[key] || {};
|
|
$.extend(v.messages[key], messages);
|
|
},
|
|
|
|
/**
|
|
* Adds a new validator
|
|
*/
|
|
fn: function(matcher, msg, fn) {
|
|
|
|
// no message supplied
|
|
if ($.isFunction(msg)) {
|
|
fn = msg;
|
|
|
|
// message(s) on second argument
|
|
} else {
|
|
if (typeof msg == 'string') { msg = {en: msg}; }
|
|
this.messages[matcher.key || matcher] = msg;
|
|
}
|
|
|
|
// check for "[type=xxx]" (not supported by jQuery)
|
|
var test = typeRe.exec(matcher);
|
|
if (test) { matcher = isType(test[1]); }
|
|
|
|
// add validator to the arsenal
|
|
fns.push([matcher, fn]);
|
|
},
|
|
|
|
/* Add new show/hide effect */
|
|
addEffect: function(name, showFn, closeFn) {
|
|
effects[name] = [showFn, closeFn];
|
|
}
|
|
|
|
};
|
|
|
|
/* calculate error message position relative to the input */
|
|
function getPosition(trigger, el, conf) {
|
|
|
|
// get origin top/left position
|
|
var top = trigger.offset().top,
|
|
left = trigger.offset().left,
|
|
pos = conf.position.split(/,?\s+/),
|
|
y = pos[0],
|
|
x = pos[1];
|
|
|
|
top -= el.outerHeight() - conf.offset[0];
|
|
left += trigger.outerWidth() + conf.offset[1];
|
|
|
|
|
|
// iPad position fix
|
|
if (/iPad/i.test(navigator.userAgent)) {
|
|
top -= $(window).scrollTop();
|
|
}
|
|
|
|
// adjust Y
|
|
var height = el.outerHeight() + trigger.outerHeight();
|
|
if (y == 'center') { top += height / 2; }
|
|
if (y == 'bottom') { top += height; }
|
|
|
|
// adjust X
|
|
var width = trigger.outerWidth();
|
|
if (x == 'center') { left -= (width + el.outerWidth()) / 2; }
|
|
if (x == 'left') { left -= width; }
|
|
|
|
return {top: top, left: left};
|
|
}
|
|
|
|
|
|
|
|
// $.is("[type=xxx]") or $.filter("[type=xxx]") not working in jQuery 1.3.2 or 1.4.2
|
|
function isType(type) {
|
|
function fn() {
|
|
return this.getAttribute("type") == type;
|
|
}
|
|
fn.key = "[type=" + type + "]";
|
|
return fn;
|
|
}
|
|
|
|
|
|
var fns = [], effects = {
|
|
|
|
'default' : [
|
|
|
|
// show errors function
|
|
function(errs) {
|
|
|
|
var conf = this.getConf();
|
|
|
|
// loop errors
|
|
$.each(errs, function(i, err) {
|
|
|
|
// add error class
|
|
var input = err.input;
|
|
input.addClass(conf.errorClass);
|
|
|
|
// get handle to the error container
|
|
var msg = input.data("msg.el");
|
|
|
|
// create it if not present
|
|
if (!msg) {
|
|
msg = $(conf.message).addClass(conf.messageClass).appendTo(document.body);
|
|
input.data("msg.el", msg);
|
|
}
|
|
|
|
// clear the container
|
|
msg.css({visibility: 'hidden'}).find("p").remove();
|
|
|
|
// populate messages
|
|
$.each(err.messages, function(i, m) {
|
|
$("<p/>").html(m).appendTo(msg);
|
|
});
|
|
|
|
// make sure the width is not full body width so it can be positioned correctly
|
|
if (msg.outerWidth() == msg.parent().width()) {
|
|
msg.add(msg.find("p")).css({display: 'inline'});
|
|
}
|
|
|
|
// insert into correct position (relative to the field)
|
|
var pos = getPosition(input, msg, conf);
|
|
|
|
msg.css({ visibility: 'visible', position: 'absolute', top: pos.top, left: pos.left })
|
|
.fadeIn(conf.speed);
|
|
});
|
|
|
|
|
|
// hide errors function
|
|
}, function(inputs) {
|
|
|
|
var conf = this.getConf();
|
|
inputs.removeClass(conf.errorClass).each(function() {
|
|
var msg = $(this).data("msg.el");
|
|
if (msg) { msg.css({visibility: 'hidden'}); }
|
|
});
|
|
}
|
|
]
|
|
};
|
|
|
|
|
|
/* sperial selectors */
|
|
$.each("email,url,number".split(","), function(i, key) {
|
|
$.expr[':'][key] = function(el) {
|
|
return el.getAttribute("type") === key;
|
|
};
|
|
});
|
|
|
|
|
|
/*
|
|
oninvalid() jQuery plugin.
|
|
Usage: $("input:eq(2)").oninvalid(function() { ... });
|
|
*/
|
|
$.fn.oninvalid = function( fn ){
|
|
return this[fn ? "bind" : "trigger"]("OI", fn);
|
|
};
|
|
|
|
|
|
/******* built-in HTML5 standard validators *********/
|
|
|
|
v.fn(":email", "Please enter a valid email address", function(el, v) {
|
|
return !v || emailRe.test(v);
|
|
});
|
|
|
|
v.fn(":url", "Please enter a valid URL", function(el, v) {
|
|
return !v || urlRe.test(v);
|
|
});
|
|
|
|
v.fn(":number", "Please enter a numeric value.", function(el, v) {
|
|
return numRe.test(v);
|
|
});
|
|
|
|
v.fn("[max]", "Please enter a value smaller than $1", function(el, v) {
|
|
|
|
// skip empty values and dateinputs
|
|
if (v === '' || dateInput && el.is(":date")) { return true; }
|
|
|
|
var max = el.attr("max");
|
|
return parseFloat(v) <= parseFloat(max) ? true : [max];
|
|
});
|
|
|
|
v.fn("[min]", "Please enter a value larger than $1", function(el, v) {
|
|
|
|
// skip empty values and dateinputs
|
|
if (v === '' || dateInput && el.is(":date")) { return true; }
|
|
|
|
var min = el.attr("min");
|
|
return parseFloat(v) >= parseFloat(min) ? true : [min];
|
|
});
|
|
|
|
v.fn("[required]", "Please complete this mandatory field.", function(el, v) {
|
|
if (el.is(":checkbox")) { return el.is(":checked"); }
|
|
return !!v;
|
|
});
|
|
|
|
v.fn("[pattern]", function(el) {
|
|
var p = new RegExp("^" + el.attr("pattern") + "$");
|
|
return p.test(el.val());
|
|
});
|
|
|
|
|
|
function Validator(inputs, form, conf) {
|
|
|
|
// private variables
|
|
var self = this,
|
|
fire = form.add(self);
|
|
|
|
// make sure there are input fields available
|
|
inputs = inputs.not(":button, :image, :reset, :submit");
|
|
|
|
// utility function
|
|
function pushMessage(to, matcher, returnValue) {
|
|
|
|
// only one message allowed
|
|
if (!conf.grouped && to.length) { return; }
|
|
|
|
// the error message
|
|
var msg;
|
|
|
|
// substitutions are returned
|
|
if (returnValue === false || $.isArray(returnValue)) {
|
|
msg = v.messages[matcher.key || matcher] || v.messages["*"];
|
|
msg = msg[conf.lang] || v.messages["*"].en;
|
|
|
|
// substitution
|
|
var matches = msg.match(/\$\d/g);
|
|
|
|
if (matches && $.isArray(returnValue)) {
|
|
$.each(matches, function(i) {
|
|
msg = msg.replace(this, returnValue[i]);
|
|
});
|
|
}
|
|
|
|
// error message is returned directly
|
|
} else {
|
|
msg = returnValue[conf.lang] || returnValue;
|
|
}
|
|
|
|
to.push(msg);
|
|
}
|
|
|
|
|
|
// API methods
|
|
$.extend(self, {
|
|
|
|
getConf: function() {
|
|
return conf;
|
|
},
|
|
|
|
getForm: function() {
|
|
return form;
|
|
},
|
|
|
|
getInputs: function() {
|
|
return inputs;
|
|
},
|
|
|
|
reflow: function() {
|
|
inputs.each(function() {
|
|
var input = $(this),
|
|
msg = input.data("msg.el");
|
|
|
|
if (msg) {
|
|
var pos = getPosition(input, msg, conf);
|
|
msg.css({ top: pos.top, left: pos.left });
|
|
}
|
|
});
|
|
return self;
|
|
},
|
|
|
|
/* @param e - for internal use only */
|
|
invalidate: function(errs, e) {
|
|
|
|
// errors are given manually: { fieldName1: 'message1', fieldName2: 'message2' }
|
|
if (!e) {
|
|
var errors = [];
|
|
$.each(errs, function(key, val) {
|
|
var input = inputs.filter("[name='" + key + "']");
|
|
if (input.length) {
|
|
|
|
// trigger HTML5 ininvalid event
|
|
input.trigger("OI", [val]);
|
|
|
|
errors.push({ input: input, messages: [val]});
|
|
}
|
|
});
|
|
|
|
errs = errors;
|
|
e = $.Event();
|
|
}
|
|
|
|
// onFail callback
|
|
e.type = "onFail";
|
|
fire.trigger(e, [errs]);
|
|
|
|
// call the effect
|
|
if (!e.isDefaultPrevented()) {
|
|
effects[conf.effect][0].call(self, errs, e);
|
|
}
|
|
|
|
return self;
|
|
},
|
|
|
|
reset: function(els) {
|
|
els = els || inputs;
|
|
els.removeClass(conf.errorClass).each(function() {
|
|
var msg = $(this).data("msg.el");
|
|
if (msg) {
|
|
msg.remove();
|
|
$(this).data("msg.el", null);
|
|
}
|
|
}).unbind(conf.errorInputEvent || '');
|
|
return self;
|
|
},
|
|
|
|
destroy: function() {
|
|
form.unbind(conf.formEvent + ".V").unbind("reset.V");
|
|
inputs.unbind(conf.inputEvent + ".V").unbind("change.V");
|
|
return self.reset();
|
|
},
|
|
|
|
|
|
//{{{ checkValidity() - flesh and bone of this tool
|
|
|
|
/* @returns boolean */
|
|
checkValidity: function(els, e) {
|
|
|
|
els = els || inputs;
|
|
els = els.not(":disabled");
|
|
if (!els.length) { return true; }
|
|
|
|
e = e || $.Event();
|
|
|
|
// onBeforeValidate
|
|
e.type = "onBeforeValidate";
|
|
fire.trigger(e, [els]);
|
|
if (e.isDefaultPrevented()) { return e.result; }
|
|
|
|
// container for errors
|
|
var errs = [];
|
|
|
|
// loop trough the inputs
|
|
els.not(":radio:not(:checked)").each(function() {
|
|
|
|
// field and it's error message container
|
|
var msgs = [],
|
|
el = $(this).data("messages", msgs),
|
|
event = dateInput && el.is(":date") ? "onHide.v" : conf.errorInputEvent + ".v";
|
|
|
|
// cleanup previous validation event
|
|
el.unbind(event);
|
|
|
|
|
|
// loop all validator functions
|
|
$.each(fns, function() {
|
|
var fn = this, match = fn[0];
|
|
|
|
// match found
|
|
if (el.filter(match).length) {
|
|
|
|
// execute a validator function
|
|
var returnValue = fn[1].call(self, el, el.val());
|
|
|
|
|
|
// validation failed. multiple substitutions can be returned with an array
|
|
if (returnValue !== true) {
|
|
|
|
// onBeforeFail
|
|
e.type = "onBeforeFail";
|
|
fire.trigger(e, [el, match]);
|
|
if (e.isDefaultPrevented()) { return false; }
|
|
|
|
// overridden custom message
|
|
var msg = el.attr(conf.messageAttr);
|
|
if (msg) {
|
|
msgs = [msg];
|
|
return false;
|
|
} else {
|
|
pushMessage(msgs, match, returnValue);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
if (msgs.length) {
|
|
|
|
errs.push({input: el, messages: msgs});
|
|
|
|
// trigger HTML5 ininvalid event
|
|
el.trigger("OI", [msgs]);
|
|
|
|
// begin validating upon error event type (such as keyup)
|
|
if (conf.errorInputEvent) {
|
|
el.bind(event, function(e) {
|
|
self.checkValidity(el, e);
|
|
});
|
|
}
|
|
}
|
|
|
|
if (conf.singleError && errs.length) { return false; }
|
|
|
|
});
|
|
|
|
|
|
// validation done. now check that we have a proper effect at hand
|
|
var eff = effects[conf.effect];
|
|
if (!eff) { throw "Validator: cannot find effect \"" + conf.effect + "\""; }
|
|
|
|
// errors found
|
|
if (errs.length) {
|
|
self.invalidate(errs, e);
|
|
return false;
|
|
|
|
// no errors
|
|
} else {
|
|
|
|
// call the effect
|
|
eff[1].call(self, els, e);
|
|
|
|
// onSuccess callback
|
|
e.type = "onSuccess";
|
|
fire.trigger(e, [els]);
|
|
|
|
els.unbind(conf.errorInputEvent + ".v");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
//}}}
|
|
|
|
});
|
|
|
|
// callbacks
|
|
$.each("onBeforeValidate,onBeforeFail,onFail,onSuccess".split(","), function(i, name) {
|
|
|
|
// configuration
|
|
if ($.isFunction(conf[name])) {
|
|
$(self).bind(name, conf[name]);
|
|
}
|
|
|
|
// API methods
|
|
self[name] = function(fn) {
|
|
if (fn) { $(self).bind(name, fn); }
|
|
return self;
|
|
};
|
|
});
|
|
|
|
|
|
// form validation
|
|
if (conf.formEvent) {
|
|
form.bind(conf.formEvent + ".V", function(e) {
|
|
if (!self.checkValidity(null, e)) {
|
|
return e.preventDefault();
|
|
}
|
|
});
|
|
}
|
|
|
|
// form reset
|
|
form.bind("reset.V", function() {
|
|
self.reset();
|
|
});
|
|
|
|
// disable browser's default validation mechanism
|
|
if (inputs[0] && inputs[0].validity) {
|
|
inputs.each(function() {
|
|
this.oninvalid = function() {
|
|
return false;
|
|
};
|
|
});
|
|
}
|
|
|
|
// Web Forms 2.0 compatibility
|
|
if (form[0]) {
|
|
form[0].checkValidity = self.checkValidity;
|
|
}
|
|
|
|
// input validation
|
|
if (conf.inputEvent) {
|
|
inputs.bind(conf.inputEvent + ".V", function(e) {
|
|
self.checkValidity($(this), e);
|
|
});
|
|
}
|
|
|
|
// checkboxes, selects and radios are checked separately
|
|
inputs.filter(":checkbox, select").filter("[required]").bind("change.V", function(e) {
|
|
var el = $(this);
|
|
if (this.checked || (el.is("select") && $(this).val())) {
|
|
effects[conf.effect][1].call(self, el, e);
|
|
}
|
|
});
|
|
|
|
var radios = inputs.filter(":radio").change(function(e) {
|
|
self.checkValidity(radios, e);
|
|
});
|
|
|
|
// reposition tooltips when window is resized
|
|
$(window).resize(function() {
|
|
self.reflow();
|
|
});
|
|
}
|
|
|
|
|
|
// jQuery plugin initialization
|
|
$.fn.validator = function(conf) {
|
|
|
|
var instance = this.data("validator");
|
|
|
|
// destroy existing instance
|
|
if (instance) {
|
|
instance.destroy();
|
|
this.removeData("validator");
|
|
}
|
|
|
|
// configuration
|
|
conf = $.extend(true, {}, v.conf, conf);
|
|
|
|
// selector is a form
|
|
if (this.is("form")) {
|
|
return this.each(function() {
|
|
var form = $(this);
|
|
instance = new Validator(form.find(":input"), form, conf);
|
|
form.data("validator", instance);
|
|
});
|
|
|
|
} else {
|
|
instance = new Validator(this, this.eq(0).closest("form"), conf);
|
|
return this.data("validator", instance);
|
|
}
|
|
|
|
};
|
|
|
|
})(jQuery);
|
|
|
|
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 Overlay - Overlay base. Extend it.
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/overlay/
|
|
*
|
|
* Since: March 2008
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
|
|
// static constructs
|
|
$.tools = $.tools || {version: '1.2.5'};
|
|
|
|
$.tools.overlay = {
|
|
|
|
addEffect: function(name, loadFn, closeFn) {
|
|
effects[name] = [loadFn, closeFn];
|
|
},
|
|
|
|
conf: {
|
|
close: null,
|
|
closeOnClick: true,
|
|
closeOnEsc: true,
|
|
closeSpeed: 'fast',
|
|
effect: 'default',
|
|
|
|
// since 1.2. fixed positioning not supported by IE6
|
|
fixed: !$.browser.msie || $.browser.version > 6,
|
|
|
|
left: 'center',
|
|
load: false, // 1.2
|
|
mask: null,
|
|
oneInstance: true,
|
|
speed: 'normal',
|
|
target: null, // target element to be overlayed. by default taken from [rel]
|
|
top: '10%'
|
|
}
|
|
};
|
|
|
|
|
|
var instances = [], effects = {};
|
|
|
|
// the default effect. nice and easy!
|
|
$.tools.overlay.addEffect('default',
|
|
|
|
/*
|
|
onLoad/onClose functions must be called otherwise none of the
|
|
user supplied callback methods won't be called
|
|
*/
|
|
function(pos, onLoad) {
|
|
|
|
var conf = this.getConf(),
|
|
w = $(window);
|
|
|
|
if (!conf.fixed) {
|
|
pos.top += w.scrollTop();
|
|
pos.left += w.scrollLeft();
|
|
}
|
|
|
|
pos.position = conf.fixed ? 'fixed' : 'absolute';
|
|
this.getOverlay().css(pos).fadeIn(conf.speed, onLoad);
|
|
|
|
}, function(onClose) {
|
|
this.getOverlay().fadeOut(this.getConf().closeSpeed, onClose);
|
|
}
|
|
);
|
|
|
|
|
|
function Overlay(trigger, conf) {
|
|
|
|
// private variables
|
|
var self = this,
|
|
fire = trigger.add(self),
|
|
w = $(window),
|
|
closers,
|
|
overlay,
|
|
opened,
|
|
maskConf = $.tools.expose && (conf.mask || conf.expose),
|
|
uid = Math.random().toString().slice(10);
|
|
|
|
|
|
// mask configuration
|
|
if (maskConf) {
|
|
if (typeof maskConf == 'string') { maskConf = {color: maskConf}; }
|
|
maskConf.closeOnClick = maskConf.closeOnEsc = false;
|
|
}
|
|
|
|
// get overlay and triggerr
|
|
var jq = conf.target || trigger.attr("rel");
|
|
overlay = jq ? $(jq) : null || trigger;
|
|
|
|
// overlay not found. cannot continue
|
|
if (!overlay.length) { throw "Could not find Overlay: " + jq; }
|
|
|
|
// trigger's click event
|
|
if (trigger && trigger.index(overlay) == -1) {
|
|
trigger.click(function(e) {
|
|
self.load(e);
|
|
return e.preventDefault();
|
|
});
|
|
}
|
|
|
|
// API methods
|
|
$.extend(self, {
|
|
|
|
load: function(e) {
|
|
|
|
// can be opened only once
|
|
if (self.isOpened()) { return self; }
|
|
|
|
// find the effect
|
|
var eff = effects[conf.effect];
|
|
if (!eff) { throw "Overlay: cannot find effect : \"" + conf.effect + "\""; }
|
|
|
|
// close other instances?
|
|
if (conf.oneInstance) {
|
|
$.each(instances, function() {
|
|
this.close(e);
|
|
});
|
|
}
|
|
|
|
// onBeforeLoad
|
|
e = e || $.Event();
|
|
e.type = "onBeforeLoad";
|
|
fire.trigger(e);
|
|
if (e.isDefaultPrevented()) { return self; }
|
|
|
|
// opened
|
|
opened = true;
|
|
|
|
// possible mask effect
|
|
if (maskConf) { $(overlay).expose(maskConf); }
|
|
|
|
// position & dimensions
|
|
var top = conf.top,
|
|
left = conf.left,
|
|
oWidth = overlay.outerWidth({margin:true}),
|
|
oHeight = overlay.outerHeight({margin:true});
|
|
|
|
if (typeof top == 'string') {
|
|
top = top == 'center' ? Math.max((w.height() - oHeight) / 2, 0) :
|
|
parseInt(top, 10) / 100 * w.height();
|
|
}
|
|
|
|
if (left == 'center') { left = Math.max((w.width() - oWidth) / 2, 0); }
|
|
|
|
|
|
// load effect
|
|
eff[0].call(self, {top: top, left: left}, function() {
|
|
if (opened) {
|
|
e.type = "onLoad";
|
|
fire.trigger(e);
|
|
}
|
|
});
|
|
|
|
// mask.click closes overlay
|
|
if (maskConf && conf.closeOnClick) {
|
|
$.mask.getMask().one("click", self.close);
|
|
}
|
|
|
|
// when window is clicked outside overlay, we close
|
|
if (conf.closeOnClick) {
|
|
$(document).bind("click." + uid, function(e) {
|
|
if (!$(e.target).parents(overlay).length) {
|
|
self.close(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
// keyboard::escape
|
|
if (conf.closeOnEsc) {
|
|
|
|
// one callback is enough if multiple instances are loaded simultaneously
|
|
$(document).bind("keydown." + uid, function(e) {
|
|
if (e.keyCode == 27) {
|
|
self.close(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
return self;
|
|
},
|
|
|
|
close: function(e) {
|
|
|
|
if (!self.isOpened()) { return self; }
|
|
|
|
e = e || $.Event();
|
|
e.type = "onBeforeClose";
|
|
fire.trigger(e);
|
|
if (e.isDefaultPrevented()) { return; }
|
|
|
|
opened = false;
|
|
|
|
// close effect
|
|
effects[conf.effect][1].call(self, function() {
|
|
e.type = "onClose";
|
|
fire.trigger(e);
|
|
});
|
|
|
|
// unbind the keyboard / clicking actions
|
|
$(document).unbind("click." + uid).unbind("keydown." + uid);
|
|
|
|
if (maskConf) {
|
|
$.mask.close();
|
|
}
|
|
|
|
return self;
|
|
},
|
|
|
|
getOverlay: function() {
|
|
return overlay;
|
|
},
|
|
|
|
getTrigger: function() {
|
|
return trigger;
|
|
},
|
|
|
|
getClosers: function() {
|
|
return closers;
|
|
},
|
|
|
|
isOpened: function() {
|
|
return opened;
|
|
},
|
|
|
|
// manipulate start, finish and speeds
|
|
getConf: function() {
|
|
return conf;
|
|
}
|
|
|
|
});
|
|
|
|
// callbacks
|
|
$.each("onBeforeLoad,onStart,onLoad,onBeforeClose,onClose".split(","), function(i, name) {
|
|
|
|
// configuration
|
|
if ($.isFunction(conf[name])) {
|
|
$(self).bind(name, conf[name]);
|
|
}
|
|
|
|
// API
|
|
self[name] = function(fn) {
|
|
if (fn) { $(self).bind(name, fn); }
|
|
return self;
|
|
};
|
|
});
|
|
|
|
// close button
|
|
closers = overlay.find(conf.close || ".close");
|
|
|
|
if (!closers.length && !conf.close) {
|
|
closers = $('<a class="close"></a>');
|
|
overlay.prepend(closers);
|
|
}
|
|
|
|
closers.click(function(e) {
|
|
self.close(e);
|
|
});
|
|
|
|
// autoload
|
|
if (conf.load) { self.load(); }
|
|
|
|
}
|
|
|
|
// jQuery plugin initialization
|
|
$.fn.overlay = function(conf) {
|
|
|
|
// already constructed --> return API
|
|
var el = this.data("overlay");
|
|
if (el) { return el; }
|
|
|
|
if ($.isFunction(conf)) {
|
|
conf = {onBeforeLoad: conf};
|
|
}
|
|
|
|
conf = $.extend(true, {}, $.tools.overlay.conf, conf);
|
|
|
|
this.each(function() {
|
|
el = new Overlay($(this), conf);
|
|
instances.push(el);
|
|
$(this).data("overlay", el);
|
|
});
|
|
|
|
return conf.api ? el: this;
|
|
};
|
|
|
|
})(jQuery);
|
|
|
|
/**
|
|
* @license
|
|
* jQuery Tools 1.2.5 / Overlay Apple effect.
|
|
*
|
|
* NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
|
|
*
|
|
* http://flowplayer.org/tools/overlay/apple.html
|
|
*
|
|
* Since: July 2009
|
|
* Date: Thu May 15 10:43:37 CEST 2014
|
|
*/
|
|
(function($) {
|
|
|
|
// version number
|
|
var t = $.tools.overlay,
|
|
w = $(window);
|
|
|
|
// extend global configuragion with effect specific defaults
|
|
$.extend(t.conf, {
|
|
start: {
|
|
top: null,
|
|
left: null
|
|
},
|
|
|
|
fadeInSpeed: 'fast',
|
|
zIndex: 9999
|
|
});
|
|
|
|
// utility function
|
|
function getPosition(el) {
|
|
var p = el.offset();
|
|
return {
|
|
top: p.top + el.height() / 2,
|
|
left: p.left + el.width() / 2
|
|
};
|
|
}
|
|
|
|
//{{{ load
|
|
|
|
var loadEffect = function(pos, onLoad) {
|
|
|
|
var overlay = this.getOverlay(),
|
|
conf = this.getConf(),
|
|
trigger = this.getTrigger(),
|
|
self = this,
|
|
oWidth = overlay.outerWidth({margin:true}),
|
|
img = overlay.data("img"),
|
|
position = conf.fixed ? 'fixed' : 'absolute';
|
|
|
|
|
|
// growing image is required.
|
|
if (!img) {
|
|
var bg = overlay.css("backgroundImage");
|
|
|
|
if (!bg) {
|
|
throw "background-image CSS property not set for overlay";
|
|
}
|
|
|
|
// url("bg.jpg") --> bg.jpg
|
|
bg = bg.slice(bg.indexOf("(") + 1, bg.indexOf(")")).replace(/\"/g, "");
|
|
overlay.css("backgroundImage", "none");
|
|
|
|
img = $('<img src="' + bg + '"/>');
|
|
img.css({border:0, display:'none'}).width(oWidth);
|
|
$('body').append(img);
|
|
overlay.data("img", img);
|
|
}
|
|
|
|
// initial top & left
|
|
var itop = conf.start.top || Math.round(w.height() / 2),
|
|
ileft = conf.start.left || Math.round(w.width() / 2);
|
|
|
|
if (trigger) {
|
|
var p = getPosition(trigger);
|
|
itop = p.top;
|
|
ileft = p.left;
|
|
}
|
|
|
|
// put overlay into final position
|
|
if (conf.fixed) {
|
|
itop -= w.scrollTop();
|
|
ileft -= w.scrollLeft();
|
|
} else {
|
|
pos.top += w.scrollTop();
|
|
pos.left += w.scrollLeft();
|
|
}
|
|
|
|
// initialize background image and make it visible
|
|
img.css({
|
|
position: 'absolute',
|
|
top: itop,
|
|
left: ileft,
|
|
width: 0,
|
|
zIndex: conf.zIndex
|
|
}).show();
|
|
|
|
pos.position = position;
|
|
overlay.css(pos);
|
|
|
|
// begin growing
|
|
img.animate({
|
|
top: overlay.css("top"),
|
|
left: overlay.css("left"),
|
|
width: oWidth}, conf.speed, function() {
|
|
|
|
// set close button and content over the image
|
|
overlay.css("zIndex", conf.zIndex + 1).fadeIn(conf.fadeInSpeed, function() {
|
|
|
|
if (self.isOpened() && !$(this).index(overlay)) {
|
|
onLoad.call();
|
|
} else {
|
|
overlay.hide();
|
|
}
|
|
});
|
|
|
|
}).css("position", position);
|
|
|
|
};
|
|
//}}}
|
|
|
|
|
|
var closeEffect = function(onClose) {
|
|
|
|
// variables
|
|
var overlay = this.getOverlay().hide(),
|
|
conf = this.getConf(),
|
|
trigger = this.getTrigger(),
|
|
img = overlay.data("img"),
|
|
|
|
css = {
|
|
top: conf.start.top,
|
|
left: conf.start.left,
|
|
width: 0
|
|
};
|
|
|
|
// trigger position
|
|
if (trigger) { $.extend(css, getPosition(trigger)); }
|
|
|
|
|
|
// change from fixed to absolute position
|
|
if (conf.fixed) {
|
|
img.css({position: 'absolute'})
|
|
.animate({ top: "+=" + w.scrollTop(), left: "+=" + w.scrollLeft()}, 0);
|
|
}
|
|
|
|
// shrink image
|
|
img.animate(css, conf.closeSpeed, onClose);
|
|
};
|
|
|
|
|
|
// add overlay effect
|
|
t.addEffect("apple", loadEffect, closeEffect);
|
|
|
|
})(jQuery);
|
|
|