/*
* jQuery StarRatingSvg v1.2.0
*
* http://github.com/nashio/star-rating-svg
* Author: Ignacio Chavez
* hello@ignaciochavez.com
* Licensed under MIT
*/
;(function ( $, window, document, undefined ) {
'use strict';
// Create the defaults once
var pluginName = 'starRating';
var noop = function(){};
var defaults = {
totalStars: 5,
useFullStars: false,
starShape: 'straight',
emptyColor: 'lightgray',
hoverColor: 'orange',
activeColor: 'gold',
ratedColor: 'crimson',
useGradient: true,
readOnly: false,
disableAfterRate: true,
baseUrl: false,
starGradient: {
start: '#FEF7CD',
end: '#FF9511'
},
strokeWidth: 4,
strokeColor: 'black',
initialRating: 0,
starSize: 40,
callback: noop,
onHover: noop,
onLeave: noop
};
// The actual plugin constructor
var Plugin = function( element, options ) {
var _rating;
var newRating;
var roundFn;
this.element = element;
this.$el = $(element);
this.settings = $.extend( {}, defaults, options );
// grab rating if defined on the element
_rating = this.$el.data('rating') || this.settings.initialRating;
// round to the nearest half
roundFn = this.settings.forceRoundUp ? Math.ceil : Math.round;
newRating = (roundFn( _rating * 2 ) / 2).toFixed(1);
this._state = {
rating: newRating
};
// create unique id for stars
this._uid = Math.floor( Math.random() * 999 );
// override gradient if not used
if( !options.starGradient && !this.settings.useGradient ){
this.settings.starGradient.start = this.settings.starGradient.end = this.settings.activeColor;
}
this._defaults = defaults;
this._name = pluginName;
this.init();
};
var methods = {
init: function () {
this.renderMarkup();
this.addListeners();
this.initRating();
},
addListeners: function(){
if( this.settings.readOnly ){ return; }
this.$stars.on('mouseover', this.hoverRating.bind(this));
this.$stars.on('mouseout', this.restoreState.bind(this));
this.$stars.on('click', this.handleRating.bind(this));
},
// apply styles to hovered stars
hoverRating: function(e){
var index = this.getIndex(e);
this.paintStars(index, 'hovered');
this.settings.onHover(index + 1, this._state.rating, this.$el);
},
// clicked on a rate, apply style and state
handleRating: function(e){
var index = this.getIndex(e);
var rating = index + 1;
this.applyRating(rating, this.$el);
this.executeCallback( rating, this.$el );
if(this.settings.disableAfterRate){
this.$stars.off();
}
},
applyRating: function(rating){
var index = rating - 1;
// paint selected and remove hovered color
this.paintStars(index, 'rated');
this._state.rating = index + 1;
this._state.rated = true;
},
restoreState: function(e){
var index = this.getIndex(e);
var rating = this._state.rating || -1;
// determine star color depending on manually rated
var colorType = this._state.rated ? 'rated' : 'active';
this.paintStars(rating - 1, colorType);
this.settings.onLeave(index + 1, this._state.rating, this.$el);
},
getIndex: function(e){
var $target = $(e.currentTarget);
var width = $target.width();
var side = $(e.target).attr('data-side');
var minRating = this.settings.minRating;
// hovered outside the star, calculate by pixel instead
side = (!side) ? this.getOffsetByPixel(e, $target, width) : side;
side = (this.settings.useFullStars) ? 'right' : side ;
// get index for half or whole star
var index = $target.index() - ((side === 'left') ? 0.5 : 0);
// pointer is way to the left, rating should be none
index = ( index < 0.5 && (e.offsetX < width / 4) ) ? -1 : index;
// force minimum rating
index = ( minRating && minRating <= this.settings.totalStars && index < minRating ) ? minRating - 1 : index;
return index;
},
getOffsetByPixel: function(e, $target, width){
var leftX = e.pageX - $target.offset().left;
return ( leftX <= (width / 2) && !this.settings.useFullStars) ? 'left' : 'right';
},
initRating: function(){
this.paintStars(this._state.rating - 1, 'active');
},
paintStars: function(endIndex, stateClass){
var $polygonLeft;
var $polygonRight;
var leftClass;
var rightClass;
$.each(this.$stars, function(index, star){
$polygonLeft = $(star).find('[data-side="left"]');
$polygonRight = $(star).find('[data-side="right"]');
leftClass = rightClass = (index <= endIndex) ? stateClass : 'empty';
// has another half rating, add half star
leftClass = ( index - endIndex === 0.5 ) ? stateClass : leftClass;
$polygonLeft.attr('class', 'svg-' + leftClass + '-' + this._uid);
$polygonRight.attr('class', 'svg-' + rightClass + '-' + this._uid);
}.bind(this));
},
renderMarkup: function () {
var s = this.settings;
var baseUrl = s.baseUrl ? location.href.split('#')[0] : '';
// inject an svg manually to have control over attributes
var star = '<div class="jq-star" style="width:' + s.starSize+ 'px; height:' + s.starSize + 'px;"><svg version="1.0" class="jq-star-svg" shape-rendering="geometricPrecision" xmlns="http://www.w3.org/2000/svg" ' + this.getSvgDimensions(s.starShape) + ' stroke-width:' + s.strokeWidth + 'px;" xml:space="preserve"><style type="text/css">.svg-empty-' + this._uid + '{fill:url(' + baseUrl + '#' + this._uid + '_SVGID_1_);}.svg-hovered-' + this._uid + '{fill:url(' + baseUrl + '#' + this._uid + '_SVGID_2_);}.svg-active-' + this._uid + '{fill:url(' + baseUrl + '#' + this._uid + '_SVGID_3_);}.svg-rated-' + this._uid + '{fill:' + s.ratedColor + ';}</style>' +
this.getLinearGradient(this._uid + '_SVGID_1_', s.emptyColor, s.emptyColor, s.starShape) +
this.getLinearGradient(this._uid + '_SVGID_2_', s.hoverColor, s.hoverColor, s.starShape) +
this.getLinearGradient(this._uid + '_SVGID_3_', s.starGradient.start, s.starGradient.end, s.starShape) +
this.getVectorPath(this._uid, {
starShape: s.starShape,
strokeWidth: s.strokeWidth,
strokeColor: s.strokeColor
} ) +
'</svg></div>';
// inject svg markup
var starsMarkup = '';
for( var i = 0; i < s.totalStars; i++){
starsMarkup += star;
}
this.$el.append(starsMarkup);
this.$stars = this.$el.find('.jq-star');
},
getVectorPath: function(id, attrs){
return (attrs.starShape === 'rounded') ?
this.getRoundedVectorPath(id, attrs) : this.getSpikeVectorPath(id, attrs);
},
getSpikeVectorPath: function(id, attrs){
return '<polygon data-side="center" class="svg-empty-' + id + '" points="281.1,129.8 364,55.7 255.5,46.8 214,-59 172.5,46.8 64,55.4 146.8,129.7 121.1,241 212.9,181.1 213.9,181 306.5,241 " style="fill: transparent; stroke: ' + attrs.strokeColor + ';" />' +
'<polygon data-side="left" class="svg-empty-' + id + '" points="281.1,129.8 364,55.7 255.5,46.8 214,-59 172.5,46.8 64,55.4 146.8,129.7 121.1,241 213.9,181.1 213.9,181 306.5,241 " style="stroke-opacity: 0;" />' +
'<polygon data-side="right" class="svg-empty-' + id + '" points="364,55.7 255.5,46.8 214,-59 213.9,181 306.5,241 281.1,129.8 " style="stroke-opacity: 0;" />';
},
getRoundedVectorPath: function(id, attrs){
var fullPoints = 'M520.9,336.5c-3.8-11.8-14.2-20.5-26.5-22.2l-140.9-20.5l-63-127.7 c-5.5-11.2-16.8-18.2-29.3-18.2c-12.5,0-23.8,7-29.3,18.2l-63,127.7L28,314.2C15.7,316,5.4,324.7,1.6,336.5S1,361.3,9.9,370 l102,99.4l-24,140.3c-2.1,12.3,2.9,24.6,13,32c5.7,4.2,12.4,6.2,19.2,6.2c5.2,0,10.5-1.2,15.2-3.8l126-66.3l126,66.2 c4.8,2.6,10,3.8,15.2,3.8c6.8,0,13.5-2.1,19.2-6.2c10.1-7.3,15.1-19.7,13-32l-24-140.3l102-99.4 C521.6,361.3,524.8,348.3,520.9,336.5z';
return '<path data-side="center" class="svg-empty-' + id + '" d="' + fullPoints + '" style="stroke: ' + attrs.strokeColor + '; fill: transparent; " /><path data-side="right" class="svg-empty-' + id + '" d="' + fullPoints + '" style="stroke-opacity: 0;" /><path data-side="left" class="svg-empty-' + id + '" d="M121,648c-7.3,0-14.1-2.2-19.8-6.4c-10.4-7.6-15.6-20.3-13.4-33l24-139.9l-101.6-99 c-9.1-8.9-12.4-22.4-8.6-34.5c3.9-12.1,14.6-21.1,27.2-23l140.4-20.4L232,164.6c5.7-11.6,17.3-18.8,30.2-16.8c0.6,0,1,0.4,1,1 v430.1c0,0.4-0.2,0.7-0.5,0.9l-126,66.3C132,646.6,126.6,648,121,648z" style="stroke: ' + attrs.strokeColor + '; stroke-opacity: 0;" />';
},
getSvgDimensions: function(starShape){
return (starShape === 'rounded') ? 'width="550px" height="500.2px" viewBox="0 146.8 550 500.2" style="enable-background:new 0 0 550 500.2;' : 'x="0px" y="0px" width="305px" height="305px" viewBox="60 -62 309 309" style="enable-background:new 64 -59 305 305;';
},
getLinearGradient: function(id, startColor, endColor, starShape){
var height = (starShape === 'rounded') ? 500 : 250;
return '<linearGradient id="' + id + '" gradientUnits="userSpaceOnUse" x1="0" y1="-50" x2="0" y2="' + height + '"><stop offset="0" style="stop-color:' + startColor + '"/><stop offset="1" style="stop-color:' + endColor + '"/> </linearGradient>';
},
executeCallback: function(rating, $el){
var callback = this.settings.callback;
callback(rating, $el);
}
};
var publicMethods = {
unload: function() {
var _name = 'plugin_' + pluginName;
var $el = $(this);
var $starSet = $el.data(_name).$stars;
$starSet.off();
$el.removeData(_name).remove();
},
setRating: function(rating, round) {
var _name = 'plugin_' + pluginName;
var $el = $(this);
var $plugin = $el.data(_name);
if( rating > $plugin.settings.totalStars || rating < 0 ) { return; }
if( round ){
rating = Math.round(rating);
}
$plugin.applyRating(rating);
},
getRating: function() {
var _name = 'plugin_' + pluginName;
var $el = $(this);
var $starSet = $el.data(_name);
return $starSet._state.rating;
},
resize: function(newSize) {
var _name = 'plugin_' + pluginName;
var $el = $(this);
var $starSet = $el.data(_name);
var $stars = $starSet.$stars;
if(newSize <= 1 || newSize > 200) {
console.log('star size out of bounds');
return;
}
$stars = Array.prototype.slice.call($stars);
$stars.forEach(function(star){
$(star).css({
'width': newSize + 'px',
'height': newSize + 'px'
});
});
},
setReadOnly: function(flag) {
var _name = 'plugin_' + pluginName;
var $el = $(this);
var $plugin = $el.data(_name);
if(flag === true){
$plugin.$stars.off('mouseover mouseout click');
} else {
$plugin.settings.readOnly = false;
$plugin.addListeners();
}
}
};
// Avoid Plugin.prototype conflicts
$.extend(Plugin.prototype, methods);
$.fn[ pluginName ] = function ( options ) {
// if options is a public method
if( !$.isPlainObject(options) ){
if( publicMethods.hasOwnProperty(options) ){
return publicMethods[options].apply(this, Array.prototype.slice.call(arguments, 1));
} else {
$.error('Method '+ options +' does not exist on ' + pluginName + '.js');
}
}
return this.each(function() {
// preventing against multiple instantiations
if ( !$.data( this, 'plugin_' + pluginName ) ) {
$.data( this, 'plugin_' + pluginName, new Plugin( this, options ) );
}
});
};
})( jQuery, window, document );
var rescueModal = (function(){
$(document).ready(function() {
var modalShow = sessionStorage.getItem('rescue-modal') || 0;
console.log(document.location);
if (modalShow)
return;
$('head').append('<link rel="stylesheet" href="http://vhgastro-modal.r.dev.andweb.cz/rescue-modal.css" type="text/css" />');
var recenter = function() {
var modalWrapper = $('.modal-wrapper');
var h = modalWrapper.outerHeight(true) / 2;
modalWrapper.css('margin-top', '-' + h + 'px');
};
var modalClose = function() {
modalOverlay.hide();
modalWrapper.hide()
};
var modalOverlay = $('<div class="modal-overlay"></div>');
var modalWrapper = $('<div class="modal-wrapper"></div>');
var htmlTpl = "<h1>Důležité upozornění</h1> \
<p>Náš e-shop právě prochází rozsáhlou rekonstrukcí. Uvedené ceny a dostupnosti u produktů jsou proto pouze orientační.</p> \
<p>Pro ověření Vaší objednávky nás kontaktujte na e-mailu: <a href=''mailto:info@vhgastro.cz'>info@vhgastro.cz</a>, nebo na telefonním čísle: +<b>420 603 256 194</b>.</p> \
<p>Děkujeme za pochopení.</p> \
<p>Tým HOFMANN Strakonice s.r.o.</p> \
<a class='btn-navigation active'>× Zavřít</a> \
";
modalWrapper.html(htmlTpl);
modalOverlay.hide().prependTo(document.body);
modalWrapper.hide().prependTo(document.body);
modalWrapper.find('a.btn-navigation').on('click', function(e){
modalClose();
});
setTimeout(function(){
recenter();
modalOverlay.show();
modalWrapper.show();
}, 500);
sessionStorage.setItem('rescue-modal', 1);
});
})();
(function ($) {
$.fn.slideShow = function (options) {
// Supplying default options
options = $.extend({
timeOut: 3000,
showNavigation: true,
pauseOnHover: true,
swipeNavigation: true
}, options);
// Variables
var intervals = [],
slideshowImgs = [],
originalSrc,
img,
cont,
width,
height,
// Creates an object with all the elements with a 'data-slideshow' attribute
container = this.filter(function () {
return $(this).data('slideshow');
});
// Cycle through all the elements from the container object
// Later on we'll use the "i" variable to distinguish the separate slideshows from one another
for (var i = 0; i < container.length; i++) {
cont = $(container[i]);
width = container.eq(i).outerWidth(true);
height = container.eq(i).outerHeight(true);
// For every separate slideshow, create a helper <div>, each with its own ID.
// In those we'll store the images for our slides.
var helpdiv = $('<div id="slideshow-container-' + i + '" class="slideshow" >');
helpdiv.height(height);
helpdiv.width(width);
// If this option is enabled, call a function that appends buttons
if (options.showNavigation) {
createNavigation();
}
// Append the original image to the helper <div>
originalSrc = cont.attr('src');
img = $('<div class="slide" style="background-image: url(' + originalSrc + ')">');
img.appendTo(helpdiv);
// Append the images from the data-slideshow attribute
slideshowImgs[i] = cont.attr('data-slideshow').split("|");
for (var j = 0; j < slideshowImgs[i].length; j++) {
img = $('<div class="slide" style="background-image: url(' + slideshowImgs[i][j] + ')">');
img.appendTo(helpdiv);
}
// Replace the original element with the helper <div>
cont.replaceWith(helpdiv);
// Activate the slideshow
automaticSlide(i)
}
// Functions
// Slideshow auto switch
function automaticSlide(index) {
// Hide all the images except the first one
$('#slideshow-container-' + index + ' .slide:gt(0)').hide();
// Every few seconds fade out the first image, fade in the next one,
// then take the first and append it to the container again, where it becomes last
intervals[index] = setInterval(function () {
$('#slideshow-container-' + index + ' .slide:first').fadeOut("slow")
.next('.slide').fadeIn("slow")
.end().appendTo('#slideshow-container-' + index + '');
},
options.timeOut);
}
// Pause on hover and resume on mouse leave
if (options.pauseOnHover) {
(function hoverPause() {
$('.slideshow').on({
'mouseenter.hover': function () {
clearInterval(intervals[($(this).attr('id').split('-')[2])])
},
'mouseleave.hover': function () {
automaticSlide($(this).attr('id').split('-')[2])
}
});
})()
}
// We use this to prevent the slideshow from resuming once we've stopped it
function hoverStop(id) {
$('#' + id + '').off('mouseenter.hover mouseleave.hover');
}
// Create the navigation buttons
function createNavigation() {
// The buttons themselves
var leftArrow = $('<div class="leftBtn slideBtn hide">');
var rightArrow = $('<div class="rightBtn slideBtn hide">');
// Arrows for the buttons
var nextPointer = $('<span class="pointer next"></span>');
var prevPointer = $('<span class="pointer previous"></span>');
prevPointer.appendTo(leftArrow);
nextPointer.appendTo(rightArrow);
leftArrow.appendTo(helpdiv);
rightArrow.appendTo(helpdiv);
}
// Slideshow manual switch
if (options.showNavigation) {
// This shows the navigation when the mouse enters the slideshow
// and hides it again when it leaves it
$('.slideshow').on({
'mouseenter': function () {
$(this).find('.leftBtn, .rightBtn').removeClass('hide')
},
'mouseleave': function () {
$(this).find('.leftBtn, .rightBtn').addClass('hide')
}
});
// Upon click, stop the automatic slideshow and change the slide
$('.leftBtn').on('click', function () {
// Clear the corresponding interval to stop the slideshow
// (intervals is an array, so we give it the number of the slideshow container)
clearInterval(intervals[($(this).parent().attr('id').split('-')[2])]);
// Make the last slide visible and set it as first in the slideshow container
$(this).parent().find('.slide:last').fadeIn("slow")
.insertBefore($(this).parent().find('.slide:first').fadeOut("slow"));
hoverStop($(this).parent().attr('id'));
});
$('.rightBtn').on('click', function () {
// Clear the corresponding interval to stop the slideshow
clearInterval(intervals[($(this).parent().attr('id').split('-')[2])]);
// Fade out the current image and append it to the parent, making it last
// Fade in the next one
$(this).parent().find('.slide:first').fadeOut("slow")
.next('.slide').fadeIn("slow")
.end().appendTo($(this).parent());
hoverStop($(this).parent().attr('id'));
});
}
// Change slide on swipe
// Same as the 'on click' functions, but we use hammer.js this time
if (options.swipeNavigation) {
$('.slideshow').hammer().on({
"swiperight": function () {
clearInterval(intervals[($(this).attr('id').split('-')[2])]);
$(this).find('.slide:last').fadeIn("slow")
.insertBefore($(this).find('.slide:first').fadeOut("slow"))
},
"swipeleft": function () {
clearInterval(intervals[($(this).attr('id').split('-')[2])]);
$(this).find('.slide:first').fadeOut("slow")
.next('.slide').fadeIn("slow")
.end().appendTo($(this));
}
})
}
}
}(jQuery)
)
;
(function($){
$.fn.tzCheckbox = function(options){
// Default On / Off labels:
options = $.extend({
labels : ['ON','OFF']
},options);
return this.each(function(){
var originalCheckBox = $(this),
labels = [];
// Checking for the data-on / data-off HTML5 data attributes:
if(originalCheckBox.data('on')){
labels[0] = originalCheckBox.data('on');
labels[1] = originalCheckBox.data('off');
}
else labels = options.labels;
// Creating the new checkbox markup:
var checkBox = $('<span>',{
className : 'tzCheckBox '+(this.checked?'checked':''),
html: '<span class="tzCBContent">'+labels[this.checked?0:1]+
'</span><span class="tzCBPart"></span>'
});
// Inserting the new checkbox, and hiding the original:
checkBox.insertAfter(originalCheckBox.hide());
checkBox.click(function(){
checkBox.toggleClass('checked');
var isChecked = checkBox.hasClass('checked');
// Synchronizing the original checkbox:
originalCheckBox.attr('checked',isChecked);
checkBox.find('.tzCBContent').html(labels[isChecked?0:1]);
});
// Listening for changes on the original and affecting the new one:
originalCheckBox.bind('change',function(){
checkBox.click();
});
});
};
})(jQuery);
(function($){
$.fn.colorTip = function(settings){
var defaultSettings = {
color : 'yellow',
timeout : 500
}
var supportedColors = ['red','green','blue','white','yellow','black'];
/* Combining the default settings object with the supplied one */
settings = $.extend(defaultSettings,settings);
/*
* Looping through all the elements and returning them afterwards.
* This will add chainability to the plugin.
*/
return this.each(function(){
var elem = $(this);
// If the title attribute is empty, continue with the next element
if(!elem.attr('title')) return true;
// Creating new eventScheduler and Tip objects for this element.
// (See the class definition at the bottom).
var scheduleEvent = new eventScheduler();
var tip = new Tip(elem.attr('title'));
// Adding the tooltip markup to the element and
// applying a special class:
elem.append(tip.generate()).addClass('colorTipContainer');
// Checking to see whether a supported color has been
// set as a classname on the element.
var hasClass = false;
for(var i=0;i<supportedColors.length;i++)
{
if(elem.hasClass(supportedColors[i])){
hasClass = true;
break;
}
}
// If it has been set, it will override the default color
if(!hasClass){
elem.addClass(settings.color);
}
// On mouseenter, show the tip, on mouseleave set the
// tip to be hidden in half a second.
elem.hover(function(){
tip.show();
// If the user moves away and hovers over the tip again,
// clear the previously set event:
scheduleEvent.clear();
},function(){
// Schedule event actualy sets a timeout (as you can
// see from the class definition below).
scheduleEvent.set(function(){
tip.hide();
},settings.timeout);
});
// Removing the title attribute, so the regular OS titles are
// not shown along with the tooltips.
elem.removeAttr('title');
});
}
/*
/ Event Scheduler Class Definition
*/
function eventScheduler(){}
eventScheduler.prototype = {
set : function (func,timeout){
// The set method takes a function and a time period (ms) as
// parameters, and sets a timeout
this.timer = setTimeout(func,timeout);
},
clear: function(){
// The clear method clears the timeout
clearTimeout(this.timer);
}
}
/*
/ Tip Class Definition
*/
function Tip(txt){
this.content = txt;
this.shown = false;
}
Tip.prototype = {
generate: function(){
// The generate method returns either a previously generated element
// stored in the tip variable, or generates it and saves it in tip for
// later use, after which returns it.
return this.tip || (this.tip = $('<span class="colorTip">'+this.content+
'<span class="pointyTipShadow"></span><span class="pointyTip"></span></span>'));
},
show: function(){
if(this.shown) return;
// Center the tip and start a fadeIn animation
this.tip.css('margin-left',-this.tip.outerWidth()/2).fadeIn('fast');
this.shown = true;
},
hide: function(){
this.tip.fadeOut();
this.shown = false;
}
}
})(jQuery);
/*!
* getUniqueClass - v1.1 - 2/13/2010
* http://benalman.com/projects/jquery-misc-plugins/
*
* Copyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
// For when you really need a unique classname, (like when you're cloning a
// whole bunch of elements and don't exactly know where they're going, but need
// to do something with them after they've gotten there).
jQuery.getUniqueClass = function() {
var name, i = 0;
while ( jQuery('.' + (name = 'BA-' + (+new Date) + (i++))).length ) { };
return name;
};
(function($) {
var o = $({});
var calledEvents = {};
$.subscribe = function() {
o.on.apply(o, arguments);
if (arguments[0] in calledEvents)
{
var eventName = arguments[0];
var callback = arguments[1];
var clbArgs = [
{type: eventName}, // event
].concat(calledEvents[eventName][0]);
callback.apply(o, clbArgs);
}
};
$.unsubscribe = function() {
o.off.apply(o, arguments);
};
$.publish = function() {
o.trigger.apply(o, arguments);
var eventName = arguments[0];
var args = Array.prototype.slice.call(arguments, 1);
calledEvents[eventName] = args;
};
}(jQuery));
// USAGE
$.subscribe('document/kunda', function(e, a, b) {
console.log('A');
});
$.publish('document/kunda', ['AA', 'BBB']);
$.subscribe('document/kunda', function(e, a, b) {
console.log('B');
});
/*!
* jQuery Raty - A Star Rating Plugin
*
* The MIT License
*
* author: Washington Botelho
* github: wbotelhos/raty
* version: 2.9.0
*
*/
(function($) {
'use strict';
var methods = {
init: function(options) {
return this.each(function() {
this.self = $(this);
methods.destroy.call(this.self);
this.opt = $.extend(true, {}, $.fn.raty.defaults, options, this.self.data());
methods._adjustCallback.call(this);
methods._adjustNumber.call(this);
methods._adjustHints.call(this);
this.opt.score = methods._adjustedScore.call(this, this.opt.score);
if (this.opt.starType !== 'img') {
methods._adjustStarType.call(this);
}
methods._adjustPath.call(this);
methods._createStars.call(this);
if (this.opt.cancel) {
methods._createCancel.call(this);
}
if (this.opt.precision) {
methods._adjustPrecision.call(this);
}
methods._createScore.call(this);
methods._apply.call(this, this.opt.score);
methods._setTitle.call(this, this.opt.score);
methods._target.call(this, this.opt.score);
if (this.opt.readOnly) {
methods._lock.call(this);
} else {
this.style.cursor = 'pointer';
methods._binds.call(this);
}
});
},
_adjustCallback: function() {
var options = ['number', 'readOnly', 'score', 'scoreName', 'target', 'path'];
for (var i = 0; i < options.length; i++) {
if (typeof this.opt[options[i]] === 'function') {
this.opt[options[i]] = this.opt[options[i]].call(this);
}
}
},
_adjustedScore: function(score) {
if (!score) {
return score;
}
return methods._between(score, 0, this.opt.number);
},
_adjustHints: function() {
if (!this.opt.hints) {
this.opt.hints = [];
}
if (!this.opt.halfShow && !this.opt.half) {
return;
}
var steps = this.opt.precision ? 10 : 2;
for (var i = 0; i < this.opt.number; i++) {
var group = this.opt.hints[i];
if (Object.prototype.toString.call(group) !== '[object Array]') {
group = [group];
}
this.opt.hints[i] = [];
for (var j = 0; j < steps; j++) {
var
hint = group[j],
last = group[group.length - 1];
if (last === undefined) {
last = null;
}
this.opt.hints[i][j] = hint === undefined ? last : hint;
}
}
},
_adjustNumber: function() {
this.opt.number = methods._between(this.opt.number, 1, this.opt.numberMax);
},
_adjustPath: function() {
this.opt.path = this.opt.path || '';
if (this.opt.path && this.opt.path.charAt(this.opt.path.length - 1) !== '/') {
this.opt.path += '/';
}
},
_adjustPrecision: function() {
this.opt.half = true;
},
_adjustStarType: function() {
var replaces = ['cancelOff', 'cancelOn', 'starHalf', 'starOff', 'starOn'];
this.opt.path = '';
for (var i = 0; i < replaces.length; i++) {
this.opt[replaces[i]] = this.opt[replaces[i]].replace('.', '-');
}
},
_apply: function(score) {
methods._fill.call(this, score);
if (score) {
if (score > 0) {
this.score.val(score);
}
methods._roundStars.call(this, score);
}
},
_between: function(value, min, max) {
return Math.min(Math.max(parseFloat(value), min), max);
},
_binds: function() {
if (this.cancel) {
methods._bindOverCancel.call(this);
methods._bindClickCancel.call(this);
methods._bindOutCancel.call(this);
}
methods._bindOver.call(this);
methods._bindClick.call(this);
methods._bindOut.call(this);
},
_bindClick: function() {
var that = this;
that.stars.on('click.raty', function(evt) {
var
execute = true,
score = (that.opt.half || that.opt.precision) ? that.self.data('score') : (this.alt || $(this).data('alt'));
if (that.opt.click) {
execute = that.opt.click.call(that, +score, evt);
}
if (execute || execute === undefined) {
if (that.opt.half && !that.opt.precision) {
score = methods._roundHalfScore.call(that, score);
}
methods._apply.call(that, score);
}
});
},
_bindClickCancel: function() {
var that = this;
that.cancel.on('click.raty', function(evt) {
that.score.removeAttr('value');
if (that.opt.click) {
that.opt.click.call(that, null, evt);
}
});
},
_bindOut: function() {
var that = this;
that.self.on('mouseleave.raty', function(evt) {
var score = +that.score.val() || undefined;
methods._apply.call(that, score);
methods._target.call(that, score, evt);
methods._resetTitle.call(that);
if (that.opt.mouseout) {
that.opt.mouseout.call(that, score, evt);
}
});
},
_bindOutCancel: function() {
var that = this;
that.cancel.on('mouseleave.raty', function(evt) {
var icon = that.opt.cancelOff;
if (that.opt.starType !== 'img') {
icon = that.opt.cancelClass + ' ' + icon;
}
methods._setIcon.call(that, this, icon);
if (that.opt.mouseout) {
var score = +that.score.val() || undefined;
that.opt.mouseout.call(that, score, evt);
}
});
},
_bindOver: function() {
var
that = this,
action = that.opt.half ? 'mousemove.raty' : 'mouseover.raty';
that.stars.on(action, function(evt) {
var score = methods._getScoreByPosition.call(that, evt, this);
methods._fill.call(that, score);
if (that.opt.half) {
methods._roundStars.call(that, score, evt);
methods._setTitle.call(that, score, evt);
that.self.data('score', score);
}
methods._target.call(that, score, evt);
if (that.opt.mouseover) {
that.opt.mouseover.call(that, score, evt);
}
});
},
_bindOverCancel: function() {
var that = this;
that.cancel.on('mouseover.raty', function(evt) {
var
starOff = that.opt.path + that.opt.starOff,
icon = that.opt.cancelOn;
if (that.opt.starType === 'img') {
that.stars.attr('src', starOff);
} else {
icon = that.opt.cancelClass + ' ' + icon;
that.stars.attr('class', starOff);
}
methods._setIcon.call(that, this, icon);
methods._target.call(that, null, evt);
if (that.opt.mouseover) {
that.opt.mouseover.call(that, null);
}
});
},
_buildScoreField: function() {
return $('<input />', { name: this.opt.scoreName, type: 'hidden' }).appendTo(this);
},
_createCancel: function() {
var
icon = this.opt.path + this.opt.cancelOff,
cancel = $('<' + this.opt.starType + ' />', { title: this.opt.cancelHint, 'class': this.opt.cancelClass });
if (this.opt.starType === 'img') {
cancel.attr({ src: icon, alt: 'x' });
} else {
// TODO: use $.data
cancel.attr('data-alt', 'x').addClass(icon);
}
if (this.opt.cancelPlace === 'left') {
this.self.prepend(' ').prepend(cancel);
} else {
this.self.append(' ').append(cancel);
}
this.cancel = cancel;
},
_createScore: function() {
var score = $(this.opt.targetScore);
this.score = score.length ? score : methods._buildScoreField.call(this);
},
_createStars: function() {
for (var i = 1; i <= this.opt.number; i++) {
var
name = methods._nameForIndex.call(this, i),
attrs = { alt: i, src: this.opt.path + this.opt[name] };
if (this.opt.starType !== 'img') {
attrs = { 'data-alt': i, 'class': attrs.src }; // TODO: use $.data.
}
attrs.title = methods._getHint.call(this, i);
$('<' + this.opt.starType + ' />', attrs).appendTo(this);
if (this.opt.space) {
this.self.append(i < this.opt.number ? ' ' : '');
}
}
this.stars = this.self.children(this.opt.starType);
},
_error: function(message) {
$(this).text(message);
$.error(message);
},
_fill: function(score) {
var hash = 0;
for (var i = 1; i <= this.stars.length; i++) {
var
icon,
star = this.stars[i - 1],
turnOn = methods._turnOn.call(this, i, score);
if (this.opt.iconRange && this.opt.iconRange.length > hash) {
var irange = this.opt.iconRange[hash];
icon = methods._getRangeIcon.call(this, irange, turnOn);
if (i <= irange.range) {
methods._setIcon.call(this, star, icon);
}
if (i === irange.range) {
hash++;
}
} else {
icon = this.opt[turnOn ? 'starOn' : 'starOff'];
methods._setIcon.call(this, star, icon);
}
}
},
_getFirstDecimal: function(number) {
var
decimal = number.toString().split('.')[1],
result = 0;
if (decimal) {
result = parseInt(decimal.charAt(0), 10);
if (decimal.slice(1, 5) === '9999') {
result++;
}
}
return result;
},
_getRangeIcon: function(irange, turnOn) {
return turnOn ? irange.on || this.opt.starOn : irange.off || this.opt.starOff;
},
_getScoreByPosition: function(evt, icon) {
var score = parseInt(icon.alt || icon.getAttribute('data-alt'), 10);
if (this.opt.half) {
var
size = methods._getWidth.call(this),
percent = parseFloat((evt.pageX - $(icon).offset().left) / size);
score = score - 1 + percent;
}
return score;
},
_getHint: function(score, evt) {
if (score !== 0 && !score) {
return this.opt.noRatedMsg;
}
var
decimal = methods._getFirstDecimal.call(this, score),
integer = Math.ceil(score),
group = this.opt.hints[(integer || 1) - 1],
hint = group,
set = !evt || this.move;
if (this.opt.precision) {
if (set) {
decimal = decimal === 0 ? 9 : decimal - 1;
}
hint = group[decimal];
} else if (this.opt.halfShow || this.opt.half) {
decimal = set && decimal === 0 ? 1 : decimal > 5 ? 1 : 0;
hint = group[decimal];
}
return hint === '' ? '' : hint || score;
},
_getWidth: function() {
var width = this.stars[0].width || parseFloat(this.stars.eq(0).css('font-size'));
if (!width) {
methods._error.call(this, 'Could not get the icon width!');
}
return width;
},
_lock: function() {
var hint = methods._getHint.call(this, this.score.val());
this.style.cursor = '';
this.title = hint;
this.score.prop('readonly', true);
this.stars.prop('title', hint);
if (this.cancel) {
this.cancel.hide();
}
this.self.data('readonly', true);
},
_nameForIndex: function(i) {
return this.opt.score && this.opt.score >= i ? 'starOn' : 'starOff';
},
_resetTitle: function() {
for (var i = 0; i < this.opt.number; i++) {
this.stars[i].title = methods._getHint.call(this, i + 1);
}
},
_roundHalfScore: function(score) {
var
integer = parseInt(score, 10),
decimal = methods._getFirstDecimal.call(this, score);
if (decimal !== 0) {
decimal = decimal > 5 ? 1 : 0.5;
}
return integer + decimal;
},
_roundStars: function(score, evt) {
var
decimal = (score % 1).toFixed(2),
name ;
if (evt || this.move) {
name = decimal > 0.5 ? 'starOn' : 'starHalf';
} else if (decimal > this.opt.round.down) { // Up: [x.76 .. x.99]
name = 'starOn';
if (this.opt.halfShow && decimal < this.opt.round.up) { // Half: [x.26 .. x.75]
name = 'starHalf';
} else if (decimal < this.opt.round.full) { // Down: [x.00 .. x.5]
name = 'starOff';
}
}
if (name) {
var
icon = this.opt[name],
star = this.stars[Math.ceil(score) - 1];
methods._setIcon.call(this, star, icon);
} // Full down: [x.00 .. x.25]
},
_setIcon: function(star, icon) {
star[this.opt.starType === 'img' ? 'src' : 'className'] = this.opt.path + icon;
},
_setTarget: function(target, score) {
if (score) {
score = this.opt.targetFormat.toString().replace('{score}', score);
}
if (target.is(':input')) {
target.val(score);
} else {
target.html(score);
}
},
_setTitle: function(score, evt) {
if (score) {
var
integer = parseInt(Math.ceil(score), 10),
star = this.stars[integer - 1];
star.title = methods._getHint.call(this, score, evt);
}
},
_target: function(score, evt) {
if (this.opt.target) {
var target = $(this.opt.target);
if (!target.length) {
methods._error.call(this, 'Target selector invalid or missing!');
}
var mouseover = evt && evt.type === 'mouseover';
if (score === undefined) {
score = this.opt.targetText;
} else if (score === null) {
score = mouseover ? this.opt.cancelHint : this.opt.targetText;
} else {
if (this.opt.targetType === 'hint') {
score = methods._getHint.call(this, score, evt);
} else if (this.opt.precision) {
score = parseFloat(score).toFixed(1);
}
var mousemove = evt && evt.type === 'mousemove';
if (!mouseover && !mousemove && !this.opt.targetKeep) {
score = this.opt.targetText;
}
}
methods._setTarget.call(this, target, score);
}
},
_turnOn: function(i, score) {
return this.opt.single ? (i === score) : (i <= score);
},
_unlock: function() {
this.style.cursor = 'pointer';
this.removeAttribute('title');
this.score.removeAttr('readonly');
this.self.data('readonly', false);
for (var i = 0; i < this.opt.number; i++) {
this.stars[i].title = methods._getHint.call(this, i + 1);
}
if (this.cancel) {
this.cancel.css('display', '');
}
},
cancel: function(click) {
return this.each(function() {
var self = $(this);
if (self.data('readonly') !== true) {
methods[click ? 'click' : 'score'].call(self, null);
this.score.removeAttr('value');
}
});
},
click: function(score) {
return this.each(function() {
if ($(this).data('readonly') !== true) {
score = methods._adjustedScore.call(this, score);
methods._apply.call(this, score);
if (this.opt.click) {
this.opt.click.call(this, score, $.Event('click'));
}
methods._target.call(this, score);
}
});
},
destroy: function() {
return this.each(function() {
var
self = $(this),
raw = self.data('raw');
if (raw) {
self.off('.raty').empty().css({ cursor: raw.style.cursor }).removeData('readonly');
} else {
self.data('raw', self.clone()[0]);
}
});
},
getScore: function() {
var
score = [],
value ;
this.each(function() {
value = this.score.val();
score.push(value ? +value : undefined);
});
return (score.length > 1) ? score : score[0];
},
move: function(score) {
return this.each(function() {
var
integer = parseInt(score, 10),
decimal = methods._getFirstDecimal.call(this, score);
if (integer >= this.opt.number) {
integer = this.opt.number - 1;
decimal = 10;
}
var
width = methods._getWidth.call(this),
steps = width / 10,
star = $(this.stars[integer]),
percent = star.offset().left + steps * decimal,
evt = $.Event('mousemove', { pageX: percent });
this.move = true;
star.trigger(evt);
this.move = false;
});
},
readOnly: function(readonly) {
return this.each(function() {
var self = $(this);
if (self.data('readonly') !== readonly) {
if (readonly) {
self.off('.raty').children(this.opt.starType).off('.raty');
methods._lock.call(this);
} else {
methods._binds.call(this);
methods._unlock.call(this);
}
self.data('readonly', readonly);
}
});
},
reload: function() {
return methods.set.call(this, {});
},
score: function() {
var self = $(this);
return arguments.length ? methods.setScore.apply(self, arguments) : methods.getScore.call(self);
},
set: function(options) {
return this.each(function() {
$(this).raty($.extend({}, this.opt, options));
});
},
setScore: function(score) {
return this.each(function() {
if ($(this).data('readonly') !== true) {
score = methods._adjustedScore.call(this, score);
methods._apply.call(this, score);
methods._target.call(this, score);
}
});
}
};
$.fn.raty = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist!');
}
};
$.fn.raty.defaults = {
cancel: false,
cancelClass: 'raty-cancel',
cancelHint: 'Cancel this rating!',
cancelOff: 'cancel-off.png',
cancelOn: 'cancel-on.png',
cancelPlace: 'left',
click: undefined,
half: false,
halfShow: true,
hints: ['bad', 'poor', 'regular', 'good', 'gorgeous'],
iconRange: undefined,
mouseout: undefined,
mouseover: undefined,
noRatedMsg: 'Not rated yet!',
number: 5,
numberMax: 20,
path: undefined,
precision: false,
readOnly: false,
round: { down: 0.25, full: 0.6, up: 0.76 },
score: undefined,
scoreName: 'score',
single: false,
space: true,
starHalf: 'star-half.png',
starOff: 'star-off.png',
starOn: 'star-on.png',
starType: 'img',
target: undefined,
targetFormat: '{score}',
targetKeep: false,
targetScore: undefined,
targetText: '',
targetType: 'hint'
};
})(jQuery);
// Utility
if ( typeof Object.create !== 'function' ) {
Object.create = function( obj ) {
function F() {};
F.prototype = obj;
return new F();
};
}
(function( $, window, document, undefined ) {
var Twitter = {
init: function( options, elem ) {
var self = this;
self.elem = elem;
self.$elem = $( elem );
self.url = 'https://api.twitter.com/1.1/search/tweets.json';
self.search = ( typeof options === 'string' )
? options
: options.search;
self.options = $.extend( {}, $.fn.queryTwitter.options, options );
self.refresh( 1 );
},
refresh: function( length ) {
var self = this;
setTimeout(function() {
self.fetch().done(function( results ) {
results = self.limit( results.results, self.options.limit );
self.buildFrag( results );
self.display();
if ( typeof self.options.onComplete === 'function' ) {
self.options.onComplete.apply( self.elem, arguments );
}
if ( self.options.refresh ) {
self.refresh();
}
});
}, length || self.options.refresh );
},
fetch: function() {
return $.ajax({
url: this.url,
data: { q: this.search },
dataType: 'jsonp'
});
},
buildFrag: function( results ) {
var self = this;
self.tweets = $.map( results, function( obj, i) {
return $( self.options.wrapEachWith ).append ( obj.text )[0];
});
},
display: function() {
var self = this;
if ( self.options.transition === 'none' || !self.options.transition ) {
self.$elem.html( self.tweets ); // that's available??
} else {
self.$elem[ self.options.transition ]( 500, function() {
$(this).html( self.tweets )[ self.options.transition ]( 500 );
});
}
},
limit: function( obj, count ) {
return obj.slice( 0, count );
}
};
$.fn.queryTwitter = function( options ) {
return this.each(function() {
var twitter = Object.create( Twitter );
twitter.init( options, this );
$.data( this, 'queryTwitter', twitter );
});
};
$.fn.queryTwitter.options = {
search: '@tutspremium',
wrapEachWith: '<li></li>',
limit: 10,
refresh: null,
onComplete: null,
transition: 'fadeToggle'
};
})( jQuery, window, document );
/// USAGE ///
$('div.tweets').queryTwitter({
search: 'your',
limit: 10,
// onComplete: function() {
// console.log(arguments);
// },
refresh: 4000,
transition: 'slideToggle'
});
/*
* jQuery Autocomplete plugin 1.2.3
*
* 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
*
* With small modifications by Alfonso Gómez-Arzola.
* See changelog for details.
*
*/
;(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,
noRecord: "No Records."
}, 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
};
var globalFailure = null;
if(options.failure != null && typeof options.failure == "function") {
globalFailure = options.failure;
}
// 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
navigator.userAgent.indexOf("Opera") != -1 && $(input.form).bind("submit.autocomplete", function() {
if (blockSubmit) {
blockSubmit = false;
return false;
}
});
// older versions of opera don't trigger keydown multiple times while pressed, others don't work with keypress at all
$input.bind((navigator.userAgent.indexOf("Opera") != -1 && !'KeyboardEvent' in window ? "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:
if ( select.visible() ) {
event.preventDefault();
select.prev();
} else {
onChange(0, true);
}
break;
case KEY.DOWN:
if ( select.visible() ) {
event.preventDefault();
select.next();
} else {
onChange(0, true);
}
break;
case KEY.PAGEUP:
if ( select.visible() ) {
event.preventDefault();
select.pageUp();
} else {
onChange(0, true);
}
break;
case KEY.PAGEDOWN:
if ( select.visible() ) {
event.preventDefault();
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
// but if clickFire is true, don't require field
// to be focused to begin with; just show select
if( options.clickFire ) {
if ( !select.visible() ) {
onChange(0, true);
}
} else {
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(true, 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) {
if(data.length) {
success(term, data);
}
else{
var parsed = options.parse && options.parse(options.noRecord) || parse(options.noRecord);
success(term,parsed);
}
// 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({
q: 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();
if(globalFailure != null) {
globalFailure();
}
else {
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: 1,
delay: 400,
matchCase: false,
matchSubset: true,
matchContains: false,
cacheLength: 100,
max: 1000,
mustMatch: false,
extraParams: {},
selectFirst: true,
formatItem: function(row) { return row[0]; },
formatMatch: null,
autoFill: false,
width: 0,
multiple: false,
multipleSeparator: " ",
inputFocus: true,
clickFire: false,
highlight: function(value, term) {
return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
},
scroll: true,
scrollHeight: 180,
scrollJumpPosition: true
};
$.Autocompleter.Cache = function(options) {
var data = {};
var length = 0;
function matchSubset(s, sub) {
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 ( typeof(value) === 'undefined' || 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 = $("<div/>")
.hide()
.addClass(options.resultsClass)
.css("position", "absolute")
.appendTo(document.body)
.hover(function(event) {
// Browsers except FF do not fire mouseup event on scrollbars, resulting in mouseDownOnSelect remaining true, and results list not always hiding.
if($(this).is(":visible")) {
input.focus();
}
config.mouseDownOnSelect = false;
});
list = $("<ul/>").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();
if( options.inputFocus )
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) {
if (options.scrollJumpPosition || (!options.scrollJumpPosition && !((step < 0 && active == 0) || (step > 0 && active == listItems.size() - 1)) )) {
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 = $("<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 - 9
}).show();
if(options.scroll) {
list.scrollTop(0);
list.css({
maxHeight: options.scrollHeight,
overflow: 'auto'
});
if(navigator.userAgent.indexOf("MSIE") != -1 && 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
}
}
};
})(jQuery);