/* * jlorhQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ * * Uses the built in easing capabilities added In jlorhQuery 1.1 * to offer multiple easing options * * TERMS OF USE - jlorhQuery Easing * * Open source under the BSD License. * * Copyright © 2008 George McGinley Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * Neither the name of the author nor the names of contributors may be used to endorse * or promote products derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * */ // t: current time, b: begInnIng value, c: change In value, d: duration jlorhQuery.easing['jswing'] = jlorhQuery.easing['swing']; jlorhQuery.extend( jlorhQuery.easing, { def: 'easeOutQuad', swing: function (x, t, b, c, d) { //alert(jlorhQuery.easing.default); return jlorhQuery.easing[jlorhQuery.easing.def](x, t, b, c, d); }, easeInQuad: function (x, t, b, c, d) { return c*(t/=d)*t + b; }, easeOutQuad: function (x, t, b, c, d) { return -c *(t/=d)*(t-2) + b; }, easeInOutQuad: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t + b; return -c/2 * ((--t)*(t-2) - 1) + b; }, easeInCubic: function (x, t, b, c, d) { return c*(t/=d)*t*t + b; }, easeOutCubic: function (x, t, b, c, d) { return c*((t=t/d-1)*t*t + 1) + b; }, easeInOutCubic: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t*t + b; return c/2*((t-=2)*t*t + 2) + b; }, easeInQuart: function (x, t, b, c, d) { return c*(t/=d)*t*t*t + b; }, easeOutQuart: function (x, t, b, c, d) { return -c * ((t=t/d-1)*t*t*t - 1) + b; }, easeInOutQuart: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t*t*t + b; return -c/2 * ((t-=2)*t*t*t - 2) + b; }, easeInQuint: function (x, t, b, c, d) { return c*(t/=d)*t*t*t*t + b; }, easeOutQuint: function (x, t, b, c, d) { return c*((t=t/d-1)*t*t*t*t + 1) + b; }, easeInOutQuint: function (x, t, b, c, d) { if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b; return c/2*((t-=2)*t*t*t*t + 2) + b; }, easeInSine: function (x, t, b, c, d) { return -c * Math.cos(t/d * (Math.PI/2)) + c + b; }, easeOutSine: function (x, t, b, c, d) { return c * Math.sin(t/d * (Math.PI/2)) + b; }, easeInOutSine: function (x, t, b, c, d) { return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b; }, easeInExpo: function (x, t, b, c, d) { return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; }, easeOutExpo: function (x, t, b, c, d) { return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; }, easeInOutExpo: function (x, t, b, c, d) { if (t==0) return b; if (t==d) return b+c; if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; }, easeInCirc: function (x, t, b, c, d) { return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b; }, easeOutCirc: function (x, t, b, c, d) { return c * Math.sqrt(1 - (t=t/d-1)*t) + b; }, easeInOutCirc: function (x, t, b, c, d) { if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b; return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; }, easeInElastic: function (x, t, b, c, d) { var s=1.70158;var p=0;var a=c; if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; }, easeOutElastic: function (x, t, b, c, d) { var s=1.70158;var p=0;var a=c; if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; }, easeInOutElastic: function (x, t, b, c, d) { var s=1.70158;var p=0;var a=c; if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5); if (a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; }, easeInBack: function (x, t, b, c, d, s) { if (s == undefined) s = 1.70158; return c*(t/=d)*t*((s+1)*t - s) + b; }, easeOutBack: function (x, t, b, c, d, s) { if (s == undefined) s = 1.70158; return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; }, easeInOutBack: function (x, t, b, c, d, s) { if (s == undefined) s = 1.70158; if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; }, easeInBounce: function (x, t, b, c, d) { return c - jlorhQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b; }, easeOutBounce: function (x, t, b, c, d) { if ((t/=d) < (1/2.75)) { return c*(7.5625*t*t) + b; } else if (t < (2/2.75)) { return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; } else if (t < (2.5/2.75)) { return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; } else { return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; } }, easeInOutBounce: function (x, t, b, c, d) { if (t < d/2) return jlorhQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b; return jlorhQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b; } }); /* * * TERMS OF USE - EASING EQUATIONS * * Open source under the BSD License. * * Copyright © 2001 Robert Penner * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * Neither the name of the author nor the names of contributors may be used to endorse * or promote products derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * *//* * FancyBox - simple and fancy jQuery plugin * Examples and documentation at: http://fancy.klade.lv/ * Version: 1.2.1 (13/03/2009) * Copyright (c) 2009 Janis Skarnelis * Licensed under the MIT License: http://en.wikipedia.org/wiki/MIT_License * Requires: jQuery v1.3+ */ ;(function(jlorhQuery) { jlorhQuery.fn.fixPNG = function() { return this.each(function () { var image = jlorhQuery(this).css('backgroundImage'); if (image.match(/^url\(["']?(.*\.png)["']?\)jlorhQuery/i)) { image = RegExp.$1; jlorhQuery(this).css({ 'backgroundImage': 'none', 'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=" + (jlorhQuery(this).css('backgroundRepeat') == 'no-repeat' ? 'crop' : 'scale') + ", src='" + image + "')" }).each(function () { var position = jlorhQuery(this).css('position'); if (position != 'absolute' && position != 'relative') jlorhQuery(this).css('position', 'relative'); }); } }); }; var elem, opts, busy = false, imagePreloader = new Image, loadingTimer, loadingFrame = 1, imageRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i; var isIE = (jlorhQuery.browser.msie && parseInt(jlorhQuery.browser.version.substr(0,1)) < 8); jlorhQuery.fn.fancybox = function(settings) { settings = jlorhQuery.extend({}, jlorhQuery.fn.fancybox.defaults, settings); var matchedGroup = this; function _initialize() { elem = this; opts = settings; _start(); return false; }; function _start() { if (busy) return; if (jlorhQuery.isFunction(opts.callbackOnStart)) { opts.callbackOnStart(); } opts.itemArray = []; opts.itemCurrent = 0; if (settings.itemArray.length > 0) { opts.itemArray = settings.itemArray; } else { var item = {}; if (!elem.rel || elem.rel == '') { var item = {href: elem.href, title: elem.title}; if (jlorhQuery(elem).children("img:first").length) { item.orig = jlorhQuery(elem).children("img:first"); } opts.itemArray.push( item ); } else { var subGroup = jlorhQuery(matchedGroup).filter("a[rel=" + elem.rel + "]"); var item = {}; for (var i = 0; i < subGroup.length; i++) { item = {href: subGroup[i].href, title: subGroup[i].title}; if (jlorhQuery(subGroup[i]).children("img:first").length) { item.orig = jlorhQuery(subGroup[i]).children("img:first"); } opts.itemArray.push( item ); } while ( opts.itemArray[ opts.itemCurrent ].href != elem.href ) { opts.itemCurrent++; } } } if (opts.overlayShow) { if (isIE) { jlorhQuery('embed, object, select').css('visibility', 'hidden'); } jlorhQuery("#fancy_overlay").css('opacity', opts.overlayOpacity).show(); } _change_item(); }; function _change_item() { jlorhQuery("#fancy_right, #fancy_left, #fancy_close, #fancy_title").hide(); var href = opts.itemArray[ opts.itemCurrent ].href; //alert(href); if (href.match(/#/)) { var target = window.location.href.split('#')[0]; target = href.replace(target, ''); target = target.substr(target.indexOf('#')); _set_content('
' + jlorhQuery(target).html() + '
', opts.frameWidth, opts.frameHeight); } else // if (href.match(imageRegExp)) { imagePreloader = new Image; imagePreloader.src = href; if (imagePreloader.complete) { _proceed_image(); } else { jlorhQuery.fn.fancybox.showLoading(); jlorhQuery(imagePreloader).unbind().bind('load', function() { jlorhQuery(".fancy_loading").hide(); _proceed_image(); }); } } /* else if (href.match("iframe") || elem.className.indexOf("iframe") >= 0) { _set_content('', opts.frameWidth, opts.frameHeight); } else { jlorhQuery.get(href, function(data) { _set_content( '
' + data + '
', opts.frameWidth, opts.frameHeight ); }); } //*/ }; function _proceed_image() { if (opts.imageScale) { var w = jlorhQuery.fn.fancybox.getViewport(); var r = Math.min(Math.min(w[0] - 36, imagePreloader.width) / imagePreloader.width, Math.min(w[1] - 60, imagePreloader.height) / imagePreloader.height); var width = Math.round(r * imagePreloader.width); var height = Math.round(r * imagePreloader.height); } else { var width = imagePreloader.width; var height = imagePreloader.height; } _set_content('', width, height); }; function _preload_neighbor_images() { if ((opts.itemArray.length -1) > opts.itemCurrent) { var href = opts.itemArray[opts.itemCurrent + 1].href; if (href.match(imageRegExp)) { objNext = new Image(); objNext.src = href; } } if (opts.itemCurrent > 0) { var href = opts.itemArray[opts.itemCurrent -1].href; if (href.match(imageRegExp)) { objNext = new Image(); objNext.src = href; } } }; function _set_content(value, width, height) { busy = true; var pad = opts.padding; if (isIE) { jlorhQuery("#fancy_content")[0].style.removeExpression("height"); jlorhQuery("#fancy_content")[0].style.removeExpression("width"); } if (pad > 0) { width += pad * 2; height += pad * 2; jlorhQuery("#fancy_content").css({ 'top' : pad + 'px', 'right' : pad + 'px', 'bottom' : pad + 'px', 'left' : pad + 'px', 'width' : 'auto', 'height' : 'auto' }); if (isIE) { jlorhQuery("#fancy_content")[0].style.setExpression('height', '(this.parentNode.clientHeight - 20)'); jlorhQuery("#fancy_content")[0].style.setExpression('width', '(this.parentNode.clientWidth - 20)'); } } else { jlorhQuery("#fancy_content").css({ 'top' : 0, 'right' : 0, 'bottom' : 0, 'left' : 0, 'width' : '100%', 'height' : '100%' }); } if (jlorhQuery("#fancy_outer").is(":visible") && width == jlorhQuery("#fancy_outer").width() && height == jlorhQuery("#fancy_outer").height()) { jlorhQuery("#fancy_content").fadeOut("fast", function() { jlorhQuery("#fancy_content").empty().append(jlorhQuery(value)).fadeIn("normal", function() { _finish(); }); }); return; } var w = jlorhQuery.fn.fancybox.getViewport(); var itemLeft = (width + 36) > w[0] ? w[2] : (w[2] + Math.round((w[0] - width - 36) / 2)); var itemTop = (height + 50) > w[1] ? w[3] : (w[3] + Math.round((w[1] - height - 50) / 2)); var itemOpts = { 'left': itemLeft, 'top': itemTop, 'width': width + 'px', 'height': height + 'px' }; if (jlorhQuery("#fancy_outer").is(":visible")) { jlorhQuery("#fancy_content").fadeOut("normal", function() { jlorhQuery("#fancy_content").empty(); jlorhQuery("#fancy_outer").animate(itemOpts, opts.zoomSpeedChange, opts.easingChange, function() { jlorhQuery("#fancy_content").append(jlorhQuery(value)).fadeIn("normal", function() { _finish(); }); }); }); } else { if (opts.zoomSpeedIn > 0 && opts.itemArray[opts.itemCurrent].orig !== undefined) { jlorhQuery("#fancy_content").empty().append(jlorhQuery(value)); var orig_item = opts.itemArray[opts.itemCurrent].orig; var orig_pos = jlorhQuery.fn.fancybox.getPosition(orig_item); jlorhQuery("#fancy_outer").css({ 'left': (orig_pos.left - 18) + 'px', 'top': (orig_pos.top - 18) + 'px', 'width': jlorhQuery(orig_item).width(), 'height': jlorhQuery(orig_item).height() }); if (opts.zoomOpacity) { itemOpts.opacity = 'show'; } jlorhQuery("#fancy_outer").animate(itemOpts, opts.zoomSpeedIn, opts.easingIn, function() { _finish(); }); } else { jlorhQuery("#fancy_content").hide().empty().append(jlorhQuery(value)).show(); jlorhQuery("#fancy_outer").css(itemOpts).fadeIn("normal", function() { _finish(); }); } } }; function _set_navigation() { if (opts.itemCurrent != 0) { jlorhQuery("#fancy_left, #fancy_left_ico").unbind().bind("click", function(e) { e.stopPropagation(); opts.itemCurrent--; _change_item(); return false; }); jlorhQuery("#fancy_left").show(); } if (opts.itemCurrent != ( opts.itemArray.length -1)) { jlorhQuery("#fancy_right, #fancy_right_ico").unbind().bind("click", function(e) { e.stopPropagation(); opts.itemCurrent++; _change_item(); return false; }); jlorhQuery("#fancy_right").show(); } }; function _finish() { _set_navigation(); _preload_neighbor_images(); jlorhQuery(document).keydown(function(e) { if (e.keyCode == 27) { jlorhQuery.fn.fancybox.close(); jlorhQuery(document).unbind("keydown"); } else if(e.keyCode == 37 && opts.itemCurrent != 0) { opts.itemCurrent--; _change_item(); jlorhQuery(document).unbind("keydown"); } else if(e.keyCode == 39 && opts.itemCurrent != (opts.itemArray.length - 1)) { opts.itemCurrent++; _change_item(); jlorhQuery(document).unbind("keydown"); } }); if (opts.centerOnScroll) { jlorhQuery(window).bind("resize scroll", jlorhQuery.fn.fancybox.scrollBox); } else { jlorhQuery("div#fancy_outer").css("position", "absolute"); } if (opts.hideOnContentClick) { jlorhQuery("#fancy_wrap").click(jlorhQuery.fn.fancybox.close); } jlorhQuery("#fancy_overlay, #fancy_close").bind("click", jlorhQuery.fn.fancybox.close); jlorhQuery("#fancy_close").show(); if (opts.itemArray[ opts.itemCurrent ].title !== undefined && opts.itemArray[ opts.itemCurrent ].title.length > 0) { jlorhQuery('#fancy_title div').html(opts.itemArray[ opts.itemCurrent ].title); jlorhQuery('#fancy_title').show(); } if (opts.overlayShow && isIE) { jlorhQuery('embed, object, select', jlorhQuery('#fancy_content')).css('visibility', 'visible'); } if (jlorhQuery.isFunction(opts.callbackOnShow)) { opts.callbackOnShow(); } busy = false; }; return this.unbind('click').click(_initialize); }; jlorhQuery.fn.fancybox.scrollBox = function() { var pos = jlorhQuery.fn.fancybox.getViewport(); jlorhQuery("#fancy_outer").css('left', ((jlorhQuery("#fancy_outer").width() + 36) > pos[0] ? pos[2] : pos[2] + Math.round((pos[0] - jlorhQuery("#fancy_outer").width() - 36) / 2))); jlorhQuery("#fancy_outer").css('top', ((jlorhQuery("#fancy_outer").height() + 50) > pos[1] ? pos[3] : pos[3] + Math.round((pos[1] - jlorhQuery("#fancy_outer").height() - 50) / 2))); }; jlorhQuery.fn.fancybox.getNumeric = function(el, prop) { return parseInt(jlorhQuery.curCSS(el.jquery?el[0]:el,prop,true))||0; }; jlorhQuery.fn.fancybox.getPosition = function(el) { var pos = el.offset(); pos.top += jlorhQuery.fn.fancybox.getNumeric(el, 'paddingTop'); pos.top += jlorhQuery.fn.fancybox.getNumeric(el, 'borderTopWidth'); pos.left += jlorhQuery.fn.fancybox.getNumeric(el, 'paddingLeft'); pos.left += jlorhQuery.fn.fancybox.getNumeric(el, 'borderLeftWidth'); return pos; }; jlorhQuery.fn.fancybox.showIframe = function() { jlorhQuery(".fancy_loading").hide(); jlorhQuery("#fancy_frame").show(); }; jlorhQuery.fn.fancybox.getViewport = function() { return [jlorhQuery(window).width(), jlorhQuery(window).height(), jlorhQuery(document).scrollLeft(), jlorhQuery(document).scrollTop() ]; }; jlorhQuery.fn.fancybox.animateLoading = function() { if (!jlorhQuery("#fancy_loading").is(':visible')){ clearInterval(loadingTimer); return; } jlorhQuery("#fancy_loading > div").css('top', (loadingFrame * -40) + 'px'); loadingFrame = (loadingFrame + 1) % 12; }; jlorhQuery.fn.fancybox.showLoading = function() { clearInterval(loadingTimer); var pos = jlorhQuery.fn.fancybox.getViewport(); jlorhQuery("#fancy_loading").css({'left': ((pos[0] - 40) / 2 + pos[2]), 'top': ((pos[1] - 40) / 2 + pos[3])}).show(); jlorhQuery("#fancy_loading").bind('click', jlorhQuery.fn.fancybox.close); loadingTimer = setInterval(jlorhQuery.fn.fancybox.animateLoading, 66); }; jlorhQuery.fn.fancybox.close = function() { busy = true; jlorhQuery(imagePreloader).unbind(); jlorhQuery("#fancy_overlay, #fancy_close").unbind(); if (opts.hideOnContentClick) { jlorhQuery("#fancy_wrap").unbind(); } jlorhQuery("#fancy_close, .fancy_loading, #fancy_left, #fancy_right, #fancy_title").hide(); if (opts.centerOnScroll) { jlorhQuery(window).unbind("resize scroll"); } __cleanup = function() { jlorhQuery("#fancy_overlay, #fancy_outer").hide(); if (opts.centerOnScroll) { jlorhQuery(window).unbind("resize scroll"); } if (isIE) { jlorhQuery('embed, object, select').css('visibility', 'visible'); } if (jlorhQuery.isFunction(opts.callbackOnClose)) { opts.callbackOnClose(); } busy = false; }; if (jlorhQuery("#fancy_outer").is(":visible") !== false) { if (opts.zoomSpeedOut > 0 && opts.itemArray[opts.itemCurrent].orig !== undefined) { var orig_item = opts.itemArray[opts.itemCurrent].orig; var orig_pos = jlorhQuery.fn.fancybox.getPosition(orig_item); var itemOpts = { 'left': (orig_pos.left - 18) + 'px', 'top': (orig_pos.top - 18) + 'px', 'width': jlorhQuery(orig_item).width(), 'height': jlorhQuery(orig_item).height() }; if (opts.zoomOpacity) { itemOpts.opacity = 'hide'; } jlorhQuery("#fancy_outer").stop(false, true).animate(itemOpts, opts.zoomSpeedOut, opts.easingOut, __cleanup); } else { jlorhQuery("#fancy_outer").stop(false, true).fadeOut("fast", __cleanup); } } else { __cleanup(); } return false; }; jlorhQuery.fn.fancybox.build = function() { var html = ''; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; html += ''; html += '
'; html += '
'; html += '
'; html += '
'; html += '
'; jlorhQuery(html).appendTo("body"); jlorhQuery('
').appendTo('#fancy_title'); if (isIE) { jlorhQuery("#fancy_inner").prepend(''); jlorhQuery("#fancy_close, .fancy_bg, .fancy_title, .fancy_ico").fixPNG(); } }; jlorhQuery.fn.fancybox.defaults = { padding : 10, imageScale : true, zoomOpacity : false, zoomSpeedIn : 0, zoomSpeedOut : 0, zoomSpeedChange : 300, easingIn : 'swing', easingOut : 'swing', easingChange : 'swing', frameWidth : 425, frameHeight : 355, overlayShow : true, overlayOpacity : 0.3, hideOnContentClick : true, centerOnScroll : true, itemArray : [], callbackOnStart : null, callbackOnShow : null, callbackOnClose : null }; jlorhQuery(document).ready(function() { jlorhQuery.fn.fancybox.build(); }); })(jlorhQuery);/** * $lhj.simpletip 1.3.1. A simple tooltip plugin * * Copyright (c) 2009 Craig Thompson * http://craigsworks.com * * Licensed under GPLv3 * http://www.opensource.org/licenses/gpl-3.0.html * * Launch : February 2009 * Version : 1.3.1 * Released: February 5, 2009 - 11:04am */ (function($){ function Simpletip(elem, conf) { var self = this; elem = $lhj(elem); elemParent = $lhj(document.getElementsByTagName("body")[0]); var tooltip = $lhj(document.createElement('div')) .addClass(conf.baseClass) .addClass( (conf.fixed) ? conf.fixedClass : '' ) .addClass( (conf.persistent) ? conf.persistentClass : '' ) .html(conf.content) .appendTo(elemParent); if(!conf.hidden) tooltip.show(); else tooltip.hide(); if(!conf.persistent) { elem.hover( function(event){ self.show(event) }, function(){ self.hide() } ); if(!conf.fixed) { elem.mousemove( function(event){ if(tooltip.css('display') !== 'none') self.updatePos(event); }); }; } else { elem.click(function(event) { if(event.target === elem.get(0)) { if(tooltip.css('display') !== 'none') self.hide(); else self.show(); }; }); $lhj(window).mousedown(function(event) { if(tooltip.css('display') !== 'none') { var check = (conf.focus) ? $lhj(event.target).parents('.tooltip').andSelf().filter(function(){ return this === tooltip.get(0) }).length : 0; if(check === 0) self.hide(); }; }); }; $lhj.extend(self, { getVersion: function() { return [1, 2, 0]; }, getParent: function() { return elem; }, getTooltip: function() { return tooltip; }, getPos: function() { return tooltip.offset(); }, setPos: function(posX, posY) { var elemPos = elem.offset(); if(typeof posX == 'string') posX = parseInt(posX) + elemPos.left; if(typeof posY == 'string') posY = parseInt(posY) + elemPos.top; // alert('posX: ' + posX + ', posY: ' + posY); tooltip.css({ left: posX, top: posY }); return self; }, show: function(event) { conf.onBeforeShow.call(self); self.updatePos( (conf.fixed) ? null : event ); switch(conf.showEffect) { case 'fade': tooltip.fadeIn(conf.showTime); break; case 'slide': tooltip.slideDown(conf.showTime, self.updatePos); break; case 'custom': conf.showCustom.call(tooltip, conf.showTime); break; default: case 'none': tooltip.show(); break; }; tooltip.addClass(conf.activeClass); conf.onShow.call(self); return self; }, hide: function() { conf.onBeforeHide.call(self); switch(conf.hideEffect) { case 'fade': tooltip.fadeOut(conf.hideTime); break; case 'slide': tooltip.slideUp(conf.hideTime); break; case 'custom': conf.hideCustom.call(tooltip, conf.hideTime); break; default: case 'none': tooltip.hide(); break; }; tooltip.removeClass(conf.activeClass); conf.onHide.call(self); return self; }, update: function(content) { tooltip.html(content); conf.content = content; return self; }, load: function(uri, data) { conf.beforeContentLoad.call(self); tooltip.load(uri, data, function(){ conf.onContentLoad.call(self); }); return self; }, boundryCheck: function(posX, posY) { var newX = posX + tooltip.outerWidth(); var newY = posY + tooltip.outerHeight(); var windowWidth = $lhj(window).width() + $lhj(window).scrollLeft(); var windowHeight = $lhj(window).height() + $lhj(window).scrollTop(); return [(newX >= windowWidth), (newY >= windowHeight)]; }, updatePos: function(event) { var tooltipWidth = tooltip.outerWidth(); var tooltipHeight = tooltip.outerHeight(); if(!event && conf.fixed) { if(conf.position.constructor == Array) { posX = parseInt(conf.position[0]); posY = parseInt(conf.position[1]); } else if($lhj(conf.position).attr('nodeType') === 1) { var offset = $lhj(conf.position).offset(); posX = offset.left; posY = offset.top; } else { var elemPos = elem.offset(); var elemWidth = elem.outerWidth(); var elemHeight = elem.outerHeight(); switch(conf.position) { case 'top': var posX = elemPos.left - (tooltipWidth / 2) + (elemWidth / 2); var posY = elemPos.top - tooltipHeight; break; case 'bottom': var posX = elemPos.left - (tooltipWidth / 2) + (elemWidth / 2); var posY = elemPos.top + elemHeight; break; case 'left': var posX = elemPos.left - tooltipWidth; var posY = elemPos.top - (tooltipHeight / 2) + (elemHeight / 2); break; case 'right': var posX = elemPos.left + elemWidth; var posY = elemPos.top - (tooltipHeight / 2) + (elemHeight / 2); break; default: case 'default': var posX = (elemWidth / 2) + elemPos.left + 20; var posY = elemPos.top; break; }; }; } else { var posX = event.pageX; var posY = event.pageY; }; if(typeof conf.position != 'object') { posX = posX + conf.offset[0]; posY = posY + conf.offset[1]; if(conf.boundryCheck) { var overflow = self.boundryCheck(posX, posY); if(overflow[0]) posX = posX - (tooltipWidth / 2) - (2 * conf.offset[0]); if(overflow[1]) posY = posY - (tooltipHeight / 2) - (2 * conf.offset[1]); } } else { if(typeof conf.position[0] == "string") posX = String(posX); if(typeof conf.position[1] == "string") posY = String(posY); }; self.setPos(posX, posY); return self; } }); }; $lhj.fn.simpletip = function(conf) { // Check if a simpletip is already present var api = $lhj(this).eq(typeof conf == 'number' ? conf : 0).data("simpletip"); if(api) return api; // Default configuration var defaultConf = { // Basics content: 'A simple tooltip', persistent: false, focus: false, hidden: true, // Positioning position: 'default', offset: [0, 0], boundryCheck: true, fixed: true, // Effects showEffect: 'fade', showTime: 150, showCustom: null, hideEffect: 'fade', hideTime: 150, hideCustom: null, // Selectors and classes baseClass: 'tooltip', activeClass: 'active', fixedClass: 'fixed', persistentClass: 'persistent', focusClass: 'focus', // Callbacks onBeforeShow: function(){}, onShow: function(){}, onBeforeHide: function(){}, onHide: function(){}, beforeContentLoad: function(){}, onContentLoad: function(){} }; $lhj.extend(defaultConf, conf); this.each(function() { var el = new Simpletip($lhj(this), defaultConf); $lhj(this).data("simpletip", el); }); return this; }; })(); /* * jQuery RTE plugin 0.5.1 - create a rich text form for Mozilla, Opera, Safari and Internet Explorer * * Copyright (c) 2009 Batiste Bieler * Distributed under the GPL Licenses. * Distributed under the The MIT License. * * Modified by LikeOrHate.com. */ // define the rte light plugin (function($) { $.fn.rte = function(options) { $.fn.rte.html = function(iframe) { return iframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML; }; $.fn.rte.defaults = { media_url: "", content_css_url: "", dot_net_button_class: null, max_height: 350 }; // build main options before element iteration var opts = $.extend($.fn.rte.defaults, options); // iterate and construct the RTEs return this.each( function() { var textarea = $(this); var iframe; var element_id = textarea.attr("id"); // enable design mode function enableDesignMode() { var content = textarea.val(); // Mozilla needs this to display caret if($.trim(content)=='') { content = '
'; } // already created? show/hide if(iframe) { textarea.hide(); $(iframe).contents().find("body").html(content); $(iframe).show(); $("#toolbar-" + element_id).remove(); textarea.before(toolbar()); return true; } // for compatibility reasons, need to be created this way iframe = document.createElement("iframe"); iframe.frameBorder=0; iframe.frameMargin=0; iframe.framePadding=0; iframe.height=200; if(textarea.attr('class')) iframe.className = textarea.attr('class'); if(textarea.attr('id')) iframe.id = element_id; if(textarea.attr('name')) iframe.title = textarea.attr('name'); textarea.after(iframe); var css = ""; if(opts.content_css_url) { css = ""; } var doc = ""+css+""+content+""; tryEnableDesignMode(doc, function() { $("#toolbar-" + element_id).remove(); textarea.before(toolbar()); // hide textarea textarea.hide(); }); } function tryEnableDesignMode(doc, callback) { if(!iframe) { return false; } try { iframe.contentWindow.document.open(); iframe.contentWindow.document.write(doc); iframe.contentWindow.document.close(); } catch(error) { //console.log(error); } if (document.contentEditable) { iframe.contentWindow.document.designMode = "On"; callback(); return true; } else if (document.designMode != null) { try { iframe.contentWindow.document.designMode = "on"; callback(); return true; } catch (error) { //console.log(error); } } setTimeout(function(){tryEnableDesignMode(doc, callback)}, 500); return false; } function disableDesignMode(submit) { var content = $(iframe).contents().find("body").html(); if($(iframe).is(":visible")) { textarea.val(content); } if(submit != true) { textarea.show(); $(iframe).hide(); } } // create toolbar and bind events to it's elements function toolbar() { var tb = $("
\

\ \

\

\ bold\ italic\

\

\ unordered list\ link\ image\

"); $('select', tb).change(function(){ var index = this.selectedIndex; if( index!=0 ) { var selected = this.options[index].value; formatText("formatblock", '<'+selected+'>'); } }); $('.bold', tb).click(function(){ formatText('bold');return false; }); $('.italic', tb).click(function(){ formatText('italic');return false; }); $('.unorderedlist', tb).click(function(){ formatText('insertunorderedlist');return false; }); $('.link', tb).click(function(){ var p=prompt("URL:"); if(p) formatText('CreateLink', p); return false; }); $('.image', tb).click(function(){ var p=prompt("image URL:"); if(p) formatText('InsertImage', p); return false; }); $('.disable', tb).click(function() { disableDesignMode(); var edm = $('Enable design mode'); tb.empty().append(edm); edm.click(function(e){ e.preventDefault(); enableDesignMode(); // remove, for good measure $(this).remove(); }); return false; }); // .NET compatability if(opts.dot_net_button_class) { var dot_net_button = $(iframe).parents('form').find(opts.dot_net_button_class); dot_net_button.click(function() { disableDesignMode(true); }); // Regular forms } else { $(iframe).parents('form').submit(function(){ disableDesignMode(true); }); } var iframeDoc = $(iframe.contentWindow.document); var select = $('select', tb)[0]; iframeDoc.mouseup(function(){ setSelectedType(getSelectionElement(), select); return true; }); iframeDoc.keyup(function() { setSelectedType(getSelectionElement(), select); var body = $('body', iframeDoc); if(body.scrollTop() > 0) { var iframe_height = parseInt(iframe.style['height']) if(isNaN(iframe_height)) iframe_height = 0; var h = Math.min(opts.max_height, iframe_height+body.scrollTop()) + 'px'; iframe.style['height'] = h; } return true; }); return tb; }; function formatText(command, option) { iframe.contentWindow.focus(); try{ iframe.contentWindow.document.execCommand(command, false, option); }catch(e){ //console.log(e) } iframe.contentWindow.focus(); }; function setSelectedType(node, select) { while(node.parentNode) { var nName = node.nodeName.toLowerCase(); for(var i=0;i= 5.5) && (document.body.filters)) // if (true) { for(var i=0; i"; img.outerHTML = strNewHTML; i = i-1; } } } } // Configure tooltips. loh.setTooltips(); }); ///////////// /// Functions for comment handling /// // Callback for reply comments. loh.renderCommentsReplyCallback = function (html) {loh.doRenderCommentsCallback (html, "div.comment_holder", "div.comment_children_root", true);} loh.renderCommentsParentCallback = function (html) {loh.doRenderCommentsCallback (html, "div.comment_holder", "div.comment_parent_root", true);} // Callback for root comments. loh.renderCommentsCallback = function (html) { loh.clearComments2expandParam(); loh.doRenderCommentsCallback (html, "div.comment_holder", "div.comment_children_root", false); } // Callback for comments (both types). Do the async work. loh.doRenderCommentsCallback = function (html, strClsCommentsHolder, strClsCommRoot, bReplyIncoming) { var root = $lhj.find(strClsCommentsHolder)[0]; if (bReplyIncoming) { // Get parent id var idxParentid = html.indexOf('parentid="'); if (idxParentid == -1) { alert('if (idxParentid == -1)'); return; } idxParentid += 'parentid="'.length; var idxParentid2 = html.indexOf('"', idxParentid + 1); var parentId = html.substring(idxParentid, idxParentid2); // Find parent div var jrootComment = $lhj(document.getElementById('commentitem_' + parentId)); var jchildRoot = jrootComment.find(strClsCommRoot); jchildRoot.css('display', 'block'); jchildRoot.html(html); loh.execJS(jchildRoot[0]); /* var divItem = document.createElement('div'); rootComment.appendChild(divItem); divItem.innerHTML = html; loh.execJS(divItem); //*/ } else { root.innerHTML = html; loh.execJS(root); } loh.hideLoadingSign(); // Configure tooltips. loh.setTooltips(); } /** * Hooks all listeners for a comment (divItem). * id: comment id. * parent: parent comment id, if it's a reply. */ loh.comments_hookListeners = function(divItem, id, parent) { // hook vote on comment. $lhj(divItem).find('a.comment_vote').click(function (ev) { var jthis = $lhj(this); var voteType = jthis.attr('votetype'); var attrs = 'id[]=' + id + '&rate=' + voteType; var posMouse = loh.findPos(ev.target); var signId = loh.showLoadingSign(posMouse, null, true); loh.loh_sngltn.requestJsonData(loh.loh_domain + "/rest/thing/rate/", attrs, 'JSONXML', loh.voteOnCommentCallback, loh.loh_sngltn, [signId, jthis]); return false; }); // hook vote on comment's author. $lhj(divItem).find('a.author_vote').click(function (ev) { var jthis = $lhj(this); var jparent = jthis.parents('div.jcomment'); var userId = jparent.attr('data-user'); var voteType = jthis.attr('votetype'); //alert('userId: ' + userId); var attrs = 'id[]=' + userId + '&rate=' + voteType; var posMouse = loh.findPos(ev.target); var signId = loh.showLoadingSign(posMouse, null, true); loh.loh_sngltn.requestJsonData(loh.loh_domain + "/rest/thing/rate/", attrs, 'JSONXML', loh.voteOnCommentCallback, loh.loh_sngltn, [signId, jthis]); return false; }); // hook reply button. $lhj(divItem).find('a.comment_reply').click(function (ev) { var joriComment = $lhj($lhj(this)[0]).parents('.jcomment'); var lhjForm = $lhj('#comments_form'); if (lhjForm.length > 0) { var commentId = joriComment.attr('data-comment'); lhjForm.find('input[name="parent"]').attr('value', commentId); var oriTitle = $lhj($lhj(joriComment[0].parentNode).find('h3.summary')[0]).text(); lhjForm.find('div.replytitle').css('display', 'block').text(loh.loh_sngltn.strings['commentreplytitle'] + oriTitle); // move div into place var comdiv = $lhj('div#commentform'); joriComment[0].appendChild(comdiv[0]); // don't use lhj here. comdiv.find('input[name="cancel"]').css('display', 'inline'); comdiv.find('div.commentbody').html(''); comdiv.find('.loh_html_editor').rte({ media_url: loh.loh_staticdomain + "/images/rte-jquery/"}); } return false; }); // hook abuse button. $lhj(divItem).find('a.comment_abuse').click(function (ev) { var posMouse = loh.findPos(ev.target); // TODO: move to $lhj.offset var signId = loh.showLoadingSign(posMouse, null, true); var jthis = $lhj(this); var joriComment = $lhj(jthis[0].parentNode.parentNode.parentNode.parentNode); var commentId = joriComment.attr('data-comment'); //alert('commentId: ' + commentId); var attrs = 'thing=' + commentId; loh.loh_sngltn.requestJsonData(loh.loh_domain + "/rest/abuse/report", attrs, 'JSONXML', loh.loh_sngltn.simpleCommandCallback, loh.loh_sngltn, [signId, posMouse]); return false; }); // hook view parent comment button (not used yet). $lhj(divItem).find('a.comment_parent_watch').click(function (ev) { $lhj(this).css({display: 'none'}); $lhj($lhj(this)[0].parentNode).find('a.comment_parent_hide').css({display: 'inline'}); var joriComment = $lhj(this).parents('div.jcomment'); var thingId = joriComment.attr('data-thing'); var commentId = joriComment.attr('data-comment'); var attrs = 'id[]=' + thingId + '&child=' + commentId + loh.loh_load_comments_attrs_base + '&mode=parent'; var posMouse = loh.findPosFromEvent(ev); var signId = loh.showLoadingSign(posMouse, null, true); loh.loh_sngltn.requestJsonData(loh.loh_domain + loh.loh_load_comments_rest_url, attrs, 'JSONHTML', loh.renderCommentsParentCallback, loh.loh_sngltn, [signId]); return false; }); // hook hide parent comment button (not used yet). $lhj(divItem).find('a.comment_parent_hide').css({display: 'none'}).click(function (ev) { $lhj(this).css({display: 'none'}); $lhj($lhj(this)[0].parentNode).find('a.comment_parent_watch').css({display: 'inline'}); var jchildRoot = $lhj($lhj(this)[0].parentNode).find('div.comment_parent_root'); jchildRoot.css('display', 'none'); jchildRoot.html(''); return false; }); // hook view comment's replies button. $lhj(divItem).find('a.comment_replies_read').click(function (ev) { var posMouse = loh.findPosFromEvent(ev); return loh.expandReplies($lhj(this), posMouse); }); // hook hide comment's replies button. $lhj(divItem).find('a.comment_replies_hide').css({display: 'none'}).click(function (ev) { var jthis = $lhj(this); jthis.css({display: 'none'}); $lhj(jthis[0].parentNode).find('a.comment_replies_read').css({display: 'inline'}); var jchildRoot = $lhj(jthis[0].parentNode.parentNode).find('div.comment_children_root'); jchildRoot.css('display', 'none'); jchildRoot.html(''); var joriComment = jthis.parents('div.jcomment'); var commentId = joriComment.attr('data-comment'); loh.removeComments2expandParam(commentId); return false; }); } loh.comments_hookMainListeners = function () { // Hook validation to the form $lhj('#comments_form').submit(function() { var jthis = $lhj(this); if ($lhj('#recaptcha_response_field').length > 0 && ($lhj('#recaptcha_response_field').val() == '' || $lhj('#recaptcha_response_field').val() == null)) { alert('Fill the validation field! Type what you see on the image!'); return false; } if ($lhj('#message').val() == '' || $lhj('#message').val() == null) { alert('Please comment something before submitting the comment!'); return false; } return true; }); } // function that expands replies. loh.expandReplies = function (jreplyBtn, posMouse) { jreplyBtn.css({display: 'none'}); $lhj(jreplyBtn[0].parentNode).find('a.comment_replies_hide').css({display: 'inline'}); var joriComment = jreplyBtn.parents('div.jcomment'); var thingId = joriComment.attr('data-thing'); var commentId = joriComment.attr('data-comment'); var attrs = 'id[]=' + thingId + '&parent=' + commentId + loh.loh_load_comments_attrs_base + '&mode=replies'; var signId = -1; if (posMouse != null) signId = loh.showLoadingSign(posMouse, null, true); loh.loh_sngltn.requestJsonData(loh.loh_domain + loh.loh_load_comments_rest_url, attrs, 'JSONHTML', loh.renderCommentsReplyCallback, loh.loh_sngltn, [signId]); loh.addComments2expandParam(commentId); return false; }; // callback for voting actions. For now, reload comments. loh.voteOnCommentCallback = function(xml, arrayParams) { var signId = arrayParams[0]; var jthis = arrayParams[1]; var joriComment = jthis.parents('div.jcomment'); var jRoot = joriComment.parents('#comment_holder'); var jPagRoot = $lhj(jRoot.find('div.pagination')[0]); var thingId = joriComment.attr('data-thing'); var comments2expand = loh.getComments2expandParam(); var begin = jRoot.attr('data-begin'); if (begin == null || !(begin >= 0)) begin = 0; var total = jPagRoot.attr('data-total'); loh.loh_sngltn.requestJsonData(loh.loh_domain + loh.loh_load_comments_rest_url, 'id[]=' + thingId + loh.loh_load_comments_attrs_base_nopag + '&mode=rootonelevel&begin=' + begin + '&total=' + total + '&' + comments2expand, 'JSONHTML', loh.renderCommentsCallback, null, null); }; // functions that does pagination for replies. loh.repliesPaginationListener = function(event) { var jPagRoot = $lhj(this).parents('div.pagination'); var joriComment = jPagRoot.parents('div.jcomment'); var jRoot = joriComment.parents('#comment_holder'); var begin = $lhj(this).attr('data-begin'); var total = jPagRoot.attr('data-total'); var thingId = joriComment.attr('data-thing'); var commentId = joriComment.attr('data-comment'); var attrs = 'id[]=' + thingId + '&parent=' + commentId + loh.loh_load_comments_attrs_base_nopag + '&mode=replies&begin=' + begin + '&total=' + total; //alert('attrs: ' + attrs); var posMouse = loh.findPosFromEvent(ev); var signId = loh.showLoadingSign(posMouse, null, true); loh.loh_sngltn.requestJsonData(loh.loh_domain + loh.loh_load_comments_rest_url, attrs, 'JSONHTML', loh.renderCommentsReplyCallback, loh.loh_sngltn, [signId]); return false; }; // functions that does pagination for top comments. loh.rootPaginationListener = function(event) { var jPagRoot = $lhj(this).parents('div.pagination'); var jRoot = jPagRoot.parents('#comment_holder'); var begin = $lhj(this).attr('data-begin'); jRoot.attr('data-begin', begin); var total = jPagRoot.attr('data-total'); var thingId = jRoot.attr('data-thing'); var attrs = 'id[]=' + thingId + '&parent=-1' + loh.loh_load_comments_attrs_base_nopag + '&mode=replies&begin=' + begin + '&total=' + total; //alert('attrs: ' + attrs); var posMouse = loh.findPosFromEvent(event); var signId = loh.showLoadingSign(posMouse, null, true); loh.loh_sngltn.requestJsonData(loh.loh_domain + loh.loh_load_comments_rest_url, attrs, 'JSONHTML', loh.renderCommentsCallback, loh.loh_sngltn, [signId]); return false; }; loh.arrayCommentsExpanded = new Array(); loh.mapCommentsExpanded = new Object(); loh.addComments2expandParam = function(commId) { loh.arrayCommentsExpanded.push(commId); loh.mapCommentsExpanded[commId] = 1; } loh.removeComments2expandParam = function(commId) { loh.mapCommentsExpanded[commId] = 0; } loh.clearComments2expandParam = function() { loh.arrayCommentsExpanded = new Array(); loh.mapCommentsExpanded = new Object(); } loh.getComments2expandParam = function() { var str = ''; for (var i = 0; i < loh.arrayCommentsExpanded.length; i++) { var commId = loh.arrayCommentsExpanded[i]; if (loh.mapCommentsExpanded[commId] == 1) { if (str.length > 0) str += ';'; str += commId; } } return 'commentsexpand=' + str; } /** This file should hold the majority of scripts that are used (only) on the main site. */ /** Sets everything that must be set when the page is loaded! */ $lhj(document).ready(function() { ///// // Configure the tabs of the main thing being shown. //* $lhj('div.tabsd').each(function (i) { loh.makeTabs({ root: $lhj(this), tabList: 'tablist', tabSel: 'tabsel', tabUnsel: 'tab', tabMore: null, tabMoreWnd: null, onShow: function(event, toShow, root) { var idThing = root.attr('thingid'); var aTabPane = root.find('#' + toShow.getAttribute('pane')); aTabPane.css('display', 'block'); // PQP: cache tabs/don't reload // we use tabs in some other places as well if (idThing) { if (toShow.getAttribute('pane') == 'tab_links') { var isLoaded = aTabPane.attr('data-loaded'); if (isLoaded == null || isLoaded != 'true') { loh.loh_sngltn.requestJsonData(loh.loh_domain + '/rest/thing/trackback/', 'id[]=' + idThing + '&subformat=XHTML', 'JSONXML', function (xml) { var htmlOut = ''; var err = false; var realXml = $lhj(xml); if (err) htmlOut = '

' + loh.loh_sngltn.strings['trck_notfound'] + '

'; else { var countLinks = realXml.find('ul').attr('count'); if (countLinks == 0) htmlOut = '

' + loh.loh_sngltn.strings['trck_notfound'] + '

'; else htmlOut = '

' + loh.loh_sngltn.strings['trck_found_tit'] + countLinks + '

' + loh.xml2str(realXml.find('ul')[0]); } root.find('div.' + toShow.getAttribute('pane')).html(htmlOut); aTabPane.attr('data-loaded', 'true'); }); } } else if (toShow.getAttribute('pane') == 'tab_trackback' || toShow.getAttribute('pane') == 'tab_overview' || toShow.getAttribute('pane') == 'tab_media' || toShow.getAttribute('pane') == 'tab_information') { var isLoaded = aTabPane.attr('data-loaded'); if (isLoaded == null || isLoaded != 'true') { var func = toShow.getAttribute('pane').substring(4); $lhj(aTabPane).load(loh.loh_domain + '/rest/thing/' + func + '/?' + 'id=' + idThing + '&responseType=HTML'); aTabPane.attr('data-loaded', 'true'); } } else if (toShow.getAttribute('pane') == 'tab_youtube') { // TODO: for some reason this plugin reloads page. document.location = event.target.href; } else { var isLoaded = aTabPane.attr('data-loaded'); if (isLoaded == null || isLoaded != 'true') { // default behaviour var func = toShow.getAttribute('pane').substring(4); // alert('func: ' + func); // var fncFnc = function (json) {aTabPane.html(json);} // loh.loh_sngltn.requestJsonData(loh.loh_domain + '/rest/thing/' + func + '/', 'id[]=' + idThing, 'JSONTEXT', fncFnc); $lhj(aTabPane).load(loh.loh_domain + '/rest/plugin/' + func + '/?' + 'id[]=' + idThing + '&responseType=HTML'); aTabPane.attr('data-loaded', 'true'); } } } }, onHide: function(event, toHide, root) { var aTabPane = root.find('#' + toHide.getAttribute('pane')); aTabPane.css('display', 'none'); } }); }); //*/ // Considers the selected tab. // $lhj('.tablist')[0].tabSel = $lhj('.tabsel')[0]; /** Configure the thumbs of the smallthings. */ $lhj('div.loh_smallthing').find('a.thingthumb').hover(function () { // In hover }, function () { // Out hover } ).click(function (ev) { /** When clicked, a thumbnail shows the image viewer. First, it must recover the id of the thing that the smallthing is showing and the id of the media that the thumb represents. Then this info is sent to loh to retrieve */ var jthis = $lhj(this); var idThing = jthis.attr('thingid'); var idMedia = jthis.attr('mediaid'); var attrs = 'id[]=' + idThing + '&pagesize=7&firstload=1&media=' + idMedia; var posMouse = loh.findPos(ev.target); posMouse[0] += 100; posMouse[1] += 100; var signId = loh.showLoadingSign(posMouse, null, true); setTimeout(function () { loh.loh_sngltn.requestJsonData(loh.loh_domain + "/rest/thing/media/", attrs, 'JSONXML', loh_thumbFirstLoadCallback, loh.loh_sngltn, [signId]); }, 10); return false; }); /** Configure the vote bars */ $lhj('a.aclickvote').hover(function () { // In hover, show vote text var textel = $lhj(this).find('span.loh_votebarvotes'); var percent = textel.text(); $lhj(this).attr('percent', percent); textel.text('Vote!'); }, function () { // Out hover var textel = $lhj(this).find('span.loh_votebarvotes'); textel.text($lhj(this).attr('percent')); } ).click(loh.loh_sngltn.voteOnThingOnSite); $lhj('a.aclickvote').click(loh.loh_sngltn.voteOnThingOnSite); // ajax vote callback /* prepare the image viewers */ $lhj('div.mediamain').each(function () { var thingId = $lhj(this).attr('data-thing'); var mediaFirst = $lhj(this).attr('data-media-first')*1; var mediaLast = $lhj(this).attr('data-media-last'); loh_mediasel_init(this, thingId); //loh_mediasel_init($lhj('.thumbselector')[0], ); if (mediaFirst != -1) loh_mediasel_hookListeners($lhj(this).find('div.thumbselector'), thingId, mediaFirst, mediaLast); }); }); /** * Casts a vote on the thing. * * @param ev The element causing the event * @return */ loh.core.prototype.voteOnThingOnSiteReal = function (ev) { loh.hideLoadingSign(); var posMouse = loh.findPos(ev.target); // TODO: move to $lhj.offset // get the target. var blib = $lhj(loh.getEvtTarget(ev)); if (!blib.hasClass('aclickvote')) blib = $lhj(blib).parents('a.aclickvote'); // get the vote type. var voteType = ''; switch (blib.attr('rev')) { case 'vote-for': voteType = 'like'; break; case 'vote-abstain': voteType = 'whatever'; break; case 'vote-against': voteType = 'hate'; break; default: return false; } var id = blib.attr('thingid'); var attrs = 'id[]=' + id + '&label[]=&rate=' + voteType + '&type=POST'; // ok, vote. var signId = loh.showLoadingSign(posMouse, null, true); loh.loh_sngltn.requestJsonData(loh.loh_domain + "/rest/thing/rate/", attrs, 'JSONXML', loh.loh_sngltn.voteOnThingOnSiteCallback, loh.loh_sngltn, [id, blib[0], signId, posMouse]); // clean any vote check signs var basediv = $lhj("div.lohthing" + id); basediv.find(".iconuservote").css("display", "none"); // smallthing basediv.find(".uservote").css("visibility", "hidden"); // bigthing basediv.find(".uservote." + voteType).css("visibility", "visible"); // bigthing // and mark the vote var el = basediv.find("a.vote-" + voteType); el.find(".iconuservote").css("display", "block"); // smallthing } /** * Callback for vote. First test if the user is logged in. If not, invite him * to login or register. * * @param ev * @return */ loh.core.prototype.voteOnThingOnSite = function (ev) { var posMouse = loh.findPos(ev.target); // TODO: move to $lhj.offset if (!loh.loginbarshown && !loh.ctrl.isauth) { // not logged in, first time we reach here. Invite him. loh.loginbarshown = true; var tagThingParent = $lhj(this).parents(".ratingparent"); var posMouse = loh.findPos(tagThingParent[0]); // get the target. var blib = $lhj(loh.getEvtTarget(ev)); if (!blib.hasClass('aclickvote')) blib = $lhj(blib).parents('a.aclickvote'); // get the vote type. var voteType = ''; switch (blib.attr('rev')) { case 'vote-for': voteType = 'like'; break; case 'vote-abstain': voteType = 'whatever'; break; case 'vote-against': voteType = 'hate'; break; default: return false; } var thingId = blib.attr('thingid'); var voteSignId = loh.showLoadingSign(posMouse, '
' + loh.loh_sngltn.strings['wouldlikelogin'] + '

' + '' + '' + '' + '' + loh.loh_sngltn.strings['yesplease'] + '' + loh.loh_sngltn.strings['nothanks'] + '
', false, 0, '115px', '210px'); setTimeout(function () { $lhj('#formasklogin').find('a.btn_submit').click(function (event) { $lhj('#formasklogin').submit(); return false; }); $lhj('#formasklogin').find('a.btn_cancel').click(function (event) { loh.loh_sngltn.voteOnThingOnSiteReal(ev); return false; }); }, 100); } else loh.loh_sngltn.voteOnThingOnSiteReal(ev); return false; }; /** * Callback for ajax vote http request. Handles both big and small things. */ loh.core.prototype.voteOnThingOnSiteCallback = function(xml, arrayParams) { var status = $lhj(xml).find('likeorhate'); if (!status || status.attr('status') != 'true') { // shit happens. Handle it. var signId = arrayParams[2]; var posMouse = arrayParams[3]; loh.hideLoadingSign(signId); // TODO: translation with loh[strings] var errSignId = loh.showLoadingSign(posMouse, '
' + loh.loh_sngltn.strings['error_on_rate_thing'] + '
' + loh.loh_sngltn.strings['error_on_rate_thing_det1'] + '

' + loh.loh_sngltn.strings['error_ack_lbl'] + '', false, 0, '115px', '230px'); setTimeout(function () { $lhj('#formvoteerror_btn').click(function (event) { loh.hideLoadingSign(); return false; }); }, 100); return; } // yipee, vote worked! var thingid = arrayParams[0]; var tagThingLink = arrayParams[1]; // get all things with this thingid. Note we use classes instead of ids // because there may be more than one instance of this thing on the page. var tagThingParents = $lhj('div.lohthing' + thingid); if (!tagThingParents.length) { var signId = arrayParams[2]; loh.hideLoadingSign(signId); return; } // parse the html. var thingXml = $lhj(xml).find("thing"); var like = thingXml.find("like").text(); var whatever = thingXml.find("whatever").text(); var hate = thingXml.find("hate").text(); var plike = thingXml.find("like").attr('percent'); var pwhatever = thingXml.find("whatever").attr('percent'); var phate = thingXml.find("hate").attr('percent'); var wLike = thingXml.find("like").attr('barwidth'); var wWhatever = thingXml.find("whatever").attr('barwidth'); var wHate = thingXml.find("hate").attr('barwidth'); var score = parseFloat(thingXml.find("average").text()); if (score.toFixed) score = score.toFixed(4); // for each thingbox, update it. for (var i = 0; i < tagThingParents.length; i++) { var tagThingParent = $lhj(tagThingParents[i]); var jthingBarLike = tagThingParent.find('div.vote-like'); // rating bars if (jthingBarLike.length) { jthingBarLike.find('img.centerimg').css({width: wLike + 'px'}); jthingBarLike.find('span.loh_votebarvotes').text(plike + '%'); jthingBarLike.attr('percent', plike + '%'); var jthingBarWhatever = tagThingParent.find('div.vote-whatever'); jthingBarWhatever.find('img.centerimg').css({width: wWhatever + 'px'}); jthingBarWhatever.find('span.loh_votebarvotes').text(pwhatever + '%'); jthingBarWhatever.attr('percent', pwhatever + '%'); var jthingBarHate = tagThingParent.find('div.vote-hate'); jthingBarHate.find('img.centerimg').css({width: wHate + 'px'}); jthingBarHate.find('span.loh_votebarvotes').text(phate + '%'); jthingBarHate.attr('percent', phate + '%'); } var thingLike = tagThingParent.find('div.number.like'); // fix vote count if (thingLike.length) { //thingLike = thingLike[0]; thingLike.find('span.votes').text(like); thingLike.find('span.percent').text(plike + '%'); var thingWhatever = tagThingParent.find('div.number.whatever'); thingWhatever.find('span.votes').text(whatever); thingWhatever.find('span.percent').text(pwhatever + '%'); var thingHate = tagThingParent.find('div.number.hate'); thingHate.find('span.votes').text(hate); thingHate.find('span.percent').text(phate + '%'); tagThingParent.find('span.score').text(score); // fix bars tagThingParent.find("div.vtlike").css('width', plike + '%'); tagThingParent.find("div.vtwhatever").css('width', pwhatever +'%'); tagThingParent.find("div.vthate").css('width', phate + '%'); } } var signId = arrayParams[2]; loh.hideLoadingSign(signId); }; /** * Callback for ajax simple commands. */ loh.core.prototype.simpleCommandCallback = function(xml, arrayParams) { var status = $lhj(xml).find('likeorhate'); var answer = $lhj(xml).find('answer'); var signId = arrayParams[0]; var posMouse = arrayParams[1]; loh.hideLoadingSign(signId); if ( (!status || status.attr('status') != 'true') || (!answer || answer.attr('status') != 'ok') ) { // TODO: translation with loh[strings] var errSignId = loh.showLoadingSign(posMouse, '
' + loh.loh_sngltn.strings['error_onop'] + '
' + answer.text() + '

' + loh.loh_sngltn.strings['error_ack_lbl'] + '', false, 0, '115px', '230px'); setTimeout(function () { $lhj('operror_btn').click(function (event) {loh.hideLoadingSign(); return false;}); }, 100); return; } }; ////////////////////////////////// /////////// Image viewer stuff ////////////////////////////////// /** Structure. The image viewer has three levels of image view: - thumbnail. There are some of then in the top, and the user can navigate to see more of them using next and prev arrows. - bigger images. It's shown only one at a time, after the user click in a thumb. - full view image (in a fancybox). It's shown after the user click on a bigger image. */ /** Init the imageviewer structure, setting effets to the thumbnails holder, adding event listeners to the img tags that will hold the thumbs and the bigger image view, and preparing the bigger image holders to open the full image viewer (fancybox). */ function loh_mediasel_init(divHolder, idThing) { var jdivHolder = $lhj(divHolder); // Adds opacity effect to the thumbs holder when the mouse hover them. jdivHolder.find('div.thingthumb').each(function() { if ($lhj(this)[0].filters) $lhj(this).css('filter', 'alpha(opacity=65)'); else $lhj(this).css('opacity', '.65'); }).mouseover(function (ev) { if ($lhj(this)[0].filters) $lhj(this)[0].filters.alpha.opacity=100; else $lhj(this).css('opacity', '1'); }).mouseout(function (ev) { if ($lhj(this)[0].filters) $lhj(this)[0].filters.alpha.opacity=65; else $lhj(this).css('opacity', '.65'); }); var mediaholder = jdivHolder.find("div.mediaholder"); var mediamedia = mediaholder.find("div.mediamedia"); var imgTags = mediamedia.find("img"); /** Prepare the two bigger image holder to deal with new images being showed after the user clicked in one of the thumbnails. When one of the img tags finishes loading a new image, it must hide the other img tag (if the other is visible) and show itself. To conclude the transition effect, the size of the whole image is adjusted. */ imgTags.bind("load", function (ev) { var bIsShown = mediaholder.attr('data-imvisible'); mediaholder.attr('data-imvisible', 'true'); var dataWhosshown = mediaholder.attr('data-whosshown') == 1? 1 : 0; mediaholder.attr('data-whosshown', (dataWhosshown + 1)%2); if (!bIsShown) { $lhj(this).css('display', 'block'); mediaholder.slideDown(700, function() {}); mediaholder.attr('data-whosshown', '1'); } else { $lhj(imgTags[dataWhosshown]).fadeOut(700); $lhj(this).fadeIn(700); $lhj(this).css('width', ''); $lhj(this).css('height', ''); } var realWidth = $lhj(this).width(); var realHeight = $lhj(this).height(); if (realWidth > 325 || realHeight > 300) { if (realWidth/325 > realHeight/300) $lhj(this).css('width', '325px'); else $lhj(this).css('height', '300px'); } // Considerates some room for the description! var calcHeight = $lhj(this).height() + 2 + 20; mediamedia.animate({height: calcHeight + 'px'}, 700); loh.hideLoadingSign(); }); /** Deals with images 404 ... */ imgTags.bind("error", function (ev) { loh.onErrorExists = true; // TODO: translation with loh[strings] var errSignId = loh.modLoadingSign(-1, '
' + loh.loh_sngltn.strings['error_img_notfound'] + '

' + 'Ok ...' + '', false, null, '70px', '180px'); setTimeout(function () { $lhj('#formimgerror_btn').click(function (event) { loh.hideLoadingSign(); return false; }); }, 300); setTimeout(function () { loh.hideLoadingSign(); }, 6000); return; }); // Sets the link tag that surounds the img tags of the bigger images // to open a fancybow when on of the bigger images is clicked. var aTags = mediamedia.find('a'); aTags.fancybox(); var jthumbholder_btn = jdivHolder.find('a.thumbholder_btn'); jthumbholder_btn.click(function (ev) { var jthis = $lhj(this); var posMouse = loh.findPos(ev.target); posMouse[1] += 200; var signId = loh.showLoadingSign(posMouse, null, true); // Hides the loading message after a while in case a 404 occurs during // the image loading process on browsers that doesn't implement // onerror event ... setTimeout(function() {if (!loh.onErrorExists)loh.hideLoadingSign(signId);}, 6000); var mediaholder = jdivHolder.find('div.mediaholder'); var dataWhosshown = ((mediaholder.attr('data-whosshown') == 1? 1 : 0) + 1)%2; var jthumb2show = jthis.find("img"); //alert('jthumb2show.attr(alt): ' + jthumb2show.attr('alt')); var imgTags = mediaholder.find("img"); $lhj(imgTags[dataWhosshown] ).attr('src', jthis.attr('url') ).attr('alt', jthumb2show.attr('alt') ).attr('title', jthumb2show.attr('title')); var imgTitleTag = mediaholder.find('div.imgtitle'); //alert('imgTitleTag.length: ' + imgTitleTag.length); imgTitleTag.text(jthumb2show.attr('alt')); $lhj(imgTags[dataWhosshown].parentNode).attr('href', jthis.attr('url')); return false; }); // Shows a thumb as a bigger image randomically when it first opened. var idx2click = Math.round(Math.random()*(jthumbholder_btn.length-1)); var btn2simclick = jthumbholder_btn[idx2click]; var jthumb2show = $lhj(btn2simclick).find("img"); { var mediaholder = jdivHolder.find('div.mediaholder'); var dataWhosshown = ((mediaholder.attr('data-whosshown') == 1? 1 : 0) + 1)%2; var imgTags = mediaholder.find('img'); if (imgTags.length > 0) { if ($lhj(btn2simclick).attr('url') != -1) { $lhj(imgTags[dataWhosshown]).attr('src', $lhj(btn2simclick).attr('url')); $lhj(imgTags[dataWhosshown].parentNode).attr('href', $lhj(btn2simclick).attr('url')); var imgTitleTag = mediaholder.find('div.imgtitle'); imgTitleTag.text(jthumb2show.attr('alt')); } } return false; } } /** Adds event listeners to the next and prev buttons of the image holder. */ function loh_mediasel_hookListeners(jdivHolder, idThing, idMediaFirst, idMediaLast) { jdivHolder.each(function (ev) { var root = $lhj(this); root.find('a.thumbselctrlsbtnprev').click(function (ev) { var attrs = 'id[]=' + idThing + '&media=' + idMediaFirst + '&next=0&pagesize=7'; var posMouse = loh.findPos(ev.target); posMouse[0] += 100; posMouse[1] += 100; var signId = loh.showLoadingSign(posMouse, null, true); loh.loh_sngltn.requestJsonData(loh.loh_domain + "/rest/thing/media/", attrs, 'JSONXML', loh_thumbPrevCallback, root, [signId]); return false; }); }); jdivHolder.each(function (ev) { var root = $lhj(this); root.find('a.thumbselctrlsbtnnext').click(function (ev) { var attrs = 'id[]=' + idThing + '&media=' + idMediaLast + '&next=1&pagesize=7'; var posMouse = loh.findPos(ev.target); posMouse[0] -= 150; posMouse[1] += 100; var signId = loh.showLoadingSign(posMouse, null, true); loh.loh_sngltn.requestJsonData(loh.loh_domain + "/rest/thing/media/", attrs, 'JSONXML', loh_thumbNextCallback, root, [signId]); return false; }); }); }; /** Callbacks called after the result of the click on the next and prev buttons returns from the server. */ function loh_thumbPrevCallback(xml) {loh_thumbNextPrevCallback(xml, false, $lhj(this));} function loh_thumbNextCallback(xml) {loh_thumbNextPrevCallback(xml, true, $lhj(this));} function loh_thumbNextPrevCallback(xml, nextBtn, jdivRoot, firstTime) { // var jdivHolder = jdivRoot.find('.thumbselector'); var jdivHolder = jdivRoot; var divHolder = jdivHolder[0]; if (!divHolder) {alert('divHolder: ' + divHolder);return;} var thingId = $lhj(xml).find("thing").attr('id'); var arrayMedias = $lhj(xml).find("media"); var arrayThumbs = $lhj(divHolder).find('img.thingthumb'); var thumbCount = arrayMedias.length == 7 ? 6 : arrayMedias.length; var bNext = true; var bPrev = !firstTime; if (nextBtn) bNext = arrayMedias.length == 7 ? true : false; else bPrev = (!firstTime && arrayMedias.length == 7) ? true : false; var extraAdd = (nextBtn ? 0 : (bPrev ? 1: 0)); for (var i = 5; i > (thumbCount-1); i--) $lhj(arrayThumbs[i]).css('display', 'none'); for (var i = thumbCount-1; i > -1; i--) { var thumb = arrayThumbs[i]; var athumb = thumb.parentNode; var media = arrayMedias[i + extraAdd]; var mediaId = $lhj(media).attr('id'); var linkThumb = $lhj(media).find("thumb").attr('src'); var linkImg = $lhj(media).find("image").attr('src'); var desc = $lhj(media).find("desc").text(); $lhj(athumb).css('display', 'block') .attr('href', loh.loh_domain + '/rest/thing/media?thing=' + thingId + '&media=' + mediaId) .attr('url', linkImg) .attr('mediaid', mediaId) .attr('thingid', thingId) ; $lhj(thumb).css('display', 'block') .attr('src', linkThumb) .attr('alt', desc).attr('title', desc) ; } var prevHolder = $lhj(divHolder).find('div.thumbselctrlsleft')[0]; loh.removeChildren(prevHolder); if (bPrev) prevHolder.innerHTML = ''; else prevHolder.innerHTML = ''; var nextHolder = $lhj(divHolder).find(".thumbselctrlsright")[0]; loh.removeChildren(nextHolder); if (bNext) nextHolder.innerHTML = ''; else nextHolder.innerHTML = ''; loh_mediasel_hookListeners(jdivHolder, thingId, $lhj(arrayMedias[extraAdd]).attr('id'), $lhj(arrayMedias[thumbCount - 1 + extraAdd]).attr('id')); loh.hideLoadingSign(); }; /** Callback called after the result of the click on a thumbnail of a smallthing returns from the server. */ function loh_thumbFirstLoadCallback(xml) { var myMain = $lhj('div.mediamain_smallthing'); loh_thumbNextPrevCallback(xml, true, myMain, true); loh.hideLoadingSign(); myMain.css('top', $lhj(window).scrollTop() + 300); myMain.css('left', $lhj(window).scrollLeft() + $lhj(window).width()/2 - myMain.width()/2); myMain.show(); myMain.find('div.mediamain_smallthing_close').click(function(ev) { myMain.hide(); }); myMain.jqDrag('div.mediamain_smallthing_drag'); var jthumbholder_btn = myMain.find('a.thumbholder_btn'); var btn2simclick = jthumbholder_btn[0]; var jbtn2simclick = $lhj(btn2simclick); var jthumb2show = jbtn2simclick.find("img"); var mediamain = btn2simclick.parentNode.parentNode.parentNode; { var mediaholder = $lhj(mediamain).find("div.mediaholder"); var dataWhosshown = ((mediaholder.attr('data-whosshown') == 1? 1 : 0) + 1)%2; var imgTags = mediaholder.find("img"); if (imgTags.length > 0) { $lhj(imgTags[dataWhosshown]).attr('src', jbtn2simclick.attr('url')); $lhj(imgTags[dataWhosshown].parentNode).attr('href', jbtn2simclick.attr('url')); var imgTitleTag = mediaholder.find('div.imgtitle'); imgTitleTag.text(jthumb2show.attr('alt')); } return false; } }; /* * jQuery Autocomplete plugin 1.1 * * Copyright (c) 2009 Jörn Zaefferer * * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * * PATCHED by likeorhate * * Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $ */ (function($) { $.fn.extend({ autocomplete: function(urlOrData, options) { var isUrl = typeof urlOrData == "string"; options = $.extend({}, $.Autocompleter.defaults, { url: isUrl ? urlOrData : null, data: isUrl ? null : urlOrData, delay: isUrl ? $.Autocompleter.defaults.delay : 10, max: options && !options.scroll ? 10 : 150, parse: options && options.parse ? options.parse : null }, options); // if highlight is set to false, replace it with a do-nothing function options.highlight = options.highlight || function(value) { return value; }; // if the formatMatch option is not specified, then use formatItem for backwards compatibility options.formatMatch = options.formatMatch || options.formatItem; return this.each(function() { new $.Autocompleter(this, options); }); }, result: function(handler) { return this.bind("result", handler); }, search: function(handler) { return this.trigger("search", [handler]); }, flushCache: function() { return this.trigger("flushCache"); }, setOptions: function(options){ return this.trigger("setOptions", [options]); }, unautocomplete: function() { return this.trigger("unautocomplete"); } }); $.Autocompleter = function(input, options) { var KEY = { UP: 38, DOWN: 40, DEL: 46, TAB: 9, RETURN: 13, ESC: 27, COMMA: 188, PAGEUP: 33, PAGEDOWN: 34, BACKSPACE: 8 }; // Create $ object for input element var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass); var timeout; var previousValue = ""; var cache = $.Autocompleter.Cache(options); var hasFocus = 0; var lastKeyPressCode; var config = { mouseDownOnSelect: false }; var select = $.Autocompleter.Select(options, input, selectCurrent, config); var blockSubmit; // prevent form submit in opera when selecting with return key $.browser.opera && $(input.form).bind("submit.autocomplete", function() { if (blockSubmit) { blockSubmit = false; return false; } }); // only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) { // a keypress means the input has focus // avoids issue where input had focus before the autocomplete was applied hasFocus = 1; // track last key pressed lastKeyPressCode = event.keyCode; switch(event.keyCode) { case KEY.UP: event.preventDefault(); if ( select.visible() ) { select.prev(); } else { onChange(0, true); } break; case KEY.DOWN: event.preventDefault(); if ( select.visible() ) { select.next(); } else { onChange(0, true); } break; case KEY.PAGEUP: event.preventDefault(); if ( select.visible() ) { select.pageUp(); } else { onChange(0, true); } break; case KEY.PAGEDOWN: event.preventDefault(); if ( select.visible() ) { select.pageDown(); } else { onChange(0, true); } break; // matches also semicolon case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA: case KEY.TAB: case KEY.RETURN: if( selectCurrent() ) { // stop default to prevent a form submit, Opera needs special handling event.preventDefault(); blockSubmit = true; return false; } break; case KEY.ESC: select.hide(); break; default: clearTimeout(timeout); timeout = setTimeout(onChange, options.delay); break; } }).focus(function(){ // track whether the field has focus, we shouldn't process any // results if the field no longer has focus hasFocus++; }).blur(function() { hasFocus = 0; if (!config.mouseDownOnSelect) { hideResults(); } }).click(function() { // show select when clicking in a focused field if ( hasFocus++ > 1 && !select.visible() ) { onChange(0, true); } }).bind("search", function() { // TODO why not just specifying both arguments? var fn = (arguments.length > 1) ? arguments[1] : null; function findValueCallback(q, data) { var result; if( data && data.length ) { for (var i=0; i < data.length; i++) { if( data[i].result.toLowerCase() == q.toLowerCase() ) { result = data[i]; break; } } } if( typeof fn == "function" ) fn(result); else $input.trigger("result", result && [result.data, result.value]); } $.each(trimWords($input.val()), function(i, value) { request(value, findValueCallback, findValueCallback); }); }).bind("flushCache", function() { cache.flush(); }).bind("setOptions", function() { $.extend(options, arguments[1]); // if we've updated the data, repopulate if ( "data" in arguments[1] ) cache.populate(); }).bind("unautocomplete", function() { select.unbind(); $input.unbind(); $(input.form).unbind(".autocomplete"); }); function selectCurrent() { var selected = select.selected(); if( !selected ) return false; var v = selected.result; previousValue = v; if ( options.multiple ) { var words = trimWords($input.val()); if ( words.length > 1 ) { var seperator = options.multipleSeparator.length; var cursorAt = $(input).selection().start; var wordAt, progress = 0; $.each(words, function(i, word) { progress += word.length; if (cursorAt <= progress) { wordAt = i; return false; } progress += seperator; }); words[wordAt] = v; // TODO this should set the cursor to the right position, but it gets overriden somewhere //$.Autocompleter.Selection(input, progress + seperator, progress + seperator); v = words.join( options.multipleSeparator ); } v += options.multipleSeparator; } $input.val(v); hideResultsNow(); $input.trigger("result", [selected.data, selected.value]); return true; } function onChange(crap, skipPrevCheck) { if( lastKeyPressCode == KEY.DEL ) { select.hide(); return; } var currentValue = $input.val(); if ( !skipPrevCheck && currentValue == previousValue ) return; previousValue = currentValue; currentValue = lastWord(currentValue); if ( currentValue.length >= options.minChars) { $input.addClass(options.loadingClass); if (!options.matchCase) currentValue = currentValue.toLowerCase(); request(currentValue, receiveData, hideResultsNow); } else { stopLoading(); select.hide(); } }; function trimWords(value) { if (!value) return [""]; if (!options.multiple) return [$.trim(value)]; return $.map(value.split(options.multipleSeparator), function(word) { return $.trim(value).length ? $.trim(word) : null; }); } function lastWord(value) { if ( !options.multiple ) return value; var words = trimWords(value); if (words.length == 1) return words[0]; var cursorAt = $(input).selection().start; if (cursorAt == value.length) { words = trimWords(value) } else { words = trimWords(value.replace(value.substring(cursorAt), "")); } return words[words.length - 1]; } // fills in the input box w/the first match (assumed to be the best match) // q: the term entered // sValue: the first matching result function autoFill(q, sValue){ // autofill in the complete box w/the first match as long as the user hasn't entered in more data // if the last user key pressed was backspace, don't autofill if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) { // fill in the value (keep the case the user has typed) $input.val($input.val() + sValue.substring(lastWord(previousValue).length)); // select the portion of the value not typed by the user (so the next character will erase) $(input).selection(previousValue.length, previousValue.length + sValue.length); } }; function hideResults() { clearTimeout(timeout); timeout = setTimeout(hideResultsNow, 200); }; function hideResultsNow() { var wasVisible = select.visible(); select.hide(); clearTimeout(timeout); stopLoading(); if (options.mustMatch) { // call search and run callback $input.search( function (result){ // if no value found, clear the input box if( !result ) { if (options.multiple) { var words = trimWords($input.val()).slice(0, -1); $input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") ); } else { $input.val( "" ); $input.trigger("result", null); } } } ); } }; function receiveData(q, data) { if ( data && data.length && hasFocus ) { stopLoading(); select.display(data, q); autoFill(q, data[0].value); select.show(); } else { hideResultsNow(); } }; function request(term, success, failure) { if (!options.matchCase) term = term.toLowerCase(); var data = cache.load(term); // recieve the cached data if (data && data.length) { success(term, data); // if an AJAX url has been supplied, try loading the data now } else if( (typeof options.url == "string") && (options.url.length > 0) ){ var extraParams = { timestamp: +new Date() }; $.each(options.extraParams, function(key, param) { extraParams[key] = typeof param == "function" ? param() : param; }); $.ajax({ // try to leverage ajaxQueue plugin to abort previous requests mode: "abort", // limit abortion to this input port: "autocomplete" + input.name, dataType: options.dataType, url: options.url, data: $.extend({ query: lastWord(term), limit: options.max }, extraParams), success: function(data) { var parsed = options.parse && options.parse(data) || parse(data); cache.add(term, parsed); success(term, parsed); } }); } else { // if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match select.emptyList(); failure(term); } }; function parse(data) { var parsed = []; var rows = data.split("\n"); for (var i=0; i < rows.length; i++) { var row = $.trim(rows[i]); if (row) { row = row.split("|"); parsed[parsed.length] = { data: row, value: row[0], result: options.formatResult && options.formatResult(row, row[0]) || row[0] }; } } return parsed; }; function stopLoading() { $input.removeClass(options.loadingClass); }; }; $.Autocompleter.defaults = { inputClass: "ac_input", resultsClass: "ac_results", loadingClass: "ac_loading", minChars: 3, delay: 100, matchCase: false, matchSubset: true, matchContains: false, cacheLength: 10, max: 100, mustMatch: false, extraParams: {}, selectFirst: true, formatItem: function(row) { return row[0]; }, formatMatch: null, autoFill: false, width: 0, multiple: false, multipleSeparator: ", ", highlight: function(value, term) { return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "$1"); }, scroll: true, scrollHeight: 180 }; $.Autocompleter.Cache = function(options) { var data = {}; var length = 0; function matchSubset(s, sub) { if (typeof(s) != 'string') return false; if (!options.matchCase) s = s.toLowerCase(); var i = s.indexOf(sub); if (options.matchContains == "word"){ i = s.toLowerCase().search("\\b" + sub.toLowerCase()); } if (i == -1) return false; return i == 0 || options.matchContains; }; function add(q, value) { if (length > options.cacheLength){ flush(); } if (!data[q]){ length++; } data[q] = value; } function populate(){ if( !options.data ) return false; // track the matches var stMatchSets = {}, nullData = 0; // no url was specified, we need to adjust the cache length to make sure it fits the local data store if( !options.url ) options.cacheLength = 1; // track all options for minChars = 0 stMatchSets[""] = []; // loop through the array and create a lookup structure for ( var i = 0, ol = options.data.length; i < ol; i++ ) { var rawValue = options.data[i]; // if rawValue is a string, make an array otherwise just reference the array rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue; var value = options.formatMatch(rawValue, i+1, options.data.length); if ( value === false ) continue; var firstChar = value.charAt(0).toLowerCase(); // if no lookup array for this character exists, look it up now if( !stMatchSets[firstChar] ) stMatchSets[firstChar] = []; // if the match is a string var row = { value: value, data: rawValue, result: options.formatResult && options.formatResult(rawValue) || value }; // push the current match into the set list stMatchSets[firstChar].push(row); // keep track of minChars zero items if ( nullData++ < options.max ) { stMatchSets[""].push(row); } }; // add the data items to the cache $.each(stMatchSets, function(i, value) { // increase the cache size options.cacheLength++; // add to the cache add(i, value); }); } // populate any existing data setTimeout(populate, 25); function flush(){ data = {}; length = 0; } return { flush: flush, add: add, populate: populate, load: function(q) { if (!options.cacheLength || !length) return null; /* * if dealing w/local data and matchContains than we must make sure * to loop through all the data collections looking for matches */ if( !options.url && options.matchContains ){ // track all matches var csub = []; // loop through all the data grids for matches for( var k in data ){ // don't search through the stMatchSets[""] (minChars: 0) cache // this prevents duplicates if( k.length > 0 ){ var c = data[k]; $.each(c, function(i, x) { // if we've got a match, add it to the array if (matchSubset(x.value, q)) { csub.push(x); } }); } } return csub; } else // if the exact item exists, use it if (data[q]){ return data[q]; } else if (options.matchSubset) { for (var i = q.length - 1; i >= options.minChars; i--) { var c = data[q.substr(0, i)]; if (c) { var csub = []; $.each(c, function(i, x) { if (matchSubset(x.value, q)) { csub[csub.length] = x; } }); return csub; } } } return null; } }; }; $.Autocompleter.Select = function (options, input, select, config) { var CLASSES = { ACTIVE: "ac_over" }; var listItems, active = -1, data, term = "", needsInit = true, element, list; // Create results function init() { if (!needsInit) return; element = $("
") .hide() .addClass(options.resultsClass) .css("position", "absolute") .appendTo(document.body); list = $("
    ").appendTo(element).mouseover( function(event) { if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') { active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event)); $(target(event)).addClass(CLASSES.ACTIVE); } }).click(function(event) { $(target(event)).addClass(CLASSES.ACTIVE); select(); // TODO provide option to avoid setting focus again after selection? useful for cleanup-on-focus input.focus(); return false; }).mousedown(function() { config.mouseDownOnSelect = true; }).mouseup(function() { config.mouseDownOnSelect = false; }); if( options.width > 0 ) element.css("width", options.width); needsInit = false; } function target(event) { var element = event.target; while(element && element.tagName != "LI") element = element.parentNode; // more fun with IE, sometimes event.target is empty, just ignore it then if(!element) return []; return element; } function moveSelect(step) { listItems.slice(active, active + 1).removeClass(CLASSES.ACTIVE); movePosition(step); var activeItem = listItems.slice(active, active + 1).addClass(CLASSES.ACTIVE); if(options.scroll) { var offset = 0; listItems.slice(0, active).each(function() { offset += this.offsetHeight; }); if((offset + activeItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) { list.scrollTop(offset + activeItem[0].offsetHeight - list.innerHeight()); } else if(offset < list.scrollTop()) { list.scrollTop(offset); } } }; function movePosition(step) { active += step; if (active < 0) { active = listItems.size() - 1; } else if (active >= listItems.size()) { active = 0; } } function limitNumberOfItems(available) { return options.max && options.max < available ? options.max : available; } function fillList() { list.empty(); var max = limitNumberOfItems(data.length); for (var i=0; i < max; i++) { if (!data[i]) continue; var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term); if ( formatted === false ) continue; var li = $("
  • ").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0]; $.data(li, "ac_data", data[i]); } listItems = list.find("li"); if ( options.selectFirst ) { listItems.slice(0, 1).addClass(CLASSES.ACTIVE); active = 0; } // apply bgiframe if available if ( $.fn.bgiframe ) list.bgiframe(); } return { display: function(d, q) { init(); data = d; term = q; fillList(); }, next: function() { moveSelect(1); }, prev: function() { moveSelect(-1); }, pageUp: function() { if (active != 0 && active - 8 < 0) { moveSelect( -active ); } else { moveSelect(-8); } }, pageDown: function() { if (active != listItems.size() - 1 && active + 8 > listItems.size()) { moveSelect( listItems.size() - 1 - active ); } else { moveSelect(8); } }, hide: function() { element && element.hide(); listItems && listItems.removeClass(CLASSES.ACTIVE); active = -1; }, visible : function() { return element && element.is(":visible"); }, current: function() { return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]); }, show: function() { var offset = $(input).offset(); element.css({ width: typeof options.width == "string" || options.width > 0 ? options.width : $(input).width(), top: offset.top + input.offsetHeight, left: offset.left }).show(); if(options.scroll) { list.scrollTop(0); list.css({ maxHeight: options.scrollHeight, overflow: 'auto' }); if($.browser.msie && typeof document.body.style.maxHeight === "undefined") { var listHeight = 0; listItems.each(function() { listHeight += this.offsetHeight; }); var scrollbarsVisible = listHeight > options.scrollHeight; list.css('height', scrollbarsVisible ? options.scrollHeight : listHeight ); if (!scrollbarsVisible) { // IE doesn't recalculate width when scrollbar disappears listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) ); } } } }, selected: function() { var selected = listItems && listItems.filter("." + CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE); return selected && selected.length && $.data(selected[0], "ac_data"); }, emptyList: function (){ list && list.empty(); }, unbind: function() { element && element.remove(); } }; }; $.fn.selection = function(start, end) { if (start !== undefined) { return this.each(function() { if( this.createTextRange ){ var selRange = this.createTextRange(); if (end === undefined || start == end) { selRange.move("character", start); selRange.select(); } else { selRange.collapse(true); selRange.moveStart("character", start); selRange.moveEnd("character", end); selRange.select(); } } else if( this.setSelectionRange ){ this.setSelectionRange(start, end); } else if( this.selectionStart ){ this.selectionStart = start; this.selectionEnd = end; } }); } var field = this[0]; if ( field.createTextRange ) { var range = document.selection.createRange(), orig = field.value, teststring = "<->", textLength = range.text.length; range.text = teststring; var caretAt = field.value.indexOf(teststring); field.value = orig; this.selection(caretAt, caretAt + textLength); return { start: caretAt, end: caretAt + textLength } } else if( field.selectionStart !== undefined ){ return { start: field.selectionStart, end: field.selectionEnd } } }; })(jlorhQuery);