diff options
Diffstat (limited to 'library')
-rw-r--r-- | library/justifiedGallery/dist/js/jquery.justifiedGallery.js | 1234 | ||||
-rw-r--r-- | library/stylish_select/index.html | 314 | ||||
-rw-r--r-- | library/stylish_select/jquery.stylish-select.js | 492 | ||||
-rwxr-xr-x | library/stylish_select/select-bg.png | bin | 0 -> 2438 bytes | |||
-rwxr-xr-x | library/stylish_select/stylish-select.css | 121 |
5 files changed, 1581 insertions, 580 deletions
diff --git a/library/justifiedGallery/dist/js/jquery.justifiedGallery.js b/library/justifiedGallery/dist/js/jquery.justifiedGallery.js index 9b5c66081..7754ae437 100644 --- a/library/justifiedGallery/dist/js/jquery.justifiedGallery.js +++ b/library/justifiedGallery/dist/js/jquery.justifiedGallery.js @@ -1,587 +1,661 @@ -/*! - * Justified Gallery - v3.2.0 +/* + * Justified Gallery - v3.4.0 * http://miromannino.com/projects/justified-gallery/ * Copyright (c) 2014 Miro Mannino * Licensed under the MIT license. */ (function($) { - /* Events - jg.complete : called when all the gallery has been created - jg.resize : called when the gallery has been resized - */ - - $.fn.justifiedGallery = function (arg) { - - // Default options - var defaults = { - sizeRangeSuffixes : { - 'lt100': '_t', - 'lt240': '_m', - 'lt320': '_n', - 'lt500': '', - 'lt640': '_z', - 'lt1024': '_b' - }, - rowHeight : 120, - maxRowHeight : 0, //negative value = no limits, 0 = 1.5 * rowHeight - margins : 1, - lastRow : 'nojustify', // or can be 'justify' or 'hide' - justifyThreshold: 0.75, /* if row width / available space > 0.75 it will be always justified - (i.e. lastRow setting is not considered) */ - fixedHeight : false, - captions : true, - cssAnimation: false, - imagesAnimationDuration : 300, //ignored with css animations - captionSettings : { //ignored with css animations - animationDuration : 500, - visibleOpacity : 0.7, - nonVisibleOpacity : 0.0 - }, - rel : null, //rewrite the rel of each analyzed links - target : null, //rewrite the target of all links - extension : /\.[^.]+$/, - refreshTime : 250, - randomize : false - }; - - function getSuffix(width, height, context) { - var longestSide; - longestSide = (width > height) ? width : height; - if (longestSide <= 100) { - return context.settings.sizeRangeSuffixes.lt100; - } else if (longestSide <= 240) { - return context.settings.sizeRangeSuffixes.lt240; - } else if (longestSide <= 320) { - return context.settings.sizeRangeSuffixes.lt320; - } else if (longestSide <= 500) { - return context.settings.sizeRangeSuffixes.lt500; - } else if (longestSide <= 640) { - return context.settings.sizeRangeSuffixes.lt640; - } else { - return context.settings.sizeRangeSuffixes.lt1024; - } - } - - function onEntryMouseEnterForCaption (ev) { - var $caption = $(ev.currentTarget).find('.caption'); - if (ev.data.settings.cssAnimation) { - $caption.addClass('caption-visible').removeClass('caption-hidden'); - } else { - $caption.stop().fadeTo(ev.data.settings.captionSettings.animationDuration, ev.data.settings.captionSettings.visibleOpacity); - } - } - - function onEntryMouseLeaveForCaption (ev) { - var $caption = $(ev.currentTarget).find('.caption'); - if (ev.data.settings.cssAnimation) { - $caption.removeClass('caption-visible').removeClass('caption-hidden'); - } else { - $caption.stop().fadeTo(ev.data.settings.captionSettings.animationDuration, ev.data.settings.captionSettings.nonVisibleOpacity); - } - } - - function displayEntry($entry, x, y, imgWidth, imgHeight, rowHeight, context) { - var $image = $entry.find('img'); - $image.css('width', imgWidth); - $image.css('height', imgHeight); - $image.css('margin-left', - imgWidth / 2); - $image.css('margin-top', - imgHeight / 2); - $entry.width(imgWidth); - $entry.height(rowHeight); - $entry.css('top', y); - $entry.css('left', x); - - //DEBUG// console.log('displayEntry: $image.width() = ' + $image.width() + ' $image.height() = ' + $image.height()); - - // Image reloading for an high quality of thumbnails - var imageSrc = $image.attr('src'); - var newImageSrc = imageSrc.replace(context.settings.extension, '').replace(context.usedSizeRangeRegExp, '') + - getSuffix(imgWidth, imgHeight, context) + - imageSrc.match(context.settings.extension)[0]; - - $image.one('error', function () { - //DEBUG// console.log('revert the original image'); - $image.attr('src', $image.data('jg.originalSrc')); //revert to the original thumbnail, we got it. - }); - - var loadNewImage = function () { - if (imageSrc !== newImageSrc) { //load the new image after the fadeIn - $image.attr('src', newImageSrc); - } - }; - - if (context.settings.cssAnimation) { - $entry.addClass('entry-visible'); - loadNewImage(); - } else { - $entry.stop().fadeTo(context.settings.imagesAnimationDuration, 1.0, loadNewImage); - } - - // Captions ------------------------------ - var captionMouseEvents = $entry.data('jg.captionMouseEvents'); - if (context.settings.captions === true) { - var $imgCaption = $entry.find('.caption'); - if ($imgCaption.length === 0) { // Create it if it doesn't exists - var caption = $image.attr('alt'); - if (typeof caption === 'undefined') caption = $entry.attr('title'); - if (typeof caption !== 'undefined') { // Create only we found something - $imgCaption = $('<div class="caption">' + caption + '</div>'); - $entry.append($imgCaption); - } - } - - // Create events (we check again the $imgCaption because it can be still inexistent) - if ($imgCaption.length !== 0) { - if (!context.settings.cssAnimation) { - $imgCaption.stop().fadeTo(context.settings.imagesAnimationDuration, context.settings.captionSettings.nonVisibleOpacity); - } - if (typeof captionMouseEvents === 'undefined') { - captionMouseEvents = { - mouseenter: onEntryMouseEnterForCaption, - mouseleave: onEntryMouseLeaveForCaption - }; - $entry.on('mouseenter', undefined, context, captionMouseEvents.mouseenter); - $entry.on('mouseleave', undefined, context, captionMouseEvents.mouseleave); - $entry.data('jg.captionMouseEvents', captionMouseEvents); - } - } - } else { - if (typeof captionMouseEvents !== 'undefined') { - $entry.off('mouseenter', undefined, context, captionMouseEvents.mouseenter); - $entry.off('mouseleave', undefined, context, captionMouseEvents.mouseleave); - $entry.removeData('jg.captionMouseEvents'); - } - } - - } - - function prepareBuildingRow(context, isLastRow) { - var i, $entry, $image, imgAspectRatio, newImgW, newImgH, justify = true; - var minHeight = 0; - var availableWidth = context.galleryWidth - ((context.buildingRow.entriesBuff.length - 1) * context.settings.margins); - var rowHeight = availableWidth / context.buildingRow.aspectRatio; - var justificable = context.buildingRow.width / availableWidth > context.settings.justifyThreshold; - - //Skip the last row if we can't justify it and the lastRow == 'hide' - if (isLastRow && context.settings.lastRow === 'hide' && !justificable) { - for (i = 0; i < context.buildingRow.entriesBuff.length; i++) { - $entry = context.buildingRow.entriesBuff[i]; - if (context.settings.cssAnimation) - $entry.removeClass('entry-visible'); - else - $entry.stop().fadeTo(0, 0); - } - return -1; - } - - // With lastRow = nojustify, justify if is justificable (the images will not become too big) - if (isLastRow && context.settings.lastRow === 'nojustify' && !justificable) justify = false; - - for (i = 0; i < context.buildingRow.entriesBuff.length; i++) { - $image = context.buildingRow.entriesBuff[i].find('img'); - imgAspectRatio = $image.data('jg.imgw') / $image.data('jg.imgh'); - - if (justify) { - newImgW = rowHeight * imgAspectRatio; - newImgH = rowHeight; - - /* With fixedHeight the newImgH must be greater than rowHeight. - In some cases here this is not satisfied (due to the justification). - But we comment it, because is better to have a shorter but justified row instead - to have a cropped image at the end. */ - /*if (context.settings.fixedHeight && newImgH < context.settings.rowHeight) { - newImgW = context.settings.rowHeight * imgAspectRatio; - newImgH = context.settings.rowHeight; - }*/ - } else { - newImgW = context.settings.rowHeight * imgAspectRatio; - newImgH = context.settings.rowHeight; - } - - $image.data('jg.imgw', Math.ceil(newImgW)); - $image.data('jg.imgh', Math.ceil(newImgH)); - if (i === 0 || minHeight > newImgH) minHeight = newImgH; - } - - if (context.settings.fixedHeight && minHeight > context.settings.rowHeight) - minHeight = context.settings.rowHeight; - - return minHeight; - } - - function rewind(context) { - context.lastAnalyzedIndex = -1; - context.buildingRow.entriesBuff = []; - context.buildingRow.aspectRatio = 0; - context.buildingRow.width = 0; - context.offY = 0; - context.firstRowFlushed = false; - } - - function flushRow(context, isLastRow) { - var $entry, $image, minHeight, offX = 0; - - //DEBUG// console.log('flush (width: ' + context.buildingRow.width + ', galleryWidth: ' + context.galleryWidth + ', ' + 'isLastRow: ' + isLastRow + ')'); - - minHeight = prepareBuildingRow(context, isLastRow); - if (isLastRow && context.settings.lastRow === 'hide' && minHeight === -1) { - context.buildingRow.entriesBuff = []; - context.buildingRow.aspectRatio = 0; - context.buildingRow.width = 0; - return; - } - - if (context.settings.maxRowHeight > 0 && context.settings.maxRowHeight < minHeight) - minHeight = context.settings.maxRowHeight; - else if (context.settings.maxRowHeight === 0 && (1.5 * context.settings.rowHeight) < minHeight) - minHeight = 1.5 * context.settings.rowHeight; - - for (var i = 0; i < context.buildingRow.entriesBuff.length; i++) { - $entry = context.buildingRow.entriesBuff[i]; - $image = $entry.find('img'); - displayEntry($entry, offX, context.offY, $image.data('jg.imgw'), $image.data('jg.imgh'), minHeight, context); - offX += $image.data('jg.imgw') + context.settings.margins; - } - - //Gallery Height - context.$gallery.height(context.offY + minHeight + - (context.spinner.active ? context.spinner.$el.innerHeight() : 0) - ); - - if(!isLastRow) { - //Ready for a new row - context.offY += minHeight + context.settings.margins; - - //DEBUG// console.log('minHeight: ' + minHeight + ' offY: ' + context.offY); - - context.buildingRow.entriesBuff = []; //clear the array creating a new one - context.buildingRow.aspectRatio = 0; - context.buildingRow.width = 0; - context.firstRowFlushed = true; - context.$gallery.trigger('jg.rowflush'); - } - } - - function checkWidth(context) { - context.checkWidthIntervalId = setInterval(function () { - var galleryWidth = parseInt(context.$gallery.width(), 10); - if (context.galleryWidth !== galleryWidth) { - //DEBUG// console.log("resize. old: " + context.galleryWidth + " new: " + galleryWidth); - - context.galleryWidth = galleryWidth; - rewind(context); - - // Restart to analyze - startImgAnalyzer(context, true); - } - }, context.settings.refreshTime); - } - - function startLoadingSpinnerAnimation(spinnerContext) { - clearInterval(spinnerContext.intervalId); - spinnerContext.intervalId = setInterval(function () { - if (spinnerContext.phase < spinnerContext.$points.length) - spinnerContext.$points.eq(spinnerContext.phase).fadeTo(spinnerContext.timeslot, 1); - else - spinnerContext.$points.eq(spinnerContext.phase - spinnerContext.$points.length).fadeTo(spinnerContext.timeslot, 0); - spinnerContext.phase = (spinnerContext.phase + 1) % (spinnerContext.$points.length * 2); - }, spinnerContext.timeslot); - } - - function stopLoadingSpinnerAnimation(spinnerContext) { - clearInterval(spinnerContext.intervalId); - spinnerContext.intervalId = null; - } - - function stopImgAnalyzerStarter(context) { - context.yield.flushed = 0; - if (context.imgAnalyzerTimeout !== null) clearTimeout(context.imgAnalyzerTimeout); - } - - function startImgAnalyzer(context, isForResize) { - stopImgAnalyzerStarter(context); - context.imgAnalyzerTimeout = setTimeout(function () { analyzeImages(context, isForResize); }, 0.001); - analyzeImages(context, isForResize); - } - - function analyzeImages(context, isForResize) { - - //DEBUG// - /*var rnd = parseInt(Math.random() * 10000, 10); - //DEBUG// console.log('analyzeImages ' + rnd + ' start'); - //DEBUG// console.log('images status: '); - for (var i = 0; i < context.entries.length; i++) { - var $entry = $(context.entries[i]); - var $image = $entry.find('img'); - //DEBUG// console.log(i + ' (alt: ' + $image.attr('alt') + 'loaded: ' + $image.data('jg.loaded') + ')'); - }*/ - - /* The first row */ - var isLastRow; - - for (var i = context.lastAnalyzedIndex + 1; i < context.entries.length; i++) { - var $entry = $(context.entries[i]); - var $image = $entry.find('img'); - - if ($image.data('jg.loaded') === true) { - isLastRow = i >= context.entries.length - 1; - - var availableWidth = context.galleryWidth - ((context.buildingRow.entriesBuff.length - 1) * context.settings.margins); - var imgAspectRatio = $image.data('jg.imgw') / $image.data('jg.imgh'); - if (availableWidth / (context.buildingRow.aspectRatio + imgAspectRatio) < context.settings.rowHeight) { - flushRow(context, isLastRow); - - if(++context.yield.flushed >= context.yield.every) { - //DEBUG// console.log("yield"); - startImgAnalyzer(context, isForResize); - return; - } - } - - context.buildingRow.entriesBuff.push($entry); - context.buildingRow.aspectRatio += imgAspectRatio; - context.buildingRow.width += imgAspectRatio * context.settings.rowHeight; - context.lastAnalyzedIndex = i; - - } else if ($image.data('jg.loaded') !== 'error') { - return; - } - } - - // Last row flush (the row is not full) - if (context.buildingRow.entriesBuff.length > 0) flushRow(context, isLastRow); - - if (context.spinner.active) { - context.spinner.active = false; - context.$gallery.height(context.$gallery.height() - context.spinner.$el.innerHeight()); - context.spinner.$el.detach(); - stopLoadingSpinnerAnimation(context.spinner); - } - - /* Stop, if there is, the timeout to start the analyzeImages. - This is because an image can be set loaded, and the timeout can be set, - but this image can be analyzed yet. - */ - stopImgAnalyzerStarter(context); - - //On complete callback - if (!isForResize) context.$gallery.trigger('jg.complete'); else context.$gallery.trigger('jg.resize'); - - //DEBUG// console.log('analyzeImages ' + rnd + ' end'); - } - - function checkSettings (context) { - - function checkSuffixesRange(range) { - if (typeof context.settings.sizeRangeSuffixes[range] !== 'string') - throw 'sizeRangeSuffixes.' + range + ' must be a string'; - } - - function checkOrConvertNumber(parent, settingName) { - if (typeof parent[settingName] === 'string') { - parent[settingName] = parseFloat(parent[settingName], 10); - if (isNaN(parent[settingName])) throw 'invalid number for ' + settingName; - } else if (typeof parent[settingName] === 'number') { - if (isNaN(parent[settingName])) throw 'invalid number for ' + settingName; - } else { - throw settingName + ' must be a number'; - } - } - - if (typeof context.settings.sizeRangeSuffixes !== 'object') - throw 'sizeRangeSuffixes must be defined and must be an object'; - - checkSuffixesRange('lt100'); - checkSuffixesRange('lt240'); - checkSuffixesRange('lt320'); - checkSuffixesRange('lt500'); - checkSuffixesRange('lt640'); - checkSuffixesRange('lt1024'); - - checkOrConvertNumber(context.settings, 'rowHeight'); - checkOrConvertNumber(context.settings, 'maxRowHeight'); - checkOrConvertNumber(context.settings, 'margins'); - - if (context.settings.lastRow !== 'nojustify' && - context.settings.lastRow !== 'justify' && - context.settings.lastRow !== 'hide') { - throw 'lastRow must be "nojustify", "justify" or "hide"'; - } - - checkOrConvertNumber(context.settings, 'justifyThreshold'); - if (context.settings.justifyThreshold < 0 || context.settings.justifyThreshold > 1) - throw 'justifyThreshold must be in the interval [0,1]'; - if (typeof context.settings.cssAnimation !== 'boolean') { - throw 'cssAnimation must be a boolean'; - } - - checkOrConvertNumber(context.settings.captionSettings, 'animationDuration'); - checkOrConvertNumber(context.settings, 'imagesAnimationDuration'); - - checkOrConvertNumber(context.settings.captionSettings, 'visibleOpacity'); - if (context.settings.captionSettings.visibleOpacity < 0 || context.settings.captionSettings.visibleOpacity > 1) - throw 'captionSettings.visibleOpacity must be in the interval [0, 1]'; - - checkOrConvertNumber(context.settings.captionSettings, 'nonVisibleOpacity'); - if (context.settings.captionSettings.visibleOpacity < 0 || context.settings.captionSettings.visibleOpacity > 1) - throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]'; - - if (typeof context.settings.fixedHeight !== 'boolean') { - throw 'fixedHeight must be a boolean'; - } - - if (typeof context.settings.captions !== 'boolean') { - throw 'captions must be a boolean'; - } - - checkOrConvertNumber(context.settings, 'refreshTime'); - - if (typeof context.settings.randomize !== 'boolean') { - throw 'randomize must be a boolean'; - } - - } - - return this.each(function (index, gallery) { - - var $gallery = $(gallery); - $gallery.addClass('justified-gallery'); - - var context = $gallery.data('jg.context'); - if (typeof context === 'undefined') { - - if (typeof arg !== 'undefined' && arg !== null && typeof arg !== 'object') - throw 'The argument must be an object'; - - // Spinner init - var $spinner = $('<div class="spinner"><span></span><span></span><span></span></div>'); - - //Context init - context = { - settings : $.extend({}, defaults, arg), - imgAnalyzerTimeout : null, - entries : null, - buildingRow : { - entriesBuff : [], - width : 0, - aspectRatio : 0 - }, - lastAnalyzedIndex : -1, - firstRowFlushed : false, - yield : { - every : 2, /* do a flush every context.yield.every flushes ( - * must be greater than 1, else the analyzeImages will loop */ - flushed : 0 //flushed rows without a yield - }, - offY : 0, - spinner : { - active : false, - phase : 0, - timeslot : 150, - $el : $spinner, - $points : $spinner.find('span'), - intervalId : null - }, - checkWidthIntervalId : null, - galleryWidth : $gallery.width(), - $gallery : $gallery - }; - - $gallery.data('jg.context', context); - - } else if (arg === 'norewind') { - // In this case we don't rewind, and analyze all the images - } else { - context.settings = $.extend({}, context.settings, arg); - rewind(context); - } - - checkSettings(context); - - context.entries = $gallery.find('> a, > div').toArray(); - if (context.entries.length === 0) return; - - // Randomize - if (context.settings.randomize) { - context.entries.sort(function () { return Math.random() * 2 - 1; }); - $.each(context.entries, function () { - $(this).appendTo($gallery); - }); - } - - context.usedSizeRangeRegExp = new RegExp("(" + - context.settings.sizeRangeSuffixes.lt100 + "|" + - context.settings.sizeRangeSuffixes.lt240 + "|" + - context.settings.sizeRangeSuffixes.lt320 + "|" + - context.settings.sizeRangeSuffixes.lt500 + "|" + - context.settings.sizeRangeSuffixes.lt640 + "|" + - context.settings.sizeRangeSuffixes.lt1024 + ")$" - ); - - if (context.settings.maxRowHeight > 0 && context.settings.maxRowHeight < context.settings.rowHeight) - context.settings.maxRowHeight = context.settings.rowHeight; - - var imagesToLoad = false; - $.each(context.entries, function (index, entry) { - var $entry = $(entry); - var $image = $entry.find('img'); - - if ($image.data('jg.loaded') !== true) { - $image.data('jg.loaded', false); - - //DEBUG// console.log('listed ' + $image.attr('alt')); - - imagesToLoad = true; - - // Spinner start - if (context.spinner.active === false) { - context.spinner.active = true; - $gallery.append(context.spinner.$el); - $gallery.height(context.offY + context.spinner.$el.innerHeight()); - startLoadingSpinnerAnimation(context.spinner); - } - - // Link Rel global overwrite - if (context.settings.rel !== null) $entry.attr('rel', context.settings.rel); - - // Link Target global overwrite - if (context.settings.target !== null) $entry.attr('target', context.settings.target); - - // Image src - var imageSrc = (typeof $image.data('safe-src') !== 'undefined') ? $image.data('safe-src') : $image.attr('src'); - $image.data('jg.originalSrc', imageSrc); - $image.attr('src', imageSrc); - - /* Check if the image is loaded or not using another image object. - We cannot use the 'complete' image property, because some browsers, - with a 404 set complete = true */ - var loadImg = new Image(); - var $loadImg = $(loadImg); - $loadImg.one('load', function imgLoaded () { - //DEBUG// console.log('img load (alt: ' + $image.attr('alt') + ')'); - $image.off('load error'); - $image.data('jg.imgw', loadImg.width); - $image.data('jg.imgh', loadImg.height); - $image.data('jg.loaded', true); - startImgAnalyzer(context, false); - }); - $loadImg.one('error', function imgLoadError () { - //DEBUG// console.log('img error (alt: ' + $image.attr('alt') + ')'); - $image.off('load error'); - $image.data('jg.loaded', 'error'); - startImgAnalyzer(context, false); - }); - loadImg.src = imageSrc; - - } - - }); - - if (!imagesToLoad) startImgAnalyzer(context, false); - checkWidth(context); - }); - - }; - + /* Events + jg.complete : called when all the gallery has been created + jg.resize : called when the gallery has been resized + */ + + $.fn.justifiedGallery = function (arg) { + + // Default options + var defaults = { + sizeRangeSuffixes : { + 'lt100': '_t', + 'lt240': '_m', + 'lt320': '_n', + 'lt500': '', + 'lt640': '_z', + 'lt1024': '_b' + }, + rowHeight : 120, + maxRowHeight : 0, //negative value = no limits, 0 = 1.5 * rowHeight + margins : 1, + lastRow : 'nojustify', // or can be 'justify' or 'hide' + justifyThreshold: 0.75, /* if row width / available space > 0.75 it will be always justified + (i.e. lastRow setting is not considered) */ + fixedHeight : false, + waitThumbnailsLoad : true, + captions : true, + cssAnimation: false, + imagesAnimationDuration : 500, //ignored with css animations + captionSettings : { //ignored with css animations + animationDuration : 500, + visibleOpacity : 0.7, + nonVisibleOpacity : 0.0 + }, + rel : null, //rewrite the rel of each analyzed links + target : null, //rewrite the target of all links + extension : /\.[^.\\/]+$/, + refreshTime : 100, + randomize : false + }; + + function getSuffix(width, height, context) { + var longestSide; + longestSide = (width > height) ? width : height; + if (longestSide <= 100) { + return context.settings.sizeRangeSuffixes.lt100; + } else if (longestSide <= 240) { + return context.settings.sizeRangeSuffixes.lt240; + } else if (longestSide <= 320) { + return context.settings.sizeRangeSuffixes.lt320; + } else if (longestSide <= 500) { + return context.settings.sizeRangeSuffixes.lt500; + } else if (longestSide <= 640) { + return context.settings.sizeRangeSuffixes.lt640; + } else { + return context.settings.sizeRangeSuffixes.lt1024; + } + } + + function endsWith(str, suffix) { + return str.indexOf(suffix, str.length - suffix.length) !== -1; + } + + function removeSuffix(str, suffix) { + return str.substring(0, str.length - suffix.length); + } + + function getUsedSuffix(str, context) { + var voidSuffix = false; + for (var si in context.settings.sizeRangeSuffixes) { + if (context.settings.sizeRangeSuffixes[si].length === 0) { + voidSuffix = true; + continue; + } + if (endsWith(str, context.settings.sizeRangeSuffixes[si])) { + return context.settings.sizeRangeSuffixes[si]; + } + } + + if (voidSuffix) return ""; + else throw 'unknown suffix for ' + str; + } + + /* Given an image src, with the width and the height, returns the new image src with the + best suffix to show the best quality thumbnail. */ + function newSrc(imageSrc, imgWidth, imgHeight, context) { + var matchRes = imageSrc.match(context.settings.extension); + var ext = (matchRes != null) ? matchRes[0] : ''; + var newImageSrc = imageSrc.replace(context.settings.extension, ''); + newImageSrc = removeSuffix(newImageSrc, getUsedSuffix(newImageSrc, context)); + newImageSrc += getSuffix(imgWidth, imgHeight, context) + ext; + return newImageSrc; + } + + function onEntryMouseEnterForCaption (ev) { + var $caption = $(ev.currentTarget).find('.caption'); + if (ev.data.settings.cssAnimation) { + $caption.addClass('caption-visible').removeClass('caption-hidden'); + } else { + $caption.stop().fadeTo(ev.data.settings.captionSettings.animationDuration, + ev.data.settings.captionSettings.visibleOpacity); + } + } + + function onEntryMouseLeaveForCaption (ev) { + var $caption = $(ev.currentTarget).find('.caption'); + if (ev.data.settings.cssAnimation) { + $caption.removeClass('caption-visible').removeClass('caption-hidden'); + } else { + $caption.stop().fadeTo(ev.data.settings.captionSettings.animationDuration, + ev.data.settings.captionSettings.nonVisibleOpacity); + } + } + + function showImg($entry, callback, context) { + if (context.settings.cssAnimation) { + $entry.addClass('entry-visible'); + callback(); + } else { + $entry.stop().fadeTo(context.settings.imagesAnimationDuration, 1.0, callback); + } + } + + function hideImgImmediately($entry, context) { + if (context.settings.cssAnimation) { + $entry.removeClass('entry-visible'); + } else { + $entry.stop().fadeTo(0, 0); + } + } + + function displayEntry($entry, x, y, imgWidth, imgHeight, rowHeight, context) { + var $image = $entry.find('img'); + $image.css('width', imgWidth); + $image.css('height', imgHeight); + $image.css('margin-left', - imgWidth / 2); + $image.css('margin-top', - imgHeight / 2); + $entry.width(imgWidth); + $entry.height(rowHeight); + $entry.css('top', y); + $entry.css('left', x); + + //DEBUG// console.log('displayEntry (w: ' + $image.width() + ' h: ' + $image.height()); + + // Image reloading for an high quality of thumbnails + var imageSrc = $image.attr('src'); + var newImageSrc = newSrc(imageSrc, imgWidth, imgHeight, context); + + $image.one('error', function () { + //DEBUG// console.log('revert the original image'); + $image.attr('src', $image.data('jg.originalSrc')); //revert to the original thumbnail, we got it. + }); + + function loadNewImage() { + if (imageSrc !== newImageSrc) { //load the new image after the fadeIn + $image.attr('src', newImageSrc); + } + } + + if ($image.data('jg.loaded') === 'skipped') { + $image.one('load', function() { + showImg($entry, loadNewImage, context); + $image.data('jg.loaded', 'loaded'); + }); + } else { + showImg($entry, loadNewImage, context); + } + + // Captions ------------------------------ + var captionMouseEvents = $entry.data('jg.captionMouseEvents'); + if (context.settings.captions === true) { + var $imgCaption = $entry.find('.caption'); + if ($imgCaption.length === 0) { // Create it if it doesn't exists + var caption = $image.attr('alt'); + if (typeof caption === 'undefined') caption = $entry.attr('title'); + if (typeof caption !== 'undefined') { // Create only we found something + $imgCaption = $('<div class="caption">' + caption + '</div>'); + $entry.append($imgCaption); + } + } + + // Create events (we check again the $imgCaption because it can be still inexistent) + if ($imgCaption.length !== 0) { + if (!context.settings.cssAnimation) { + $imgCaption.stop().fadeTo(context.settings.imagesAnimationDuration, + context.settings.captionSettings.nonVisibleOpacity); + } + if (typeof captionMouseEvents === 'undefined') { + captionMouseEvents = { + mouseenter: onEntryMouseEnterForCaption, + mouseleave: onEntryMouseLeaveForCaption + }; + $entry.on('mouseenter', undefined, context, captionMouseEvents.mouseenter); + $entry.on('mouseleave', undefined, context, captionMouseEvents.mouseleave); + $entry.data('jg.captionMouseEvents', captionMouseEvents); + } + } + } else { + if (typeof captionMouseEvents !== 'undefined') { + $entry.off('mouseenter', undefined, context, captionMouseEvents.mouseenter); + $entry.off('mouseleave', undefined, context, captionMouseEvents.mouseleave); + $entry.removeData('jg.captionMouseEvents'); + } + } + + } + + function prepareBuildingRow(context, isLastRow) { + var settings = context.settings; + var i, $entry, $image, imgAspectRatio, newImgW, newImgH, justify = true; + var minHeight = 0; + var availableWidth = context.galleryWidth - ( + (context.buildingRow.entriesBuff.length - 1) * settings.margins); + var rowHeight = availableWidth / context.buildingRow.aspectRatio; + var justificable = context.buildingRow.width / availableWidth > settings.justifyThreshold; + + //Skip the last row if we can't justify it and the lastRow == 'hide' + if (isLastRow && settings.lastRow === 'hide' && !justificable) { + for (i = 0; i < context.buildingRow.entriesBuff.length; i++) { + $entry = context.buildingRow.entriesBuff[i]; + if (settings.cssAnimation) + $entry.removeClass('entry-visible'); + else + $entry.stop().fadeTo(0, 0); + } + return -1; + } + + // With lastRow = nojustify, justify if is justificable (the images will not become too big) + if (isLastRow && !justificable && settings.lastRow === 'nojustify') justify = false; + + for (i = 0; i < context.buildingRow.entriesBuff.length; i++) { + $image = context.buildingRow.entriesBuff[i].find('img'); + imgAspectRatio = $image.data('jg.imgw') / $image.data('jg.imgh'); + + if (justify) { + newImgW = rowHeight * imgAspectRatio; + newImgH = rowHeight; + + /* With fixedHeight the newImgH must be greater than rowHeight. + In some cases here this is not satisfied (due to the justification). + But we comment it, because is better to have a shorter but justified row instead + to have a cropped image at the end. */ + /*if (settings.fixedHeight && newImgH < settings.rowHeight) { + newImgW = settings.rowHeight * imgAspectRatio; + newImgH = settings.rowHeight; + }*/ + } else { + newImgW = settings.rowHeight * imgAspectRatio; + newImgH = settings.rowHeight; + } + + $image.data('jg.imgw', Math.ceil(newImgW)); + $image.data('jg.imgh', Math.ceil(newImgH)); + if (i === 0 || minHeight > newImgH) minHeight = newImgH; + } + + if (settings.fixedHeight && minHeight > settings.rowHeight) + minHeight = settings.rowHeight; + + return {minHeight: minHeight, justify: justify}; + } + + function rewind(context) { + context.lastAnalyzedIndex = -1; + context.buildingRow.entriesBuff = []; + context.buildingRow.aspectRatio = 0; + context.buildingRow.width = 0; + context.offY = 0; + } + + function flushRow(context, isLastRow) { + var settings = context.settings; + var $entry, $image, minHeight, buildingRowRes, offX = 0; + + //DEBUG// console.log('flush (isLastRow: ' + isLastRow + ')'); + + buildingRowRes = prepareBuildingRow(context, isLastRow); + minHeight = buildingRowRes.minHeight; + if (isLastRow && settings.lastRow === 'hide' && minHeight === -1) { + context.buildingRow.entriesBuff = []; + context.buildingRow.aspectRatio = 0; + context.buildingRow.width = 0; + return; + } + + if (settings.maxRowHeight > 0 && settings.maxRowHeight < minHeight) + minHeight = settings.maxRowHeight; + else if (settings.maxRowHeight === 0 && (1.5 * settings.rowHeight) < minHeight) + minHeight = 1.5 * settings.rowHeight; + + for (var i = 0; i < context.buildingRow.entriesBuff.length; i++) { + $entry = context.buildingRow.entriesBuff[i]; + $image = $entry.find('img'); + displayEntry($entry, offX, context.offY, $image.data('jg.imgw'), + $image.data('jg.imgh'), minHeight, context); + offX += $image.data('jg.imgw') + settings.margins; + } + + //Gallery Height + context.$gallery.height(context.offY + minHeight + + (context.spinner.active ? context.spinner.$el.innerHeight() : 0) + ); + + if (!isLastRow || (minHeight <= context.settings.rowHeight && buildingRowRes.justify)) { + //Ready for a new row + context.offY += minHeight + context.settings.margins; + + //DEBUG// console.log('minHeight: ' + minHeight + ' offY: ' + context.offY); + + context.buildingRow.entriesBuff = []; //clear the array creating a new one + context.buildingRow.aspectRatio = 0; + context.buildingRow.width = 0; + context.$gallery.trigger('jg.rowflush'); + } + } + + function checkWidth(context) { + context.checkWidthIntervalId = setInterval(function () { + var galleryWidth = parseInt(context.$gallery.width(), 10); + if (context.galleryWidth !== galleryWidth) { + //DEBUG// console.log("resize. old: " + context.galleryWidth + " new: " + galleryWidth); + + context.galleryWidth = galleryWidth; + rewind(context); + + // Restart to analyze + startImgAnalyzer(context, true); + } + }, context.settings.refreshTime); + } + + function startLoadingSpinnerAnimation(spinnerContext) { + clearInterval(spinnerContext.intervalId); + spinnerContext.intervalId = setInterval(function () { + if (spinnerContext.phase < spinnerContext.$points.length) + spinnerContext.$points.eq(spinnerContext.phase).fadeTo(spinnerContext.timeslot, 1); + else + spinnerContext.$points.eq(spinnerContext.phase - spinnerContext.$points.length) + .fadeTo(spinnerContext.timeslot, 0); + spinnerContext.phase = (spinnerContext.phase + 1) % (spinnerContext.$points.length * 2); + }, spinnerContext.timeslot); + } + + function stopLoadingSpinnerAnimation(spinnerContext) { + clearInterval(spinnerContext.intervalId); + spinnerContext.intervalId = null; + } + + function stopImgAnalyzerStarter(context) { + context.yield.flushed = 0; + if (context.imgAnalyzerTimeout !== null) clearTimeout(context.imgAnalyzerTimeout); + } + + function startImgAnalyzer(context, isForResize) { + stopImgAnalyzerStarter(context); + context.imgAnalyzerTimeout = setTimeout(function () { + analyzeImages(context, isForResize); + }, 0.001); + analyzeImages(context, isForResize); + } + + function analyzeImages(context, isForResize) { + + /* //DEBUG// + var rnd = parseInt(Math.random() * 10000, 10); + console.log('analyzeImages ' + rnd + ' start'); + console.log('images status: '); + for (var i = 0; i < context.entries.length; i++) { + var $entry = $(context.entries[i]); + var $image = $entry.find('img'); + console.log(i + ' (alt: ' + $image.attr('alt') + 'loaded: ' + $image.data('jg.loaded') + ')'); + }*/ + + /* The first row */ + var settings = context.settings; + var isLastRow; + + for (var i = context.lastAnalyzedIndex + 1; i < context.entries.length; i++) { + var $entry = $(context.entries[i]); + var $image = $entry.find('img'); + + if ($image.data('jg.loaded') === true || $image.data('jg.loaded') === 'skipped') { + isLastRow = i >= context.entries.length - 1; + + var availableWidth = context.galleryWidth - ( + (context.buildingRow.entriesBuff.length - 1) * settings.margins); + var imgAspectRatio = $image.data('jg.imgw') / $image.data('jg.imgh'); + if (availableWidth / (context.buildingRow.aspectRatio + imgAspectRatio) < settings.rowHeight) { + flushRow(context, isLastRow); + if(++context.yield.flushed >= context.yield.every) { + //DEBUG// console.log("yield"); + startImgAnalyzer(context, isForResize); + return; + } + } + + context.buildingRow.entriesBuff.push($entry); + context.buildingRow.aspectRatio += imgAspectRatio; + context.buildingRow.width += imgAspectRatio * settings.rowHeight; + context.lastAnalyzedIndex = i; + + } else if ($image.data('jg.loaded') !== 'error') { + return; + } + } + + // Last row flush (the row is not full) + if (context.buildingRow.entriesBuff.length > 0) flushRow(context, true); + + if (context.spinner.active) { + context.spinner.active = false; + context.$gallery.height(context.$gallery.height() - context.spinner.$el.innerHeight()); + context.spinner.$el.detach(); + stopLoadingSpinnerAnimation(context.spinner); + } + + /* Stop, if there is, the timeout to start the analyzeImages. + This is because an image can be set loaded, and the timeout can be set, + but this image can be analyzed yet. + */ + stopImgAnalyzerStarter(context); + + //On complete callback + if (!isForResize) + context.$gallery.trigger('jg.complete'); + else + context.$gallery.trigger('jg.resize'); + + //DEBUG// console.log('analyzeImages ' + rnd + ' end'); + } + + function checkSettings (context) { + var settings = context.settings; + + function checkSuffixesRange(range) { + if (typeof settings.sizeRangeSuffixes[range] !== 'string') + throw 'sizeRangeSuffixes.' + range + ' must be a string'; + } + + function checkOrConvertNumber(parent, settingName) { + if (typeof parent[settingName] === 'string') { + parent[settingName] = parseFloat(parent[settingName], 10); + if (isNaN(parent[settingName])) throw 'invalid number for ' + settingName; + } else if (typeof parent[settingName] === 'number') { + if (isNaN(parent[settingName])) throw 'invalid number for ' + settingName; + } else { + throw settingName + ' must be a number'; + } + } + + if (typeof settings.sizeRangeSuffixes !== 'object') + throw 'sizeRangeSuffixes must be defined and must be an object'; + + checkSuffixesRange('lt100'); + checkSuffixesRange('lt240'); + checkSuffixesRange('lt320'); + checkSuffixesRange('lt500'); + checkSuffixesRange('lt640'); + checkSuffixesRange('lt1024'); + + checkOrConvertNumber(settings, 'rowHeight'); + checkOrConvertNumber(settings, 'maxRowHeight'); + + if (settings.maxRowHeight > 0 && + settings.maxRowHeight < settings.rowHeight) { + settings.maxRowHeight = settings.rowHeight; + } + + checkOrConvertNumber(settings, 'margins'); + + if (settings.lastRow !== 'nojustify' && + settings.lastRow !== 'justify' && + settings.lastRow !== 'hide') { + throw 'lastRow must be "nojustify", "justify" or "hide"'; + } + + checkOrConvertNumber(settings, 'justifyThreshold'); + if (settings.justifyThreshold < 0 || settings.justifyThreshold > 1) + throw 'justifyThreshold must be in the interval [0,1]'; + if (typeof settings.cssAnimation !== 'boolean') { + throw 'cssAnimation must be a boolean'; + } + + checkOrConvertNumber(settings.captionSettings, 'animationDuration'); + checkOrConvertNumber(settings, 'imagesAnimationDuration'); + + checkOrConvertNumber(settings.captionSettings, 'visibleOpacity'); + if (settings.captionSettings.visibleOpacity < 0 || settings.captionSettings.visibleOpacity > 1) + throw 'captionSettings.visibleOpacity must be in the interval [0, 1]'; + + checkOrConvertNumber(settings.captionSettings, 'nonVisibleOpacity'); + if (settings.captionSettings.visibleOpacity < 0 || settings.captionSettings.visibleOpacity > 1) + throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]'; + + if (typeof settings.fixedHeight !== 'boolean') { + throw 'fixedHeight must be a boolean'; + } + + if (typeof settings.captions !== 'boolean') { + throw 'captions must be a boolean'; + } + + checkOrConvertNumber(settings, 'refreshTime'); + + if (typeof settings.randomize !== 'boolean') { + throw 'randomize must be a boolean'; + } + + } + + return this.each(function (index, gallery) { + + var $gallery = $(gallery); + $gallery.addClass('justified-gallery'); + + var context = $gallery.data('jg.context'); + if (typeof context === 'undefined') { + + if (typeof arg !== 'undefined' && arg !== null && typeof arg !== 'object') + throw 'The argument must be an object'; + + // Spinner init + var $spinner = $('<div class="spinner"><span></span><span></span><span></span></div>'); + + //Context init + context = { + settings : $.extend({}, defaults, arg), + imgAnalyzerTimeout : null, + entries : null, + buildingRow : { + entriesBuff : [], + width : 0, + aspectRatio : 0 + }, + lastAnalyzedIndex : -1, + yield : { + every : 2, /* do a flush every context.yield.every flushes ( + * must be greater than 1, else the analyzeImages will loop */ + flushed : 0 //flushed rows without a yield + }, + offY : 0, + spinner : { + active : false, + phase : 0, + timeslot : 150, + $el : $spinner, + $points : $spinner.find('span'), + intervalId : null + }, + checkWidthIntervalId : null, + galleryWidth : $gallery.width(), + $gallery : $gallery + }; + + $gallery.data('jg.context', context); + + } else if (arg === 'norewind') { + /* Hide the image of the buildingRow to prevent strange effects when the row will be + re-justified again */ + for (var i = 0; i < context.buildingRow.entriesBuff.length; i++) { + hideImgImmediately(context.buildingRow.entriesBuff[i], context); + } + // In this case we don't rewind, and analyze all the images + } else { + context.settings = $.extend({}, context.settings, arg); + rewind(context); + } + + checkSettings(context); + + context.entries = $gallery.find('> a, > div:not(.spinner, #page-end)').toArray(); + if (context.entries.length === 0) return; + + // Randomize + if (context.settings.randomize) { + context.entries.sort(function () { return Math.random() * 2 - 1; }); + $.each(context.entries, function () { + $(this).appendTo($gallery); + }); + } + + var imagesToLoad = false; + $.each(context.entries, function (index, entry) { + var $entry = $(entry); + var $image = $entry.find('img'); + + if ($image.data('jg.loaded') !== true && $image.data('jg.loaded') !== 'skipped') { + + // Link Rel global overwrite + if (context.settings.rel !== null) $entry.attr('rel', context.settings.rel); + + // Link Target global overwrite + if (context.settings.target !== null) $entry.attr('target', context.settings.target); + + // Image src + var imageSrc = (typeof $image.data('safe-src') !== 'undefined') ? + $image.data('safe-src') : $image.attr('src'); + $image.data('jg.originalSrc', imageSrc); + $image.attr('src', imageSrc); + + var width = parseInt($image.attr('width'), 10); + var height = parseInt($image.attr('height'), 10); + if(context.settings.waitThumbnailsLoad !== true && !isNaN(width) && !isNaN(height)) { + $image.data('jg.imgw', width); + $image.data('jg.imgh', height); + $image.data('jg.loaded', 'skipped'); + startImgAnalyzer(context, false); + return true; + } + + $image.data('jg.loaded', false); + imagesToLoad = true; + + // Spinner start + if (context.spinner.active === false) { + context.spinner.active = true; + $gallery.append(context.spinner.$el); + $gallery.height(context.offY + context.spinner.$el.innerHeight()); + startLoadingSpinnerAnimation(context.spinner); + } + + /* Check if the image is loaded or not using another image object. + We cannot use the 'complete' image property, because some browsers, + with a 404 set complete = true */ + var loadImg = new Image(); + var $loadImg = $(loadImg); + $loadImg.one('load', function imgLoaded () { + //DEBUG// console.log('img load (alt: ' + $image.attr('alt') + ')'); + $image.off('load error'); + $image.data('jg.imgw', loadImg.width); + $image.data('jg.imgh', loadImg.height); + $image.data('jg.loaded', true); + startImgAnalyzer(context, false); + }); + $loadImg.one('error', function imgLoadError () { + //DEBUG// console.log('img error (alt: ' + $image.attr('alt') + ')'); + $image.off('load error'); + $image.data('jg.loaded', 'error'); + startImgAnalyzer(context, false); + }); + loadImg.src = imageSrc; + + } + + }); + + if (!imagesToLoad) startImgAnalyzer(context, false); + checkWidth(context); + }); + + }; + }(jQuery)); diff --git a/library/stylish_select/index.html b/library/stylish_select/index.html new file mode 100644 index 000000000..b711c09f6 --- /dev/null +++ b/library/stylish_select/index.html @@ -0,0 +1,314 @@ +<!DOCTYPE html> +<html> + <head> + <title>jQuery Stylish Select 0.4.9 plugin examples</title> + <meta http-equiv="content-type" content="text/html;charset=utf-8" /> + <link rel="stylesheet" type="text/css" href="stylish-select.css" /> + + <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script> + <script src="jquery.stylish-select.js" type="text/javascript"></script> + + <script type="text/javascript"> + $(function(){ + + $('#my-dropdown, #my-dropdown2, #my-dropdown3, #my-dropdown4, #my-dropdown5, #my-dropdown6, #my-dropdown7, #my-dropdown8, #my-dropdown9').sSelect(); + + //set max height + $('#my-dropdownCountries').sSelect({ddMaxHeight: '300px'}); + + //set value on click + $('#setVal').click(function(){ + $('#my-dropdown5').getSetSSValue('4'); + }); + + //get value on click + $('#getVal').click(function(){ + alert('The value is: '+$('#my-dropdown5').getSetSSValue()); + }); + + //alert change event + $('#my-dropdownChange').sSelect().change(function(){alert('changed')}); + + //add options to select and update + $('#addOptions').click(function(){ + $('#my-dropdown6').append('<option value="newOpt">New Option</option>').resetSS(); + return false; + }); + + }); + </script> + + <style type="text/css"> + body {font-family:Arial, Helvetica, sans-serif; font-size:12px;} + .selCont {clear:both; margin-bottom:20px; padding-bottom:40px; float:left; border-bottom:dotted 1px #000; width:600px;} + </style> + + </head> + <body> + <form action="" method="post"> + <h1>Stylish Select 0.4.9</h1> + <h2>A cross-browser, accessible alternative to the standard form element which can be fully customised with CSS</h2> + <p>Stylish Select attempts to replicate the functionality of the browser default select box as closely as possible with support for keyboard navigation, and intelligent positioning.</p> + <p>Stylish Select aims to have a minimal code footprint and weighs in at just over 3KB when minified.</p> + <a href="http://github.com/scottdarby/Stylish-Select">Get latest source code from GitHub</a> + <h2>Usage</h2> + <p>First, include the stylesheet, jQuery and the stylish select .js file in your html head tag.</p> + <p>The plugin can be used to replace any select with the following:</p> + <pre class="brush: javascript"> +$(document).ready(function(){ +$('#my-dropdown').sSelect(); +}); + </pre> + <div class="selCont"> + <h2>Simplest example, option selected by default</h2> + <p>You can use the alphabetical and arrow keys to navigate the list as you would a browser default select.</p> + <select id="my-dropdown" name="my-dropdown"> + <option value="1">A cappella</option> + <option value="test">Acid Jazz</option> + <option value="3">Big Band</option> + <option value="4">Big Beat</option> + <option value="5">Cakewalk</option> + <option value="6">Calenda</option> + <option value="7">Dark ambient</option> + <option value="8">Dark cabaret</option> + <option value="9">Chalk & Cheese</option> + </select> + </div> + <div class="selCont"> + <h2>Change event</h2> + <p>Stylish Select alters the original select on the page, so you can access it's change event:</p> + <pre class="brush: javascript"> +//change event +$('#my-dropdownChange').sSelect().change(function(){alert('changed')}); + </pre> + <select id="my-dropdownChange" name="my-dropdown"> + <option value="1">A cappella</option> + <option value="test">Acid Jazz</option> + <option value="3" selected="selected">Big Band</option> + <option value="4">Big Beat</option> + <option value="5">Cakewalk</option> + <option value="6">Calenda</option> + <option value="7">Dark ambient</option> + <option value="8">Dark cabaret</option> + </select> + </div> + <div class="selCont"> + <h2>Grouped options</h2> + <p>Stylish Select supports optgroups and also optgroups and options together.</p> + <select id="my-dropdown2" name="my-dropdown"> + <option>Please select</option> + <optgroup label="Tool"> + <option value="1">Opiate</option> + <option value="2">Undertow</option> + <option value="3">Aenima</option> + <option value="4">Lateralus</option> + </optgroup> + <optgroup label="A Tribe Called Quest"> + <option value="5">People's Instinctive Travels and the Paths of Rhythm</option> + <option value="6">The Low End Theory</option> + <option selected="selected" value="7">Midnight Marauders</option> + <option value="8">Beats, Rhymes and Life</option> + <option value="9">The Love Movement</option> + </optgroup> + </select> + </div> + <div id="get-set" class="selCont"> + <h2>Getting/setting the value</h2> + <pre class="brush: javascript"> +//set value +$('#setVal').click(function(){ +$('#my-dropdown5').getSetSSValue(4); +}); + +//get value +$('#getVal').click(function(){ +alert('The value is: '+$('#my-dropdown5').getSetSSValue()); +}); + </pre> + <p><a id="setVal" href="javascript:void(0)">Set value to 4</a></p> + <p><a id="getVal" href="javascript:void(0)">Get value</a></p> + <select id="my-dropdown5" name="my-dropdown"> + <option value="1">Lorem</option> + <option value="2">Ipsum</option> + <option value="3">Dolor</option> + <option value="4">Sit</option> + <option value="5">Amet</option> + <option value="6">Consectetuer</option> + <option value="7">Adipiscing</option> + </select> + </div> + <div id="update" class="selCont"> + <h2>Add new options to Stylish Select</h2> + <pre class="brush: javascript"> +//add options to select and update +$('#addOptions').click(function(){ +$('#my-dropdown6').append('<option value="newOpt">New Option</option>').resetSS(); +}); + </pre> + <p>If you add or remove options from the initial select element on the page, be sure to call the .resetSS() method on the select to update the Stylish Select replacement.</p> + + <p><a id="addOptions" href="javascript:void(0)">Add new options to select and update</a></p> + <select id="my-dropdown6" name="my-dropdown"> + <option value="1">Lorem</option> + <option value="2">Ipsum</option> + <option value="3">Dolor</option> + <option value="4">Sit</option> + <option value="5">Amet</option> + <option value="6">Consectetuer</option> + <option value="7">Adipiscing</option> + <option value="7">Adipiscing</option> + <option value="7">Adipiscing</option> + <option value="7">Adipiscing</option> + </select> + </div> + <div class="selCont"> + <h2>Max-height for large lists</h2> + <pre class="brush: javascript"> +$('#my-dropdown').sSelect({ddMaxHeight: '300px'}); + </pre> + <select id="my-dropdownCountries" name="my-dropdown"> + <option value="1">Afghanistan</option> + <option value="1">Akrotiri</option> + <option value="1">Albania</option> + <option value="1">Algeria</option> + <option value="1">American Samoa</option> + <option value="1">Andorra</option> + <option value="1">Angola</option> + <option value="1">Anguilla</option> + <option value="1">Antarctica</option> + <option value="1">Antigua and Barbuda</option> + <option value="1">Argentina</option> + <option value="1">Armenia</option> + <option value="1">Aruba</option> + <option value="1">Ashmore and Cartier Islands</option> + <option value="1">Australia</option> + <option value="1">Austria</option> + <option value="1">Azerbaijan</option> + <option value="1">Bahamas, The</option> + <option value="1">Bahrain</option> + <option value="1">Bangladesh</option> + <option value="1">Barbados</option> + <option value="1">Bassas da India</option> + <option value="1">Belarus</option> + <option value="1">Belgium</option> + <option value="1">Belize</option> + <option value="1">Benin</option> + <option value="1">Bermuda</option> + <option value="1">Bhutan</option> + <option value="1">Bolivia</option> + <option value="1">Bosnia and Herzegovina</option> + <option value="1">Botswana</option> + <option value="1">Bouvet Island</option> + <option value="1">Brazil</option> + <option value="1">British Indian Ocean Territory</option> + <option value="1">British Virgin Islands</option> + <option value="1">Brunei</option> + <option value="1">Bulgaria</option> + <option value="1">Burkina Faso</option> + <option value="1">Burma</option> + <option value="1">Burundi</option> + <option value="1">Cambodia</option> + <option value="1">Cameroon</option> + <option value="1">Canada</option> + <option value="1">Cape Verde</option> + <option value="1">Cayman Islands</option> + <option value="1">Central African Republic</option> + <option value="1">Chad</option> + <option value="1">Chile</option> + <option value="1">China</option> + <option value="1">Christmas Island</option> + <option value="1">Clipperton Island</option> + <option value="1">Cocos (Keeling) Islands</option> + <option value="1">Colombia</option> + <option value="1">Comoros</option> + <option value="1">Congo, Democratic Republic of the</option> + <option value="1">Congo, Republic of the</option> + <option value="1">Cook Islands</option> + <option value="1">Coral Sea Islands</option> + <option value="1">Costa Rica</option> + <option value="1">Cote d'Ivoire</option> + <option value="1">Croatia</option> + <option value="1">Cuba</option> + <option value="1">Cyprus</option> + <option value="1">Czech Republic</option> + <option value="1">Denmark</option> + <option value="1">Dhekelia</option> + <option value="1">Djibouti</option> + <option value="1">Dominica</option> + <option value="1">Dominican Republic</option> + <option value="1">Ecuador</option> + <option value="1">Egypt</option> + <option value="1">El Salvador</option> + <option value="1">Equatorial Guinea</option> + <option value="1">Eritrea</option> + <option value="1">Estonia</option> + <option value="1">Ethiopia</option> + <option value="1">Europa Island</option> + <option value="1">Falkland Islands (Islas Malvinas)</option> + <option value="1">Faroe Islands</option> + <option value="1">Fiji</option> + <option value="1">Finland</option> + <option value="1">France</option> + <option value="1">French Guiana</option> + </select> + </div> + <div class="selCont"> + <h2>Intelligent positioning</h2> + <p>Stylish Select will always remain visible on the page.</p> + <select id="my-dropdown4" name="my-dropdown"> + <optgroup label="Tool"> + <option value="1">Opiate</option> + <option value="2">Undertow</option> + <option value="3">Aenima</option> + <option value="4">Lateralus</option> + </optgroup> + <optgroup label="A Tribe Called Quest"> + <option value="5">People's Instinctive Travels and the Paths of Rhythm</option> + <option value="6">The Low End Theory</option> + <option value="7" selected="selected">Midnight Marauders</option> + <option value="8">Beats, Rhymes and Life</option> + <option value="9">The Love Movement</option> + </optgroup> + </select> + </div> + <div class="selCont"> + <h2>Disabled Select</h2> + <select disabled="disabled" id="my-dropdown7" name="my-dropdown"> + <option value="1">Opiate</option> + <option value="2">Undertow</option> + <option value="3">Aenima</option> + <option value="4">Lateralus</option> + <option value="9">The Love Movement</option> + </select> + </div> + <div class="selCont"> + <h2>Disabled Options</h2> + <select id="my-dropdown8" name="my-dropdown"> + <option value="1">Opiate</option> + <option disabled="disabled" value="2">Undertow</option> + <option value="3">Aenima</option> + <option selected="selected" value="4">Lateralus</option> + <option value="9">The Love Movement</option> + </select> + </div> + <div class="selCont"> + <h2>Disabled Grouped options</h2> + <select id="my-dropdown9" name="my-dropdown"> + <optgroup label="Tool" disabled="disabled"> + <option value="1">Opiate</option> + <option value="2">Undertow</option> + <option value="3">Aenima</option> + <option value="4">Lateralus</option> + </optgroup> + <optgroup label="A Tribe Called Quest"> + <option value="5">People's Instinctive Travels and the Paths of Rhythm</option> + <option value="6">The Low End Theory</option> + <option value="7" selected="selected">Midnight Marauders</option> + <option value="8">Beats, Rhymes and Life</option> + <option value="9">The Love Movement</option> + </optgroup> + </select> + </div> + </form> + </body> +</html>
\ No newline at end of file diff --git a/library/stylish_select/jquery.stylish-select.js b/library/stylish_select/jquery.stylish-select.js new file mode 100644 index 000000000..61a38ca8d --- /dev/null +++ b/library/stylish_select/jquery.stylish-select.js @@ -0,0 +1,492 @@ +/** +* Stylish Select 0.4.9 - jQuery plugin to replace a select drop down box with a stylable unordered list +* http://github.com/scottdarby/Stylish-Select +* +* Requires: jQuery 1.3 or newer +* +* Contributions from Justin Beasley: http://www.harvest.org/ +* Anatoly Ressin: http://www.artazor.lv/ Wilfred Hughes: https://github.com/Wilfred +* Grigory Zarubin: https://github.com/Craigy- +* +* Dual licensed under the MIT and GPL licenses. +*/ +(function($){ + //add class to html tag + $('html').addClass('stylish-select'); + + //Cross-browser implementation of indexOf from MDN: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf + if (!Array.prototype.indexOf){ + Array.prototype.indexOf = function(searchElement /*, fromIndex */){ + if (this === void 0 || this === null) + throw new TypeError(); + + var t = Object(this); + var len = t.length >>> 0; + if (len === 0) + return -1; + + var n = 0; + if (arguments.length > 0){ + n = Number(arguments[1]); + if (n !== n) // shortcut for verifying if it's NaN + n = 0; + else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + + if (n >= len) + return -1; + + var k = n >= 0 + ? n + : Math.max(len - Math.abs(n), 0); + + for (; k < len; k++){ + if (k in t && t[k] === searchElement) + return k; + } + return -1; + }; + } + + //utility methods + $.fn.extend({ + getSetSSValue: function(value){ + if (value){ + //set value and trigger change event + $(this).val(value).change(); + return this; + } else { + return $(this).find(':selected').val(); + } + }, + //added by Justin Beasley + resetSS: function(){ + var oldOpts = $(this).data('ssOpts'); + $this = $(this); + $this.next().remove(); + //unbind all events and redraw + $this.unbind('.sSelect').sSelect(oldOpts); + } + }); + + $.fn.sSelect = function(options){ + return this.each(function(){ + var defaults = { + defaultText: 'Please select', + animationSpeed: 0, //set speed of dropdown + ddMaxHeight: '', //set css max-height value of dropdown + containerClass: '' //additional classes for container div + }; + + //initial variables + var opts = $.extend(defaults, options), + $input = $(this), + $containerDivText = $('<div class="selectedTxt"></div>'), + $containerDiv = $('<div class="newListSelected ' + opts.containerClass + ($input.is(':disabled') ? ' newListDisabled' : '') + '"></div>'), + $containerDivWrapper = $('<div class="SSContainerDivWrapper" style="visibility:hidden;"></div>'), + $newUl = $('<ul class="newList"></ul>'), + currentIndex = -1, + prevIndex = -1, + keys = [], + prevKey = false, + prevented = false, + $newLi; + + //added by Justin Beasley + $(this).data('ssOpts',options); + + if( $(this).next('.newListSelected').length ) { + return; + } + + //build new list + $containerDiv.insertAfter($input); + $containerDiv.attr("tabindex", $input.attr("tabindex") || "0"); + $containerDivText.prependTo($containerDiv); + $newUl.appendTo($containerDiv); + $newUl.wrap($containerDivWrapper); + $containerDivWrapper = $newUl.parent(); + $input.hide(); + + if($input.is(':disabled')){ + return; + } + + //added by Justin Beasley (used for lists initialized while hidden) + $containerDivText.data('ssReRender',!$containerDivText.is(':visible')); + + //add one item to list + function addItem(item, container) { + var option = $(item).text(), + key = $(item).val(), + isDisabled = $(item).is(':disabled'); + + if (!isDisabled && !$(item).parents().is(':disabled')) { + //add first letter of each word to array + keys.push(option.charAt(0).toLowerCase()); + } + container.append($('<li><a'+(isDisabled ? ' class="newListItemDisabled"' : '')+' href="JavaScript:void(0);">'+option+'</a></li>').data({ + 'key' : key, + 'selected' : $(item).is(':selected') + })); + } + + $input.children().each(function(){ + if ($(this).is('option')){ + addItem(this, $newUl); + } else { + var optionTitle = $(this).attr('label'), + $optGroup = $('<li class="newListOptionTitle ' + ($(this).is(':disabled') ? 'newListOptionDisabled' : '') + '">'+optionTitle+'</li>'), + $optGroupList = $('<ul></ul>'); + + $optGroup.appendTo($newUl); + $optGroupList.appendTo($optGroup); + + $(this).children().each(function(){ + addItem(this, $optGroupList); + }); + } + }); + + //cache list items object + $newLi = $newUl.find('li a:not(.newListItemDisabled)').not(function(){ + return $(this).parents().hasClass('newListOptionDisabled'); + }); + + //get selected item from new list (because it doesn't contain disabled options) + $newLi.each(function(i){ + if ($(this).parent().data('selected')){ + opts.defaultText = $(this).html(); + currentIndex = prevIndex = i; + } + }); + + //get heights of new elements for use later + var newUlHeight = $newUl.height(), + containerHeight = $containerDiv.height(), + newLiLength = $newLi.length; + + //check if a value is selected + if (currentIndex != -1){ + navigateList(currentIndex); + } else { + //set placeholder text + $containerDivText.text(opts.defaultText); + } + + //decide if to place the new list above or below the drop-down + function newUlPos(){ + var containerPosY = $containerDiv.offset().top, + docHeight = $(window).height(), + scrollTop = $(window).scrollTop(); + + //if height of list is greater then max height, set list height to max height value + if (newUlHeight > parseInt(opts.ddMaxHeight)){ + newUlHeight = parseInt(opts.ddMaxHeight); + } + + containerPosY = containerPosY-scrollTop; + if (containerPosY+newUlHeight >= docHeight){ + $newUl.css({ + height: newUlHeight + }); + $containerDivWrapper.css({ + top: '-'+newUlHeight+'px', + height: newUlHeight + }); + $input.onTop = true; + } else { + $newUl.css({ + height: newUlHeight + }); + $containerDivWrapper.css({ + top: containerHeight+'px', + height: newUlHeight + }); + $input.onTop = false; + } + } + + //run function on page load + newUlPos(); + + //run function on browser window resize + $(window).bind('resize.sSelect scroll.sSelect', newUlPos); + + //positioning + function positionFix(){ + $containerDiv.css('position','relative'); + } + + function positionHideFix(){ + $containerDiv.css( + { + position: 'static' + }); + } + + $containerDivText.bind('click.sSelect',function(event){ + event.stopPropagation(); + + //added by Justin Beasley + if($(this).data('ssReRender')){ + newUlHeight = $newUl.height('').height(); + $containerDivWrapper.height(''); + containerHeight = $containerDiv.height(); + $(this).data('ssReRender',false); + newUlPos(); + } + + //hide all menus apart from this one + $('.SSContainerDivWrapper') + .not($(this).next()) + .hide() + .parent() + .css('position', 'static') + .removeClass('newListSelFocus'); + + //show/hide this menu + $containerDivWrapper.toggle(); + positionFix(); + + //scroll list to selected item + if(currentIndex == -1) currentIndex = 0; + try { + $newLi.eq(currentIndex).focus(); + } catch(ex) {} + }); + + function closeDropDown(fireChange, resetText){ + if(fireChange == true){ + prevIndex = currentIndex; + $input.change(); + } + + if(resetText == true){ + currentIndex = prevIndex; + navigateList(currentIndex); + } + + $containerDivWrapper.hide(); + positionHideFix(); + } + + $newLi.bind('click.sSelect',function(e){ + var $clickedLi = $(e.target); + + //update counter + currentIndex = $newLi.index($clickedLi); + + //remove all hilites, then add hilite to selected item + prevented = true; + navigateList(currentIndex, true); + closeDropDown(); + }); + + $newLi.bind('mouseenter.sSelect', + function(e){ + var $hoveredLi = $(e.target); + $hoveredLi.addClass('newListHover'); + }).bind('mouseleave.sSelect', + function(e){ + var $hoveredLi = $(e.target); + $hoveredLi.removeClass('newListHover'); + }); + + function navigateList(currentIndex, fireChange){ + if(currentIndex == -1){ + $containerDivText.text(opts.defaultText); + $newLi.removeClass('hiLite'); + } else { + $newLi.removeClass('hiLite') + .eq(currentIndex) + .addClass('hiLite'); + + var text = $newLi.eq(currentIndex).text(), + val = $newLi.eq(currentIndex).parent().data('key'); + + try { + $input.val(val); + } catch(ex) { + // handle ie6 exception + $input[0].selectedIndex = currentIndex; + } + + $containerDivText.text(text); + + //only fire change event if specified + if(fireChange == true){ + prevIndex = currentIndex; + $input.change(); + } + + if ($containerDivWrapper.is(':visible')){ + try { + $newLi.eq(currentIndex).focus(); + } catch(ex) {} + } + } + } + + $input.bind('change.sSelect',function(event){ + var $targetInput = $(event.target); + //stop change function from firing + if (prevented == true){ + prevented = false; + return false; + } + var $currentOpt = $targetInput.find(':selected'); + currentIndex = $targetInput.find('option').index($currentOpt); + navigateList(currentIndex); + }); + + //handle up and down keys + function keyPress(element){ + //when keys are pressed + $(element).unbind('keydown.sSelect').bind('keydown.sSelect',function(e){ + var keycode = e.which; + + //prevent change function from firing + prevented = true; + + switch(keycode){ + case 40: //down + case 39: //right + incrementList(); + return false; + break; + case 38: //up + case 37: //left + decrementList(); + return false; + break; + case 33: //page up + case 36: //home + gotoFirst(); + return false; + break; + case 34: //page down + case 35: //end + gotoLast(); + return false; + break; + case 13: //enter + case 27: //esc + closeDropDown(true); + return false; + break; + case 9: //tab + closeDropDown(true); + nextFormElement(); + return false; + break; + } + + //check for keyboard shortcuts + keyPressed = String.fromCharCode(keycode).toLowerCase(); + + var currentKeyIndex = keys.indexOf(keyPressed); + + if (typeof currentKeyIndex != 'undefined'){ //if key code found in array + ++currentIndex; + currentIndex = keys.indexOf(keyPressed, currentIndex); //search array from current index + + if (currentIndex == -1 || currentIndex == null || prevKey != keyPressed){ + // if no entry was found or new key pressed search from start of array + currentIndex = keys.indexOf(keyPressed); + } + + navigateList(currentIndex); + //store last key pressed + prevKey = keyPressed; + return false; + } + }); + } + + function incrementList(){ + if (currentIndex < (newLiLength-1)){ + ++currentIndex; + navigateList(currentIndex); + } + } + + function decrementList(){ + if (currentIndex > 0){ + --currentIndex; + navigateList(currentIndex); + } + } + + function gotoFirst(){ + currentIndex = 0; + navigateList(currentIndex); + } + + function gotoLast(){ + currentIndex = newLiLength-1; + navigateList(currentIndex); + } + + $containerDiv.bind('click.sSelect',function(e){ + e.stopPropagation(); + keyPress(this); + }); + + $containerDiv.bind('focus.sSelect',function(){ + $(this).addClass('newListSelFocus'); + keyPress(this); + }); + + $containerDiv.bind('blur.sSelect',function(){ + $(this).removeClass('newListSelFocus'); + }); + + //hide list on blur + $(document).bind('click.sSelect',function(){ + $containerDiv.removeClass('newListSelFocus'); + if ($containerDivWrapper.is(':visible')){ + closeDropDown(false, true); + } else { + closeDropDown(false); + } + }); + + //select next form element in document + function nextFormElement() { + var fields = $('body').find('button,input,textarea,select'), + index = fields.index($input); + if (index > -1 && (index + 1) < fields.length) { + fields.eq(index + 1).focus(); + } + return false; + } + // handle focus on original select element + $input.focus(function(){ + $input.next().focus(); + }); + + //add classes on hover + $containerDivText.bind('mouseenter.sSelect', + function(e){ + var $hoveredTxt = $(e.target); + $hoveredTxt.parent().addClass('newListSelHover'); + }).bind('mouseleave.sSelect', + function(e){ + var $hoveredTxt = $(e.target); + $hoveredTxt.parent().removeClass('newListSelHover'); + }); + + //reset left property and hide + $containerDivWrapper.css({ + left: '0', + display: 'none', + visibility: 'visible' + }); + + }); + + }; + +})(jQuery);
\ No newline at end of file diff --git a/library/stylish_select/select-bg.png b/library/stylish_select/select-bg.png Binary files differnew file mode 100755 index 000000000..151eda726 --- /dev/null +++ b/library/stylish_select/select-bg.png diff --git a/library/stylish_select/stylish-select.css b/library/stylish_select/stylish-select.css new file mode 100755 index 000000000..1f3dcd28d --- /dev/null +++ b/library/stylish_select/stylish-select.css @@ -0,0 +1,121 @@ +/**
+* Stylish Select 0.4.9 - $ plugin to replace a select drop down box with a stylable unordered list
+* http://github.com/scottdarby/Stylish-Select/
+*
+* Copyright (c) 2009 Scott Darby
+*
+* Requires: jQuery 1.3 or newer
+*
+* Dual licensed under the MIT and GPL licenses.
+*/
+
+/**
+* Hide lists on page load
+---------------------------------------------------------*/
+
+.stylish-select .SSContainerDivWrapper {
+ left:-9999px;
+}
+
+/*
+* Red example
+---------------------------------------------------------*/
+.stylish-select .SSContainerDivWrapper {
+ margin:0;
+ padding:0;
+ width:290px;
+ position:absolute;
+ top:22px;
+ left:0;
+ z-index:2;
+}
+
+.stylish-select ul.newList {
+ margin:0;
+ padding:0;
+ list-style:none;
+ color:#000;
+ background:#fff;
+ border:1px solid #ccc;
+ overflow:auto;
+}
+
+.stylish-select ul.newList * {
+ margin:0;
+ padding:0;
+}
+
+
+.stylish-select ul.newList a {
+ color: #000;
+ text-decoration:none;
+ display:block;
+ padding:3px 8px;
+}
+
+.stylish-select .newListSelected {
+ width:285px;
+ color:#000;
+ height:19px;
+ padding:3px 0 0 6px;
+ float:left;
+ background:url(select-bg.png) no-repeat;
+}
+
+.stylish-select ul.newList li a:focus {
+ -moz-outline-style: none;
+}
+
+.stylish-select .selectedTxt {
+ width:258px;
+ overflow:hidden;
+ height:16px;
+ padding:0 23px 0 0;
+}
+
+.stylish-select .hiLite {
+ background:#650101!important;
+ color:#fff!important;
+}
+
+.stylish-select .newListHover {
+ background:#ccc!important;
+ color:#000!important;
+ cursor:default;
+}
+
+.stylish-select .newListDisabled {
+ opacity: 0.6;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";
+ filter: alpha(opacity=60);
+}
+
+.stylish-select .newListItemDisabled {
+ opacity: 0.6;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";
+ filter: alpha(opacity=60);
+}
+
+.stylish-select .newListOptionDisabled {
+ opacity: 0.6;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";
+ filter: alpha(opacity=60);
+}
+
+.stylish-select .newListSelHover,
+.stylish-select .newListSelFocus {
+ background-position:0 -22px;
+ cursor:default;
+}
+
+.stylish-select .newListOptionTitle {
+ font-weight:bold;
+}
+
+.stylish-select .newListOptionTitle ul {
+ margin:3px 0 0;
+}
+
+.stylish-select .newListOptionTitle li {
+ font-weight:normal;
+}
\ No newline at end of file |