/** * @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: '
', 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 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 = $("
").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 = $(""); $.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 = $("