diff --git a/build/packaged/javascript/semantic.js b/build/packaged/javascript/semantic.js new file mode 100644 index 000000000..2ac59e81e --- /dev/null +++ b/build/packaged/javascript/semantic.js @@ -0,0 +1,11048 @@ +/* + * # Semantic - Accordion + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ($, window, document, undefined) { + +$.fn.accordion = function(parameters) { + var + $allModules = $(this), + + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.accordion.settings, parameters) + : $.fn.accordion.settings, + + className = settings.className, + namespace = settings.namespace, + selector = settings.selector, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + $allModules + .each(function() { + var + $module = $(this), + $title = $module.find(selector.title), + $content = $module.find(selector.content), + + element = this, + instance = $module.data(moduleNamespace), + module + ; + + module = { + + initialize: function() { + module.debug('Initializing accordion with bound events', $module); + // initializing + $title + .on('click' + eventNamespace, module.event.click) + ; + module.instantiate(); + }, + + instantiate: function() { + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.debug('Destroying previous accordion for', $module); + $module + .removeData(moduleNamespace) + ; + $title + .off(eventNamespace) + ; + }, + + event: { + click: function() { + module.verbose('Title clicked', this); + var + $activeTitle = $(this), + index = $title.index($activeTitle) + ; + module.toggle(index); + }, + resetStyle: function() { + module.verbose('Resetting styles on element', this); + $(this) + .removeAttr('style') + .children() + .removeAttr('style') + ; + } + }, + + toggle: function(index) { + module.debug('Toggling content content at index', index); + var + $activeTitle = $title.eq(index), + $activeContent = $activeTitle.next($content), + contentIsOpen = $activeContent.is(':visible') + ; + if(contentIsOpen) { + if(settings.collapsible) { + module.close(index); + } + else { + module.debug('Cannot close accordion content collapsing is disabled'); + } + } + else { + module.open(index); + } + }, + + open: function(index) { + var + $activeTitle = $title.eq(index), + $activeContent = $activeTitle.next($content), + $previousTitle = $title.filter('.' + className.active), + $previousContent = $previousTitle.next($title), + contentIsOpen = ($previousTitle.size() > 0) + ; + if( !$activeContent.is(':animated') ) { + module.debug('Opening accordion content', $activeTitle); + if(settings.exclusive && contentIsOpen) { + $previousTitle + .removeClass(className.active) + ; + $previousContent + .stop() + .children() + .animate({ + opacity: 0 + }, settings.duration, module.event.resetStyle) + .end() + .slideUp(settings.duration , settings.easing, function() { + $previousContent + .removeClass(className.active) + .removeAttr('style') + .children() + .removeAttr('style') + ; + }) + ; + } + $activeTitle + .addClass(className.active) + ; + $activeContent + .stop() + .children() + .removeAttr('style') + .end() + .slideDown(settings.duration, settings.easing, function() { + $activeContent + .addClass(className.active) + .removeAttr('style') + ; + $.proxy(settings.onOpen, $activeContent)(); + $.proxy(settings.onChange, $activeContent)(); + }) + ; + } + }, + + close: function(index) { + var + $activeTitle = $title.eq(index), + $activeContent = $activeTitle.next($content) + ; + module.debug('Closing accordion content', $activeTitle); + $activeTitle + .removeClass(className.active) + ; + $activeContent + .removeClass(className.active) + .show() + .stop() + .children() + .animate({ + opacity: 0 + }, settings.duration, module.event.resetStyle) + .end() + .slideUp(settings.duration, settings.easing, function(){ + $activeContent + .removeAttr('style') + ; + $.proxy(settings.onClose, $activeContent)(); + $.proxy(settings.onChange, $activeContent)(); + }) + ; + }, + + setting: function(name, value) { + module.debug('Changing setting', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + module.debug('Changing internal', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.accordion.settings = { + name : 'Accordion', + namespace : 'accordion', + + debug : true, + verbose : true, + performance : true, + + exclusive : true, + collapsible : true, + + duration : 300, + easing : 'linear', + + onOpen : function(){}, + onClose : function(){}, + onChange : function(){}, + + error: { + method : 'The method you called is not defined' + }, + + className : { + active : 'active' + }, + + selector : { + title : '.title', + content : '.content' + }, + + +}; + +})( jQuery, window , document ); + +/* + * # Semantic - API + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + + $.api = $.fn.api = function(parameters) { + + var + settings = $.extend(true, {}, $.api.settings, parameters), + + // if this keyword isn't a jQuery object, create one + context = (typeof this != 'function') + ? this + : $('
'), + // context defines the element used for loading/error state + $context = (settings.stateContext) + ? $(settings.stateContext) + : $(context), + // module is the thing that initiates the api action, can be independent of context + $module = typeof this == 'object' + ? $(context) + : $context, + + element = this, + time = new Date().getTime(), + performance = [], + + moduleSelector = $module.selector || '', + moduleNamespace = settings.namespace + '-module', + + className = settings.className, + metadata = settings.metadata, + error = settings.error, + + instance = $module.data(moduleNamespace), + + query = arguments[0], + methodInvoked = (instance !== undefined && typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + + module, + invokedResponse + ; + + module = { + initialize: function() { + var + runSettings, + + loadingTimer = new Date().getTime(), + loadingDelay, + + promise, + url, + + formData = {}, + data, + + ajaxSettings = {}, + xhr + ; + + // serialize parent form if requested! + if(settings.serializeForm && $(this).toJSON() !== undefined) { + formData = module.get.formData(); + module.debug('Adding form data to API Request', formData); + $.extend(true, settings.data, formData); + } + + // let beforeSend change settings object + runSettings = $.proxy(settings.beforeSend, $module)(settings); + + // check for exit conditions + if(runSettings !== undefined && !runSettings) { + module.error(error.beforeSend); + module.reset(); + return; + } + + // get real url from template + url = module.get.url( module.get.templateURL() ); + + // exit conditions reached from missing url parameters + if( !url ) { + module.error(error.missingURL); + module.reset(); + return; + } + + // promise handles notification on api request, so loading min. delay can occur for all notifications + promise = + $.Deferred() + .always(function() { + if(settings.stateContext) { + $context + .removeClass(className.loading) + ; + } + $.proxy(settings.complete, $module)(); + }) + .done(function(response) { + module.debug('API request successful'); + // take a stab at finding success state if json + if(settings.dataType == 'json') { + if (response.error !== undefined) { + $.proxy(settings.failure, $context)(response.error, settings, $module); + } + else if ($.isArray(response.errors)) { + $.proxy(settings.failure, $context)(response.errors[0], settings, $module); + } + else { + $.proxy(settings.success, $context)(response, settings, $module); + } + } + // otherwise + else { + $.proxy(settings.success, $context)(response, settings, $module); + } + }) + .fail(function(xhr, status, httpMessage) { + var + errorMessage = (settings.error[status] !== undefined) + ? settings.error[status] + : httpMessage, + response + ; + // let em know unless request aborted + if(xhr !== undefined) { + // readyState 4 = done, anything less is not really sent + if(xhr.readyState !== undefined && xhr.readyState == 4) { + + // if http status code returned and json returned error, look for it + if( xhr.status != 200 && httpMessage !== undefined && httpMessage !== '') { + module.error(error.statusMessage + httpMessage); + } + else { + if(status == 'error' && settings.dataType == 'json') { + try { + response = $.parseJSON(xhr.responseText); + if(response && response.error !== undefined) { + errorMessage = response.error; + } + } + catch(error) { + module.error(error.JSONParse); + } + } + } + $context + .removeClass(className.loading) + .addClass(className.error) + ; + // show error state only for duration specified in settings + if(settings.errorLength > 0) { + setTimeout(function(){ + $context + .removeClass(className.error) + ; + }, settings.errorLength); + } + module.debug('API Request error:', errorMessage); + $.proxy(settings.failure, $context)(errorMessage, settings, this); + } + else { + module.debug('Request Aborted (Most likely caused by page change)'); + } + } + }) + ; + + // look for params in data + $.extend(true, ajaxSettings, settings, { + success : function(){}, + failure : function(){}, + complete : function(){}, + type : settings.method || settings.type, + data : data, + url : url, + beforeSend : settings.beforeXHR + }); + + if(settings.stateContext) { + $context + .addClass(className.loading) + ; + } + + if(settings.progress) { + module.verbose('Adding progress events'); + $.extend(true, ajaxSettings, { + xhr: function() { + var + xhr = new window.XMLHttpRequest() + ; + xhr.upload.addEventListener('progress', function(event) { + var + percentComplete + ; + if (event.lengthComputable) { + percentComplete = Math.round(event.loaded / event.total * 10000) / 100 + '%'; + $.proxy(settings.progress, $context)(percentComplete, event); + } + }, false); + xhr.addEventListener('progress', function(event) { + var + percentComplete + ; + if (event.lengthComputable) { + percentComplete = Math.round(event.loaded / event.total * 10000) / 100 + '%'; + $.proxy(settings.progress, $context)(percentComplete, event); + } + }, false); + return xhr; + } + }); + } + + module.verbose('Creating AJAX request with settings: ', ajaxSettings); + xhr = + $.ajax(ajaxSettings) + .always(function() { + // calculate if loading time was below minimum threshold + loadingDelay = ( settings.loadingLength - (new Date().getTime() - loadingTimer) ); + settings.loadingDelay = loadingDelay < 0 + ? 0 + : loadingDelay + ; + }) + .done(function(response) { + var + context = this + ; + setTimeout(function(){ + promise.resolveWith(context, [response]); + }, settings.loadingDelay); + }) + .fail(function(xhr, status, httpMessage) { + var + context = this + ; + // page triggers abort on navigation, dont show error + if(status != 'abort') { + setTimeout(function(){ + promise.rejectWith(context, [xhr, status, httpMessage]); + }, settings.loadingDelay); + } + else { + $context + .removeClass(className.error) + .removeClass(className.loading) + ; + } + }) + ; + if(settings.stateContext) { + $module + .data(metadata.promise, promise) + .data(metadata.xhr, xhr) + ; + } + }, + + get: { + formData: function() { + return $module + .closest('form') + .toJSON() + ; + }, + templateURL: function() { + var + action = $module.data(settings.metadata.action) || settings.action || false, + url + ; + if(action) { + module.debug('Creating url for: ', action); + if(settings.api[action] !== undefined) { + url = settings.api[action]; + } + else { + module.error(error.missingAction); + } + } + // override with url if specified + if(settings.url) { + url = settings.url; + module.debug('Getting url', url); + } + return url; + }, + url: function(url, urlData) { + var + urlVariables + ; + if(url) { + urlVariables = url.match(settings.regExpTemplate); + urlData = urlData || settings.urlData; + + if(urlVariables) { + module.debug('Looking for URL variables', urlVariables); + $.each(urlVariables, function(index, templateValue){ + var + term = templateValue.substr( 2, templateValue.length - 3), + termValue = ($.isPlainObject(urlData) && urlData[term] !== undefined) + ? urlData[term] + : ($module.data(term) !== undefined) + ? $module.data(term) + : urlData[term] + ; + module.verbose('Looking for variable', term, $module, $module.data(term), urlData[term]); + // remove optional value + if(termValue === false) { + module.debug('Removing variable from URL', urlVariables); + url = url.replace('/' + templateValue, ''); + } + // undefined condition + else if(termValue === undefined || !termValue) { + module.error(error.missingParameter + term); + url = false; + return false; + } + else { + url = url.replace(templateValue, termValue); + } + }); + } + } + return url; + } + }, + + // reset api request + reset: function() { + $module + .data(metadata.promise, false) + .data(metadata.xhr, false) + ; + $context + .removeClass(className.error) + .removeClass(className.loading) + ; + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; + }; + + // handle DOM attachment to API functionality + $.fn.apiButton = function(parameters) { + $(this) + .each(function(){ + var + // if only function passed it is success callback + $module = $(this), + selector = $(this).selector || '', + + settings = ( $.isFunction(parameters) ) + ? $.extend(true, {}, $.api.settings, $.fn.apiButton.settings, { stateContext: this, success: parameters }) + : $.extend(true, {}, $.api.settings, $.fn.apiButton.settings, { stateContext: this}, parameters), + module + ; + module = { + initialize: function() { + if(settings.context && selector !== '') { + $(settings.context) + .on(selector, 'click.' + settings.namespace, module.click) + ; + } + else { + $module + .on('click.' + settings.namespace, module.click) + ; + } + }, + click: function() { + if(!settings.filter || $(this).filter(settings.filter).size() === 0) { + $.proxy( $.api, this )(settings); + } + } + }; + module.initialize(); + }) + ; + return this; + }; + + $.api.settings = { + + name : 'API', + namespace : 'api', + + debug : true, + verbose : true, + performance : true, + + api : {}, + + beforeSend : function(settings) { + return settings; + }, + beforeXHR : function(xhr) {}, + success : function(response) {}, + complete : function(response) {}, + failure : function(errorCode) {}, + progress : false, + + error : { + missingAction : 'API action used but no url was defined', + missingURL : 'URL not specified for the API action', + missingParameter : 'Missing an essential URL parameter: ', + + timeout : 'Your request timed out', + error : 'There was an error with your request', + parseError : 'There was an error parsing your request', + JSONParse : 'JSON could not be parsed during error handling', + statusMessage : 'Server gave an error: ', + beforeSend : 'The before send function has aborted the request', + exitConditions : 'API Request Aborted. Exit conditions met' + }, + + className: { + loading : 'loading', + error : 'error' + }, + + metadata: { + action : 'action', + promise : 'promise', + xhr : 'xhr' + }, + + regExpTemplate: /\{\$([A-z]+)\}/g, + + action : false, + url : false, + urlData : false, + serializeForm : false, + + stateContext : false, + + method : 'get', + data : {}, + dataType : 'json', + cache : true, + + loadingLength : 200, + errorLength : 2000 + + }; + + $.fn.apiButton.settings = { + filter : '.disabled, .loading', + context : false, + stateContext : false + }; + +})( jQuery, window , document ); +/* + * # Semantic - Colorize + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + + $.fn.colorize = function(parameters) { + var + settings = $.extend(true, {}, $.fn.colorize.settings, parameters), + // hoist arguments + moduleArguments = arguments || false + ; + $(this) + .each(function(instanceIndex) { + + var + $module = $(this), + + mainCanvas = $('')[0], + imageCanvas = $('')[0], + overlayCanvas = $('')[0], + + backgroundImage = new Image(), + + // defs + mainContext, + imageContext, + overlayContext, + + image, + imageName, + + width, + height, + + // shortucts + colors = settings.colors, + paths = settings.paths, + namespace = settings.namespace, + error = settings.error, + + // boilerplate + instance = $module.data('module-' + namespace), + module + ; + + module = { + + checkPreconditions: function() { + module.debug('Checking pre-conditions'); + + if( !$.isPlainObject(colors) || $.isEmptyObject(colors) ) { + module.error(error.undefinedColors); + return false; + } + return true; + }, + + async: function(callback) { + if(settings.async) { + setTimeout(callback, 0); + } + else { + callback(); + } + }, + + getMetadata: function() { + module.debug('Grabbing metadata'); + image = $module.data('image') || settings.image || undefined; + imageName = $module.data('name') || settings.name || instanceIndex; + width = settings.width || $module.width(); + height = settings.height || $module.height(); + if(width === 0 || height === 0) { + module.error(error.undefinedSize); + } + }, + + initialize: function() { + module.debug('Initializing with colors', colors); + if( module.checkPreconditions() ) { + + module.async(function() { + module.getMetadata(); + module.canvas.create(); + + module.draw.image(function() { + module.draw.colors(); + module.canvas.merge(); + }); + $module + .data('module-' + namespace, module) + ; + }); + } + }, + + redraw: function() { + module.debug('Redrawing image'); + module.async(function() { + module.canvas.clear(); + module.draw.colors(); + module.canvas.merge(); + }); + }, + + change: { + color: function(colorName, color) { + module.debug('Changing color', colorName); + if(colors[colorName] === undefined) { + module.error(error.missingColor); + return false; + } + colors[colorName] = color; + module.redraw(); + } + }, + + canvas: { + create: function() { + module.debug('Creating canvases'); + + mainCanvas.width = width; + mainCanvas.height = height; + imageCanvas.width = width; + imageCanvas.height = height; + overlayCanvas.width = width; + overlayCanvas.height = height; + + mainContext = mainCanvas.getContext('2d'); + imageContext = imageCanvas.getContext('2d'); + overlayContext = overlayCanvas.getContext('2d'); + + $module + .append( mainCanvas ) + ; + mainContext = $module.children('canvas')[0].getContext('2d'); + }, + clear: function(context) { + module.debug('Clearing canvas'); + overlayContext.fillStyle = '#FFFFFF'; + overlayContext.fillRect(0, 0, width, height); + }, + merge: function() { + if( !$.isFunction(mainContext.blendOnto) ) { + module.error(error.missingPlugin); + return; + } + mainContext.putImageData( imageContext.getImageData(0, 0, width, height), 0, 0); + overlayContext.blendOnto(mainContext, 'multiply'); + } + }, + + draw: { + + image: function(callback) { + module.debug('Drawing image'); + callback = callback || function(){}; + if(image) { + backgroundImage.src = image; + backgroundImage.onload = function() { + imageContext.drawImage(backgroundImage, 0, 0); + callback(); + }; + } + else { + module.error(error.noImage); + callback(); + } + }, + + colors: function() { + module.debug('Drawing color overlays', colors); + $.each(colors, function(colorName, color) { + settings.onDraw(overlayContext, imageName, colorName, color); + }); + } + + }, + + debug: function(message, variableName) { + if(settings.debug) { + if(variableName !== undefined) { + console.info(settings.name + ': ' + message, variableName); + } + else { + console.info(settings.name + ': ' + message); + } + } + }, + error: function(errorMessage) { + console.warn(settings.name + ': ' + errorMessage); + }, + invoke: function(methodName, context, methodArguments) { + var + method + ; + methodArguments = methodArguments || Array.prototype.slice.call( arguments, 2 ); + + if(typeof methodName == 'string' && instance !== undefined) { + methodName = methodName.split('.'); + $.each(methodName, function(index, name) { + if( $.isPlainObject( instance[name] ) ) { + instance = instance[name]; + return true; + } + else if( $.isFunction( instance[name] ) ) { + method = instance[name]; + return true; + } + module.error(settings.error.method); + return false; + }); + } + return ( $.isFunction( method ) ) + ? method.apply(context, methodArguments) + : false + ; + } + + }; + if(instance !== undefined && moduleArguments) { + // simpler than invoke realizing to invoke itself (and losing scope due prototype.call() + if(moduleArguments[0] == 'invoke') { + moduleArguments = Array.prototype.slice.call( moduleArguments, 1 ); + } + return module.invoke(moduleArguments[0], this, Array.prototype.slice.call( moduleArguments, 1 ) ); + } + // initializing + module.initialize(); + }) + ; + return this; + }; + + $.fn.colorize.settings = { + name : 'Image Colorizer', + debug : true, + namespace : 'colorize', + + onDraw : function(overlayContext, imageName, colorName, color) {}, + + // whether to block execution while updating canvas + async : true, + // object containing names and default values of color regions + colors : {}, + + metadata: { + image : 'image', + name : 'name' + }, + + error: { + noImage : 'No tracing image specified', + undefinedColors : 'No default colors specified.', + missingColor : 'Attempted to change color that does not exist', + missingPlugin : 'Blend onto plug-in must be included', + undefinedHeight : 'The width or height of image canvas could not be automatically determined. Please specify a height.' + } + + }; + +})( jQuery, window , document ); + +/* + * # Semantic - Form Validation + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.form = function(fields, parameters) { + var + $allModules = $(this), + + settings = $.extend(true, {}, $.fn.form.settings, parameters), + validation = $.extend({}, $.fn.form.settings.defaults, fields), + + namespace = settings.namespace, + metadata = settings.metadata, + selector = settings.selector, + className = settings.className, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + $allModules + .each(function() { + var + $module = $(this), + $field = $(this).find(selector.field), + $group = $(this).find(selector.group), + $message = $(this).find(selector.message), + $prompt = $(this).find(selector.prompt), + $submit = $(this).find(selector.submit), + + formErrors = [], + + element = this, + instance = $module.data(moduleNamespace), + module + ; + + module = { + + initialize: function() { + module.verbose('Initializing form validation', $module, validation, settings); + if(settings.keyboardShortcuts) { + $field + .on('keydown' + eventNamespace, module.event.field.keydown) + ; + } + $module + .on('submit' + eventNamespace, module.validate.form) + ; + $field + .on('blur' + eventNamespace, module.event.field.blur) + ; + $submit + .on('click' + eventNamespace, module.submit) + ; + $field + .on(module.get.changeEvent() + eventNamespace, module.event.field.change) + ; + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module', instance); + $module + .off(eventNamespace) + .removeData(moduleNamespace) + ; + }, + + refresh: function() { + module.verbose('Refreshing selector cache'); + $field = $module.find(selector.field); + }, + + submit: function() { + module.verbose('Submitting form', $module); + $module + .submit() + ; + }, + + event: { + field: { + keydown: function(event) { + var + $field = $(this), + key = event.which, + keyCode = { + enter : 13, + escape : 27 + } + ; + if( key == keyCode.escape) { + module.verbose('Escape key pressed blurring field'); + $field + .blur() + ; + } + if(!event.ctrlKey && key == keyCode.enter && $field.is(selector.input) ) { + module.debug('Enter key pressed, submitting form'); + $submit + .addClass(className.down) + ; + $field + .one('keyup' + eventNamespace, module.event.field.keyup) + ; + event.preventDefault(); + return false; + } + }, + keyup: function() { + module.verbose('Doing keyboard shortcut form submit'); + $submit.removeClass(className.down); + module.submit(); + }, + blur: function() { + var + $field = $(this), + $fieldGroup = $field.closest($group) + ; + if( $fieldGroup.hasClass(className.error) ) { + module.debug('Revalidating field', $field, module.get.validation($field)); + module.validate.field( module.get.validation($field) ); + } + else if(settings.on == 'blur' || settings.on == 'change') { + module.validate.field( module.get.validation($field) ); + } + }, + change: function() { + var + $field = $(this), + $fieldGroup = $field.closest($group) + ; + if( $fieldGroup.hasClass(className.error) ) { + module.debug('Revalidating field', $field, module.get.validation($field)); + module.validate.field( module.get.validation($field) ); + } + else if(settings.on == 'change') { + module.validate.field( module.get.validation($field) ); + } + } + } + + }, + + get: { + changeEvent: function() { + return (document.createElement('input').oninput !== undefined) + ? 'input' + : (document.createElement('input').onpropertychange !== undefined) + ? 'propertychange' + : 'keyup' + ; + }, + field: function(identifier) { + module.verbose('Finding field with identifier', identifier); + if( $field.filter('#' + identifier).size() > 0 ) { + return $field.filter('#' + identifier); + } + else if( $field.filter('[name="' + identifier +'"]').size() > 0 ) { + return $field.filter('[name="' + identifier +'"]'); + } + else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').size() > 0 ) { + return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]'); + } + return $(''); + }, + validation: function($field) { + var + rules + ; + $.each(validation, function(fieldName, field) { + if( module.get.field(field.identifier).get(0) == $field.get(0) ) { + rules = field; + } + }); + return rules || false; + } + }, + + has: { + + field: function(identifier) { + module.verbose('Checking for existence of a field with identifier', identifier); + if( $field.filter('#' + identifier).size() > 0 ) { + return true; + } + else if( $field.filter('[name="' + identifier +'"]').size() > 0 ) { + return true; + } + else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').size() > 0 ) { + return true; + } + return false; + } + + }, + + add: { + prompt: function(field, errors) { + var + $field = module.get.field(field.identifier), + $fieldGroup = $field.closest($group), + $prompt = $fieldGroup.find(selector.prompt), + promptExists = ($prompt.size() !== 0) + ; + module.verbose('Adding inline error', field); + $fieldGroup + .addClass(className.error) + ; + if(settings.inline) { + if(!promptExists) { + $prompt = settings.templates.prompt(errors); + $prompt + .appendTo($fieldGroup) + ; + } + $prompt + .html(errors[0]) + ; + if(!promptExists) { + if(settings.transition && $.fn.transition !== undefined) { + module.verbose('Displaying error with css transition', settings.transition); + $prompt.transition(settings.transition + ' in', settings.duration); + } + else { + module.verbose('Displaying error with fallback javascript animation'); + $prompt + .fadeIn(settings.duration) + ; + } + } + } + }, + errors: function(errors) { + module.debug('Adding form error messages', errors); + $message + .html( settings.templates.error(errors) ) + ; + } + }, + + remove: { + prompt: function(field) { + var + $field = module.get.field(field.identifier), + $fieldGroup = $field.closest($group), + $prompt = $fieldGroup.find(selector.prompt) + ; + $fieldGroup + .removeClass(className.error) + ; + if(settings.inline && $prompt.is(':visible')) { + module.verbose('Removing prompt for field', field); + if(settings.transition && $.fn.transition !== undefined) { + $prompt.transition(settings.transition + ' out', settings.duration, function() { + $prompt.remove(); + }); + } + else { + $prompt + .fadeOut(settings.duration, function(){ + $prompt.remove(); + }) + ; + } + } + } + }, + + validate: { + + form: function(event) { + var + allValid = true + ; + // reset errors + formErrors = []; + $.each(validation, function(fieldName, field) { + if( !( module.validate.field(field) ) ) { + allValid = false; + } + }); + if(allValid) { + module.debug('Form has no validation errors, submitting'); + $module + .removeClass(className.error) + .addClass(className.success) + ; + $.proxy(settings.onSuccess, this)(event); + } + else { + module.debug('Form has errors'); + $module.addClass(className.error); + if(!settings.inline) { + module.add.errors(formErrors); + } + return $.proxy(settings.onFailure, this)(formErrors); + } + }, + + // takes a validation object and returns whether field passes validation + field: function(field) { + var + $field = module.get.field(field.identifier), + fieldValid = true, + fieldErrors = [] + ; + if(field.rules !== undefined) { + $.each(field.rules, function(index, rule) { + if( module.has.field(field.identifier) && !( module.validate.rule(field, rule) ) ) { + module.debug('Field is invalid', field.identifier, rule.type); + fieldErrors.push(rule.prompt); + fieldValid = false; + } + }); + } + if(fieldValid) { + module.remove.prompt(field, fieldErrors); + $.proxy(settings.onValid, $field)(); + } + else { + formErrors = formErrors.concat(fieldErrors); + module.add.prompt(field, fieldErrors); + $.proxy(settings.onInvalid, $field)(fieldErrors); + return false; + } + return true; + }, + + // takes validation rule and returns whether field passes rule + rule: function(field, validation) { + var + $field = module.get.field(field.identifier), + type = validation.type, + value = $field.val(), + + bracketRegExp = /\[(.*?)\]/i, + bracket = bracketRegExp.exec(type), + isValid = true, + ancillary, + functionType + ; + // if bracket notation is used, pass in extra parameters + if(bracket !== undefined && bracket !== null) { + ancillary = bracket[1]; + functionType = type.replace(bracket[0], ''); + isValid = $.proxy(settings.rules[functionType], $module)(value, ancillary); + } + // normal notation + else { + isValid = $.proxy(settings.rules[type], $field)(value); + } + return isValid; + } + }, + + setting: function(name, value) { + module.debug('Changing setting', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + module.debug('Changing internal', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.form.settings = { + + name : 'Form', + namespace : 'form', + + debug : true, + verbose : true, + performance : true, + + + keyboardShortcuts : true, + on : 'submit', + inline : false, + + transition : 'scale', + duration : 150, + + + onValid : function() {}, + onInvalid : function() {}, + onSuccess : function() { return true; }, + onFailure : function() { return false; }, + + metadata : { + validate: 'validate' + }, + + selector : { + message : '.error.message', + field : 'input, textarea, select', + group : '.field', + input : 'input', + prompt : '.prompt', + submit : '.submit' + }, + + className : { + error : 'error', + success : 'success', + down : 'down', + label : 'ui label prompt' + }, + + // errors + error: { + method : 'The method you called is not defined.' + }, + + + + templates: { + error: function(errors) { + var + html = '
    ' + ; + $.each(errors, function(index, value) { + html += '
  • ' + value + '
  • '; + }); + html += '
'; + return $(html); + }, + prompt: function(errors) { + return $('
') + .addClass('ui red pointing prompt label') + .html(errors[0]) + ; + } + }, + + rules: { + checked: function() { + return ($(this).filter(':checked').size() > 0); + }, + empty: function(value) { + return !(value === undefined || '' === value); + }, + email: function(value){ + var + emailRegExp = new RegExp("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?") + ; + return emailRegExp.test(value); + }, + length: function(value, requiredLength) { + return (value !== undefined) + ? (value.length >= requiredLength) + : false + ; + }, + not: function(value, notValue) { + return (value != notValue); + }, + contains: function(value, text) { + return (value.search(text) !== -1); + }, + is: function(value, text) { + return (value == text); + }, + maxLength: function(value, maxLength) { + return (value !== undefined) + ? (value.length <= maxLength) + : false + ; + }, + match: function(value, fieldIdentifier) { + // use either id or name of field + var + $form = $(this), + matchingValue + ; + if($form.find('#' + fieldIdentifier).size() > 0) { + matchingValue = $form.find('#' + fieldIdentifier).val(); + } + else if($form.find('[name=' + fieldIdentifier +']').size() > 0) { + matchingValue = $form.find('[name=' + fieldIdentifier + ']').val(); + } + else if( $form.find('[data-validate="'+ fieldIdentifier +'"]').size() > 0 ) { + matchingValue = $form.find('[data-validate="'+ fieldIdentifier +'"]').val(); + } + return (matchingValue !== undefined) + ? ( value.toString() == matchingValue.toString() ) + : false + ; + }, + url: function(value) { + var + urlRegExp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/ + ; + return urlRegExp.test(value); + } + } + +}; + +})( jQuery, window , document ); + +/* + * # Semantic - State + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.state = function(parameters) { + var + $allModules = $(this), + settings = $.extend(true, {}, $.fn.state.settings, parameters), + + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + + // shortcuts + error = settings.error, + metadata = settings.metadata, + className = settings.className, + namespace = settings.namespace, + states = settings.states, + text = settings.text, + + eventNamespace = '.' + namespace, + moduleNamespace = namespace + '-module', + + + invokedResponse + ; + $allModules + .each(function() { + var + $module = $(this), + + element = this, + instance = $module.data(moduleNamespace), + + module + ; + module = { + + initialize: function() { + module.verbose('Initializing module'); + + // allow module to guess desired state based on element + if(settings.automatic) { + module.add.defaults(); + } + + // bind events with delegated events + if(settings.context && moduleSelector !== '') { + if( module.allows('hover') ) { + $(element, settings.context) + .on(moduleSelector, 'mouseenter' + eventNamespace, module.enable.hover) + .on(moduleSelector, 'mouseleave' + eventNamespace, module.disable.hover) + ; + } + if( module.allows('down') ) { + $(element, settings.context) + .on(moduleSelector, 'mousedown' + eventNamespace, module.enable.down) + .on(moduleSelector, 'mouseup' + eventNamespace, module.disable.down) + ; + } + if( module.allows('focus') ) { + $(element, settings.context) + .on(moduleSelector, 'focus' + eventNamespace, module.enable.focus) + .on(moduleSelector, 'blur' + eventNamespace, module.disable.focus) + ; + } + $(settings.context) + .on(moduleSelector, 'mouseenter' + eventNamespace, module.change.text) + .on(moduleSelector, 'mouseleave' + eventNamespace, module.reset.text) + .on(moduleSelector, 'click' + eventNamespace, module.toggle.state) + ; + } + else { + if( module.allows('hover') ) { + $module + .on('mouseenter' + eventNamespace, module.enable.hover) + .on('mouseleave' + eventNamespace, module.disable.hover) + ; + } + if( module.allows('down') ) { + $module + .on('mousedown' + eventNamespace, module.enable.down) + .on('mouseup' + eventNamespace, module.disable.down) + ; + } + if( module.allows('focus') ) { + $module + .on('focus' + eventNamespace, module.enable.focus) + .on('blur' + eventNamespace, module.disable.focus) + ; + } + $module + .on('mouseenter' + eventNamespace, module.change.text) + .on('mouseleave' + eventNamespace, module.reset.text) + .on('click' + eventNamespace, module.toggle.state) + ; + } + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module', instance); + $module + .off(eventNamespace) + .removeData(moduleNamespace) + ; + }, + + refresh: function() { + module.verbose('Refreshing selector cache'); + $module = $(element); + }, + + add: { + defaults: function() { + var + userStates = parameters && $.isPlainObject(parameters.states) + ? parameters.states + : {} + ; + $.each(settings.defaults, function(type, typeStates) { + if( module.is[type] !== undefined && module.is[type]() ) { + module.verbose('Adding default states', type, element); + $.extend(settings.states, typeStates, userStates); + } + }); + } + }, + + is: { + + active: function() { + return $module.hasClass(className.active); + }, + loading: function() { + return $module.hasClass(className.loading); + }, + inactive: function() { + return !( $module.hasClass(className.active) ); + }, + + enabled: function() { + return !( $module.is(settings.filter.active) ); + }, + disabled: function() { + return ( $module.is(settings.filter.active) ); + }, + textEnabled: function() { + return !( $module.is(settings.filter.text) ); + }, + + // definitions for automatic type detection + button: function() { + return $module.is('.button:not(a, .submit)'); + }, + input: function() { + return $module.is('input'); + } + }, + + allow: function(state) { + module.debug('Now allowing state', state); + states[state] = true; + }, + disallow: function(state) { + module.debug('No longer allowing', state); + states[state] = false; + }, + + allows: function(state) { + return states[state] || false; + }, + + enable: { + state: function(state) { + if(module.allows(state)) { + $module.addClass( className[state] ); + } + }, + // convenience + focus: function() { + $module.addClass(className.focus); + }, + hover: function() { + $module.addClass(className.hover); + }, + down: function() { + $module.addClass(className.down); + }, + }, + + disable: { + state: function(state) { + if(module.allows(state)) { + $module.removeClass( className[state] ); + } + }, + // convenience + focus: function() { + $module.removeClass(className.focus); + }, + hover: function() { + $module.removeClass(className.hover); + }, + down: function() { + $module.removeClass(className.down); + }, + }, + + toggle: { + state: function() { + var + apiRequest = $module.data(metadata.promise) + ; + if( module.allows('active') && module.is.enabled() ) { + module.refresh(); + if(apiRequest !== undefined) { + module.listenTo(apiRequest); + } + else { + module.change.state(); + } + } + } + }, + + listenTo: function(apiRequest) { + module.debug('API request detected, waiting for state signal', apiRequest); + if(apiRequest) { + if(text.loading) { + module.update.text(text.loading); + } + $.when(apiRequest) + .then(function() { + if(apiRequest.state() == 'resolved') { + module.debug('API request succeeded'); + settings.activateTest = function(){ return true; }; + settings.deactivateTest = function(){ return true; }; + } + else { + module.debug('API request failed'); + settings.activateTest = function(){ return false; }; + settings.deactivateTest = function(){ return false; }; + } + module.change.state(); + }) + ; + } + // xhr exists but set to false, beforeSend killed the xhr + else { + settings.activateTest = function(){ return false; }; + settings.deactivateTest = function(){ return false; }; + } + }, + + // checks whether active/inactive state can be given + change: { + + state: function() { + module.debug('Determining state change direction'); + // inactive to active change + if( module.is.inactive() ) { + module.activate(); + } + else { + module.deactivate(); + } + if(settings.sync) { + module.sync(); + } + $.proxy(settings.onChange, element)(); + }, + + text: function() { + if( module.is.textEnabled() ) { + if( module.is.active() ) { + if(text.hover) { + module.verbose('Changing text to hover text', text.hover); + module.update.text(text.hover); + } + else if(text.disable) { + module.verbose('Changing text to disable text', text.disable); + module.update.text(text.disable); + } + } + else { + if(text.hover) { + module.verbose('Changing text to hover text', text.disable); + module.update.text(text.hover); + } + else if(text.enable){ + module.verbose('Changing text to enable text', text.enable); + module.update.text(text.enable); + } + } + } + } + + }, + + activate: function() { + if( $.proxy(settings.activateTest, element)() ) { + module.debug('Setting state to active'); + $module + .addClass(className.active) + ; + module.update.text(text.active); + } + $.proxy(settings.onActivate, element)(); + }, + + deactivate: function() { + if($.proxy(settings.deactivateTest, element)() ) { + module.debug('Setting state to inactive'); + $module + .removeClass(className.active) + ; + module.update.text(text.inactive); + } + $.proxy(settings.onDeactivate, element)(); + }, + + sync: function() { + module.verbose('Syncing other buttons to current state'); + if( module.is.active() ) { + $allModules + .not($module) + .state('activate'); + } + else { + $allModules + .not($module) + .state('deactivate') + ; + } + }, + + get: { + text: function() { + return (settings.selector.text) + ? $module.find(settings.selector.text).text() + : $module.html() + ; + }, + textFor: function(state) { + return text[state] || false; + } + }, + + flash: { + text: function(text, duration) { + var + previousText = module.get.text() + ; + module.debug('Flashing text message', text, duration); + text = text || settings.text.flash; + duration = duration || settings.flashDuration; + module.update.text(text); + setTimeout(function(){ + module.update.text(previousText); + }, duration); + } + }, + + reset: { + // on mouseout sets text to previous value + text: function() { + var + activeText = text.active || $module.data(metadata.storedText), + inactiveText = text.inactive || $module.data(metadata.storedText) + ; + if( module.is.textEnabled() ) { + if( module.is.active() && activeText) { + module.verbose('Resetting active text', activeText); + module.update.text(activeText); + } + else if(inactiveText) { + module.verbose('Resetting inactive text', activeText); + module.update.text(inactiveText); + } + } + } + }, + + update: { + text: function(text) { + var + currentText = module.get.text() + ; + if(text && text !== currentText) { + module.debug('Updating text', text); + if(settings.selector.text) { + $module + .data(metadata.storedText, text) + .find(settings.selector.text) + .text(text) + ; + } + else { + $module + .data(metadata.storedText, text) + .html(text) + ; + } + } + else { + module.debug('Text is already sane, ignoring update', text); + } + } + }, + + setting: function(name, value) { + module.debug('Changing setting', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + module.debug('Changing internal', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.state.settings = { + + // module info + name : 'State', + + // debug output + debug : true, + + // verbose debug output + verbose : true, + + // namespace for events + namespace : 'state', + + // debug data includes performance + performance: true, + + // callback occurs on state change + onActivate : function() {}, + onDeactivate : function() {}, + onChange : function() {}, + + // state test functions + activateTest : function() { return true; }, + deactivateTest : function() { return true; }, + + // whether to automatically map default states + automatic : true, + + // activate / deactivate changes all elements instantiated at same time + sync : false, + + // default flash text duration, used for temporarily changing text of an element + flashDuration : 3000, + + // selector filter + filter : { + text : '.loading, .disabled', + active : '.disabled' + }, + + context : false, + + // error + error: { + method : 'The method you called is not defined.' + }, + + // metadata + metadata: { + promise : 'promise', + storedText : 'stored-text' + }, + + // change class on state + className: { + focus : 'focus', + hover : 'hover', + down : 'down', + active : 'active', + loading : 'loading' + }, + + selector: { + // selector for text node + text: false + }, + + defaults : { + input: { + hover : true, + focus : true, + down : true, + loading : false, + active : false + }, + button: { + hover : true, + focus : false, + down : true, + active : true, + loading : true + } + }, + + states : { + hover : true, + focus : true, + down : true, + loading : false, + active : false + }, + + text : { + flash : false, + hover : false, + active : false, + inactive : false, + enable : false, + disable : false + } + +}; + + + +})( jQuery, window , document ); + +/* + * # Semantic - Chatroom + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ($, window, document, undefined) { + +$.fn.chatroom = function(parameters) { + var + settings = $.extend(true, {}, $.fn.chatroom.settings, parameters), + + className = settings.className, + namespace = settings.namespace, + selector = settings.selector, + error = settings.error, + + // hoist arguments + moduleArguments = arguments || false + ; + $(this) + .each(function() { + var + $module = $(this), + + $expandButton = $module.find(selector.expandButton), + $userListButton = $module.find(selector.userListButton), + + $userList = $module.find(selector.userList), + $room = $module.find(selector.room), + $userCount = $module.find(selector.userCount), + + $log = $module.find(selector.log), + $message = $module.find(selector.message), + + $messageInput = $module.find(selector.messageInput), + $messageButton = $module.find(selector.messageButton), + + instance = $module.data('module'), + + html = '', + users = {}, + + channel, + loggedInUser, + + message, + count, + + height, + + pusher, + module + ; + + module = { + + width: { + log : $log.width(), + userList : $userList.outerWidth() + }, + + initialize: function() { + + // check error conditions + if(Pusher === undefined) { + module.error(error.pusher); + } + if(settings.key === undefined || settings.channelName === undefined) { + module.error(error.key); + return false; + } + else if( !(settings.endpoint.message || settings.endpoint.authentication) ) { + module.error(error.endpoint); + return false; + } + + // define pusher + pusher = new Pusher(settings.key); + Pusher.channel_auth_endpoint = settings.endpoint.authentication; + + channel = pusher.subscribe(settings.channelName); + + channel.bind('pusher:subscription_succeeded', module.user.list.create); + channel.bind('pusher:subscription_error', module.error); + channel.bind('pusher:member_added', module.user.joined); + channel.bind('pusher:member_removed', module.user.left); + channel.bind('update_messages', module.message.receive); + + $.each(settings.customEvents, function(label, value) { + channel.bind(label, value); + }); + + // bind module events + $userListButton + .on('click.' + namespace, module.event.toggleUserList) + ; + $expandButton + .on('click.' + namespace, module.event.toggleExpand) + ; + $messageInput + .on('keydown.' + namespace, module.event.input.keydown) + .on('keyup.' + namespace, module.event.input.keyup) + ; + $messageButton + .on('mouseenter.' + namespace, module.event.hover) + .on('mouseleave.' + namespace, module.event.hover) + .on('click.' + namespace, module.event.submit) + ; + // scroll to bottom of chat log + $log + .animate({ + scrollTop: $log.prop('scrollHeight') + }, 400) + ; + $module + .data('module', module) + .addClass(className.loading) + ; + + }, + + // refresh module + refresh: function() { + // reset width calculations + $userListButton + .removeClass(className.active) + ; + module.width = { + log : $log.width(), + userList : $userList.outerWidth() + }; + if( $userListButton.hasClass(className.active) ) { + module.user.list.hide(); + } + $module.data('module', module); + }, + + user: { + + updateCount: function() { + if(settings.userCount) { + users = $module.data('users'); + count = 0; + $.each(users, function() { + count++; + }); + $userCount + .html( settings.templates.userCount(count) ) + ; + } + }, + + // add user to user list + joined: function(member) { + users = $module.data('users'); + if(member.id != 'anonymous' && users[ member.id ] === undefined ) { + users[ member.id ] = member.info; + if(settings.randomColor && member.info.color === undefined) { + member.info.color = settings.templates.color(member.id); + } + html = settings.templates.userList(member.info); + if(member.info.isAdmin) { + $(html) + .prependTo($userList) + ; + } + else { + $(html) + .appendTo($userList) + ; + } + if(settings.partingMessages) { + $log + .append( settings.templates.joined(member.info) ) + ; + module.message.scroll.test(); + } + module.user.updateCount(); + } + }, + + // remove user from user list + left: function(member) { + users = $module.data('users'); + if(member !== undefined && member.id !== 'anonymous') { + delete users[ member.id ]; + $module + .data('users', users) + ; + $userList + .find('[data-id='+ member.id + ']') + .remove() + ; + if(settings.partingMessages) { + $log + .append( settings.templates.left(member.info) ) + ; + module.message.scroll.test(); + } + module.user.updateCount(); + } + }, + + list: { + + // receives list of members and generates user list + create: function(members) { + users = {}; + members.each(function(member) { + if(member.id !== 'anonymous' && member.id !== 'undefined') { + if(settings.randomColor && member.info.color === undefined) { + member.info.color = settings.templates.color(member.id); + } + // sort list with admin first + html = (member.info.isAdmin) + ? settings.templates.userList(member.info) + html + : html + settings.templates.userList(member.info) + ; + users[ member.id ] = member.info; + } + }); + $module + .data('users', users) + .data('user', users[members.me.id] ) + .removeClass(className.loading) + ; + $userList + .html(html) + ; + module.user.updateCount(); + $.proxy(settings.onJoin, $userList.children())(); + }, + + // shows user list + show: function() { + $log + .animate({ + width: (module.width.log - module.width.userList) + }, { + duration : settings.speed, + easing : settings.easing, + complete : module.message.scroll.move + }) + ; + }, + + // hides user list + hide: function() { + $log + .stop() + .animate({ + width: (module.width.log) + }, { + duration : settings.speed, + easing : settings.easing, + complete : module.message.scroll.move + }) + ; + } + + } + + }, + + message: { + + // handles scrolling of chat log + scroll: { + test: function() { + height = $log.prop('scrollHeight') - $log.height(); + if( Math.abs($log.scrollTop() - height) < settings.scrollArea) { + module.message.scroll.move(); + } + }, + + move: function() { + height = $log.prop('scrollHeight') - $log.height(); + $log + .scrollTop(height) + ; + } + }, + + // sends chat message + send: function(message) { + if( !module.utils.emptyString(message) ) { + $.api({ + url : settings.endpoint.message, + method : 'POST', + data : { + 'message': { + content : message, + timestamp : new Date().getTime() + } + } + }); + } + }, + + // receives chat response and processes + receive: function(response) { + message = response.data; + users = $module.data('users'); + loggedInUser = $module.data('user'); + if(users[ message.userID] !== undefined) { + // logged in user's messages already pushed instantly + if(loggedInUser === undefined || loggedInUser.id != message.userID) { + message.user = users[ message.userID ]; + module.message.display(message); + } + } + }, + + // displays message in chat log + display: function(message) { + $log + .append( settings.templates.message(message) ) + ; + module.message.scroll.test(); + $.proxy(settings.onMessage, $log.children().last() )(); + } + + }, + + expand: function() { + $module + .addClass(className.expand) + ; + $.proxy(settings.onExpand, $module )(); + module.refresh(); + }, + + contract: function() { + $module + .removeClass(className.expand) + ; + $.proxy(settings.onContract, $module )(); + module.refresh(); + }, + + event: { + + input: { + + keydown: function(event) { + if(event.which == 13) { + $messageButton + .addClass(className.down) + ; + } + }, + + keyup: function(event) { + if(event.which == 13) { + $messageButton + .removeClass(className.down) + ; + module.event.submit(); + } + } + + }, + + // handles message form submit + submit: function() { + var + message = $messageInput.val(), + loggedInUser = $module.data('user') + ; + if(loggedInUser !== undefined && !module.utils.emptyString(message)) { + module.message.send(message); + // display immediately + module.message.display({ + user: loggedInUser, + text: message + }); + module.message.scroll.move(); + $messageInput + .val('') + ; + + } + }, + + // handles button click on expand button + toggleExpand: function() { + if( !$module.hasClass(className.expand) ) { + $expandButton + .addClass(className.active) + ; + module.expand(); + } + else { + $expandButton + .removeClass(className.active) + ; + module.contract(); + } + }, + + // handles button click on user list button + toggleUserList: function() { + if( !$log.is(':animated') ) { + if( !$userListButton.hasClass(className.active) ) { + $userListButton + .addClass(className.active) + ; + module.user.list.show(); + } + else { + $userListButton + .removeClass('active') + ; + module.user.list.hide(); + } + } + + } + }, + + utils: { + + emptyString: function(string) { + if(typeof string == 'string') { + return (string.search(/\S/) == -1); + } + return false; + } + + }, + + + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + title += ' ' + '(' + $allDropdowns.size() + ')'; + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + } + else { + module.error(error.method); + } + }); + } + if ( $.isFunction( found ) ) { + return found.apply(context, passedArguments); + } + return found || false; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + invokedResponse = module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) +; + + return (invokedResponse) + ? invokedResponse + : this + ; +}; + + $.fn.chatroom.settings = { + + name : 'Chat', + debug : false, + namespace : 'chat', + + channel : 'present-chat', + + onJoin : function(){}, + onMessage : function(){}, + onExpand : function(){}, + onContract : function(){}, + + customEvents : {}, + + partingMessages : false, + userCount : true, + randomColor : true, + + speed : 300, + easing : 'easeOutQuint', + + // pixels from bottom of chat log that should trigger auto scroll to bottom + scrollArea : 9999, + + endpoint : { + message : false, + authentication : false + }, + + error: { + method : 'The method you called is not defined', + endpoint : 'Please define a message and authentication endpoint.', + key : 'You must specify a pusher key and channel.', + pusher : 'You must include the Pusher library.' + }, + + className : { + expand : 'expand', + active : 'active', + hover : 'hover', + down : 'down', + loading : 'loading' + }, + + selector : { + userCount : '.actions .message', + userListButton : '.actions .list.button', + expandButton : '.actions .expand.button', + room : '.room', + userList : '.room .list', + log : '.room .log', + message : '.room .log .message', + author : '.room log .message .author', + messageInput : '.talk input', + messageButton : '.talk .send.button' + }, + + templates: { + + userCount: function(number) { + return number + ' users in chat'; + }, + + color: function(userID) { + var + colors = [ + '#000000', + '#333333', + '#666666', + '#999999', + '#CC9999', + '#CC6666', + '#CC3333', + '#993333', + '#663333', + '#CC6633', + '#CC9966', + '#CC9933', + '#999966', + '#CCCC66', + '#99CC66', + '#669933', + '#669966', + '#33A3CC', + '#336633', + '#33CCCC', + '#339999', + '#336666', + '#336699', + '#6666CC', + '#9966CC', + '#333399', + '#663366', + '#996699', + '#993366', + '#CC6699' + ] + ; + return colors[ Math.floor( Math.random() * colors.length) ]; + }, + + message: function(message) { + var + html = '' + ; + if(message.user.isAdmin) { + message.user.color = '#55356A'; + html += '
'; + html += ''; + } + /* + else if(message.user.isPro) { + html += '
'; + html += ''; + } + */ + else { + html += '
'; + } + html += '

'; + if(message.user.color !== undefined) { + html += '' + message.user.name + ': '; + } + else { + html += '' + message.user.name + ': '; + } + html += '' + + message.text + + '

' + + '
' + ; + return html; + }, + + joined: function(member) { + return (typeof member.name !== undefined) + ? '
' + member.name + ' has joined the chat.
' + : false + ; + }, + left: function(member) { + return (typeof member.name !== undefined) + ? '
' + member.name + ' has left the chat.
' + : false + ; + }, + + userList: function(member) { + var + html = '' + ; + if(member.isAdmin) { + member.color = '#55356A'; + } + html += '' + + '
' + + '
' + + ' ' + + '
' + ; + if(member.color !== undefined) { + html += '

' + member.name + '

'; + } + else { + html += '

' + member.name + '

'; + } + html += '
'; + return html; + } + + } + + }; + +})( jQuery, window , document ); + +/* + * # Semantic - Checkbox + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.checkbox = function(parameters) { + var + $allModules = $(this), + + settings = $.extend(true, {}, $.fn.checkbox.settings, parameters), + + className = settings.className, + namespace = settings.namespace, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + + $allModules + .each(function() { + var + $module = $(this), + $label = $(this).next(settings.selector.label).first(), + $input = $(this).find(settings.selector.input), + + selector = $module.selector || '', + instance = $module.data(moduleNamespace), + + element = this, + module + ; + + module = { + + initialize: function() { + module.verbose('Initializing checkbox', settings); + if(settings.context && selector !== '') { + module.verbose('Adding delegated events'); + $(element, settings.context) + .on(selector, 'click' + eventNamespace, module.toggle) + .on(selector + ' + ' + settings.selector.label, 'click' + eventNamespace, module.toggle) + ; + } + else { + $module + .on('click' + eventNamespace, module.toggle) + .data(moduleNamespace, module) + ; + $label + .on('click' + eventNamespace, module.toggle) + ; + } + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module'); + $module + .off(eventNamespace) + .removeData(moduleNamespace) + ; + }, + + is: { + radio: function() { + return $module.hasClass(className.radio); + } + }, + + can: { + disable: function() { + return (typeof settings.required === 'boolean') + ? settings.required + : !module.is.radio() + ; + } + }, + + enable: function() { + module.debug('Enabling checkbox'); + $input + .prop('checked', true) + ; + $.proxy(settings.onChange, $input.get())(); + $.proxy(settings.onEnable, $input.get())(); + }, + + disable: function() { + module.debug('Disabling checkbox'); + $input + .prop('checked', false) + ; + $.proxy(settings.onChange, $input.get())(); + $.proxy(settings.onDisable, $input.get())(); + }, + + toggle: function(event) { + module.verbose('Determining new checkbox state'); + if($input.prop('checked') === undefined || !$input.prop('checked')) { + module.enable(); + } + else if( module.can.disable() ) { + module.disable(); + } + }, + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.checkbox.settings = { + + name : 'Checkbox', + namespace : 'checkbox', + + verbose : true, + debug : true, + performance : true, + + // delegated event context + context : false, + required : 'auto', + + onChange : function(){}, + onEnable : function(){}, + onDisable : function(){}, + + error : { + method : 'The method you called is not defined.' + }, + + selector : { + input : 'input', + label : 'label' + }, + + className : { + radio : 'radio' + } + +}; + +})( jQuery, window , document ); + +/* + * # Semantic - Dimmer + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.dimmer = function(parameters) { + var + $allModules = $(this), + + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.dimmer.settings, parameters) + : $.fn.dimmer.settings, + + selector = settings.selector, + namespace = settings.namespace, + className = settings.className, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + clickEvent = ('ontouchstart' in document.documentElement) + ? 'touchstart' + : 'click', + + invokedResponse + ; + + $allModules + .each(function() { + var + $module = $(this), + $dimmer = $module.children(selector.dimmer).first(), + + element = this, + instance = $dimmer.data(moduleNamespace), + module + ; + + module = { + + initialize: function() { + if( module.is.dimmer() ) { + $dimmer = $module; + $module = $dimmer.parent(); + module.debug('Module initialized as dimmer', settings); + } + else { + if( module.has.dimmer() ) { + $dimmer = $module.children(selector.dimmer).first(); + module.debug('Module initialized with found dimmer', settings); + } + else { + module.create(); + module.debug('Module initialized with created dimmer', settings); + } + if(settings.on == 'hover') { + $module + .on('mouseenter' + eventNamespace, module.show) + .on('mouseleave' + eventNamespace, module.hide) + ; + } + else if(settings.on == 'click') { + $module + .on(clickEvent + eventNamespace, module.toggle) + ; + } + } + if(settings.closable) { + $dimmer + .on(clickEvent, module.event.click) + ; + } + module.set.dimmable(); + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module'); + instance = module; + $dimmer + .data(moduleNamespace, instance) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module'); + $module + .off(eventNamespace) + ; + }, + + event: { + + click: function(event) { + module.verbose('Determining if event occured on dimmer', event); + if( $dimmer.find(event.target).size() === 0 || $(event.target).is(selector.content) ) { + module.hide(); + event.stopImmediatePropagation(); + } + } + + }, + + create: function() { + $dimmer = settings.template.dimmer(); + $dimmer + .appendTo($module) + ; + if(module.is.page()) { + module.set.pageDimmer(); + } + }, + + animate: { + show: function(callback) { + callback = callback || function(){}; + module.set.dimmed(); + if($.fn.transition !== undefined) { + $dimmer + .transition(settings.transition + ' in', settings.duration, function() { + module.set.active(); + callback(); + }) + ; + } + else { + module.verbose('Showing dimmer animation with javascript'); + $dimmer + .stop() + .css({ + opacity : 0, + width : '100%', + height : '100%' + }) + .fadeTo(settings.duration, 1, function() { + $dimmer.removeAttr('style'); + module.set.active(); + callback(); + }) + ; + } + }, + hide: function(callback) { + callback = callback || function(){}; + module.remove.dimmed(); + if($.fn.transition !== undefined) { + module.verbose('Hiding dimmer with css'); + $dimmer + .transition(settings.transition + ' out', settings.duration, function() { + module.remove.active(); + callback(); + }) + ; + } + else { + module.verbose('Hiding dimmer with javascript'); + $dimmer + .stop() + .fadeOut(settings.duration, function() { + $dimmer.removeAttr('style'); + module.remove.active(); + callback(); + }) + ; + } + } + }, + + has: { + dimmer: function() { + return ( $module.children(selector.dimmer).size() > 0 ); + } + }, + + is: { + active: function() { + return $dimmer.hasClass(className.active); + }, + animating: function() { + return ( $dimmer.is(':animated') || $dimmer.hasClass(className.transition) ); + }, + dimmer: function() { + return $module.is(selector.dimmer); + }, + page: function () { + return $module.is('body'); + }, + dimmable: function() { + return $module.is(selector.dimmable); + }, + enabled: function() { + return !$module.hasClass(className.disabled); + }, + disabled: function() { + return $module.hasClass(className.disabled); + }, + pageDimmer: function() { + return $dimmer.hasClass(className.pageDimmer); + } + }, + + can: { + show: function() { + return !$dimmer.hasClass(className.disabled); + } + }, + + set: { + active: function() { + $dimmer + .removeClass(className.transition) + .addClass(className.active) + ; + }, + dimmable: function() { + $module + .addClass(className.dimmable) + ; + }, + dimmed: function() { + $module.addClass(className.dimmed); + }, + pageDimmer: function() { + $dimmer.addClass(className.pageDimmer); + }, + disabled: function() { + $dimmer.addClass(className.disabled); + } + }, + + remove: { + active: function() { + $dimmer + .removeClass(className.transition) + .removeClass(className.active) + ; + }, + dimmed: function() { + $module.removeClass(className.dimmed); + }, + disabled: function() { + $dimmer.removeClass(className.disabled); + } + }, + + show: function(callback) { + module.debug('Showing dimmer', $dimmer); + if( !(module.is.active() || module.is.animating() ) && module.is.enabled() ) { + module.animate.show(callback); + $.proxy(settings.onShow, element)(); + $.proxy(settings.onChange, element)(); + } + else { + module.debug('Dimmer is already shown or disabled'); + } + }, + + hide: function(callback) { + if( module.is.active() && !module.is.animating() ) { + module.debug('Hiding dimmer', $dimmer); + module.animate.hide(callback); + $.proxy(settings.onHide, element)(); + $.proxy(settings.onChange, element)(); + } + else { + module.debug('Dimmer is not visible'); + } + }, + + toggle: function() { + module.verbose('Toggling dimmer visibility', $dimmer); + if( !module.is.active() ) { + module.show(); + } + else { + module.hide(); + } + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.dimmer.settings = { + + name : 'Dimmer', + namespace : 'dimmer', + + verbose : true, + debug : true, + performance : true, + + transition : 'fade', + + on : false, + closable : true, + duration : 500, + + onChange : function(){}, + onShow : function(){}, + onHide : function(){}, + + error : { + method : 'The method you called is not defined.' + }, + + selector: { + dimmable : '.ui.dimmable', + dimmer : '.ui.dimmer', + content : '.ui.dimmer > .content, .ui.dimmer > .content > .center' + }, + + template: { + dimmer: function() { + return $('
').attr('class', 'ui dimmer'); + } + }, + + className : { + active : 'active', + dimmable : 'ui dimmable', + dimmed : 'dimmed', + disabled : 'disabled', + pageDimmer : 'page', + hide : 'hide', + show : 'show', + transition : 'transition' + } + +}; + +})( jQuery, window , document ); +/* + * # Semantic - Dropdown + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.dropdown = function(parameters) { + var + $allDropdowns = $(this), + $document = $(document), + + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.dropdown.settings, parameters) + : $.fn.dropdown.settings, + + className = settings.className, + metadata = settings.metadata, + namespace = settings.namespace, + selector = settings.selector, + error = settings.error, + + eventNamespace = '.' + namespace, + dropdownNamespace = 'module-' + namespace, + dropdownSelector = $allDropdowns.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + + $allDropdowns + .each(function() { + var + $dropdown = $(this), + $item = $dropdown.find(selector.item), + $text = $dropdown.find(selector.text), + $input = $dropdown.find(selector.input), + + $menu = $dropdown.children(selector.menu), + + isTouchDevice = ('ontouchstart' in document.documentElement), + + element = this, + instance = $dropdown.data(dropdownNamespace), + dropdown + ; + + dropdown = { + + initialize: function() { + dropdown.debug('Initializing dropdown', settings); + if(isTouchDevice) { + $dropdown + .on('touchstart' + eventNamespace, dropdown.event.test.toggle) + ; + } + else if(settings.on == 'click') { + $dropdown + .on('click' + eventNamespace, dropdown.event.test.toggle) + ; + } + else if(settings.on == 'hover') { + $dropdown + .on('mouseenter' + eventNamespace, dropdown.delay.show) + .on('mouseleave' + eventNamespace, dropdown.delay.hide) + ; + } + else { + $dropdown + .on(settings.on + eventNamespace, dropdown.toggle) + ; + } + if(settings.action == 'form') { + dropdown.set.selected(); + } + $item + .on('mouseenter' + eventNamespace, dropdown.event.item.mouseenter) + .on('mouseleave' + eventNamespace, dropdown.event.item.mouseleave) + .on(dropdown.get.selectEvent() + eventNamespace, dropdown.event.item.click) + ; + dropdown.instantiate(); + }, + + instantiate: function() { + dropdown.verbose('Storing instance of dropdown', dropdown); + $dropdown + .data(dropdownNamespace, dropdown) + ; + }, + + destroy: function() { + dropdown.verbose('Destroying previous dropdown for', $dropdown); + $item + .off(eventNamespace) + ; + $dropdown + .off(eventNamespace) + .removeData(dropdownNamespace) + ; + }, + + event: { + + stopPropagation: function(event) { + event.stopPropagation(); + }, + + test: { + toggle: function(event) { + dropdown.determine.intent(event, dropdown.toggle); + event.stopImmediatePropagation(); + }, + hide: function(event) { + dropdown.determine.intent(event, dropdown.hide); + event.stopPropagation(); + } + }, + + item: { + + mouseenter: function(event) { + var + $currentMenu = $(this).find(selector.menu), + $otherMenus = $(this).siblings(selector.item).children(selector.menu) + ; + if( $currentMenu.size() > 0 ) { + clearTimeout(dropdown.itemTimer); + dropdown.itemTimer = setTimeout(function() { + dropdown.animate.hide(false, $otherMenus); + dropdown.verbose('Showing sub-menu', $currentMenu); + dropdown.animate.show(false, $currentMenu); + }, settings.delay.show * 2); + } + }, + + mouseleave: function(event) { + var + $currentMenu = $(this).find(selector.menu) + ; + if($currentMenu.size() > 0) { + clearTimeout(dropdown.itemTimer); + dropdown.itemTimer = setTimeout(function() { + dropdown.verbose('Hiding sub-menu', $currentMenu); + dropdown.animate.hide(false, $currentMenu); + }, settings.delay.hide); + } + }, + + click: function (event) { + var + $choice = $(this), + text = $choice.data(metadata.text) || $choice.text(), + value = $choice.data(metadata.value) || text + ; + if( $choice.find(selector.menu).size() === 0 ) { + dropdown.verbose('Adding active state to selected item'); + $item + .removeClass(className.active) + ; + $choice + .addClass(className.active) + ; + dropdown.determine.selectAction(text, value); + $.proxy(settings.onChange, element)(value, text); + event.stopPropagation(); + } + } + + }, + + resetStyle: function() { + $(this).removeAttr('style'); + } + + }, + + determine: { + selectAction: function(text, value) { + dropdown.verbose('Determining action', settings.action); + if( $.isFunction( dropdown[settings.action] ) ) { + dropdown.verbose('Triggering preset action', settings.action); + dropdown[ settings.action ](text, value); + } + else if( $.isFunction(settings.action) ) { + dropdown.verbose('Triggering user action', settings.action); + settings.action(text, value); + } + else { + dropdown.error(error.action); + } + }, + intent: function(event, callback) { + dropdown.debug('Determining whether event occurred in dropdown', event.target); + callback = callback || function(){}; + if( $(event.target).closest($menu).size() === 0 ) { + dropdown.verbose('Triggering event', callback); + callback(); + } + else { + dropdown.verbose('Event occurred in dropdown, canceling callback'); + } + } + }, + + bind: { + intent: function() { + dropdown.verbose('Binding hide intent event to document'); + $document + .on(dropdown.get.selectEvent(), dropdown.event.test.hide) + ; + } + }, + + unbind: { + intent: function() { + dropdown.verbose('Removing hide intent event from document'); + $document + .off(dropdown.get.selectEvent()) + ; + } + }, + + nothing: function() {}, + + changeText: function(text, value) { + dropdown.set.text(text); + dropdown.hide(); + }, + + updateForm: function(text, value) { + dropdown.set.text(text); + dropdown.set.value(value); + dropdown.hide(); + }, + + get: { + selectEvent: function() { + return (isTouchDevice) + ? 'touchstart' + : 'click' + ; + }, + text: function() { + return $text.text(); + }, + value: function() { + return $input.val(); + }, + item: function(value) { + var + $selectedItem + ; + value = value || $input.val(); + $item + .each(function() { + if( $(this).data(metadata.value) == value ) { + $selectedItem = $(this); + } + }) + ; + return $selectedItem || false; + } + }, + + set: { + text: function(text) { + dropdown.debug('Changing text', text, $text); + $text.removeClass(className.placeholder); + $text.text(text); + }, + value: function(value) { + dropdown.debug('Adding selected value to hidden input', value, $input); + $input.val(value); + }, + active: function() { + $dropdown.addClass(className.active); + }, + visible: function() { + $dropdown.addClass(className.visible); + }, + selected: function(value) { + var + $selectedItem = dropdown.get.item(value), + selectedText + ; + if($selectedItem) { + dropdown.debug('Setting selected menu item to', $selectedItem); + selectedText = $selectedItem.data(metadata.text) || $selectedItem.text(); + $item + .removeClass(className.active) + ; + $selectedItem + .addClass(className.active) + ; + dropdown.set.text(selectedText); + } + } + }, + + remove: { + active: function() { + $dropdown.removeClass(className.active); + }, + visible: function() { + $dropdown.removeClass(className.visible); + } + }, + + is: { + visible: function($subMenu) { + return ($subMenu) + ? $subMenu.is(':animated, :visible') + : $menu.is(':animated, :visible') + ; + }, + hidden: function($subMenu) { + return ($subMenu) + ? $subMenu.is(':not(:animated, :visible)') + : $menu.is(':not(:animated, :visible)') + ; + } + }, + + can: { + click: function() { + return (isTouchDevice || settings.on == 'click'); + }, + show: function() { + return !$dropdown.hasClass(className.disabled); + } + }, + + animate: { + show: function(callback, $subMenu) { + var + $currentMenu = $subMenu || $menu + ; + callback = callback || function(){}; + if( dropdown.is.hidden($currentMenu) ) { + dropdown.verbose('Doing menu show animation', $currentMenu); + if(settings.transition == 'none') { + callback(); + } + else if($.fn.transition !== undefined) { + $currentMenu.transition({ + animation : settings.transition + ' in', + duration : settings.duration, + complete : callback, + queue : false + }) + } + else if(settings.transition == 'slide down') { + $currentMenu + .hide() + .clearQueue() + .children() + .clearQueue() + .css('opacity', 0) + .delay(50) + .animate({ + opacity : 1 + }, settings.duration, 'easeOutQuad', dropdown.event.resetStyle) + .end() + .slideDown(100, 'easeOutQuad', function() { + $.proxy(dropdown.event.resetStyle, this)(); + callback(); + }) + ; + } + else if(settings.transition == 'fade') { + $currentMenu + .hide() + .clearQueue() + .fadeIn(settings.duration, function() { + $.proxy(dropdown.event.resetStyle, this)(); + callback(); + }) + ; + } + else { + dropdown.error(error.transition); + } + } + }, + hide: function(callback, $subMenu) { + var + $currentMenu = $subMenu || $menu + ; + callback = callback || function(){}; + if(dropdown.is.visible($currentMenu) ) { + dropdown.verbose('Doing menu hide animation', $currentMenu); + if($.fn.transition !== undefined) { + $currentMenu.transition({ + animation : settings.transition + ' out', + duration : settings.duration, + complete : callback, + queue : false + }) + } + else if(settings.transition == 'none') { + callback(); + } + else if(settings.transition == 'slide down') { + $currentMenu + .show() + .clearQueue() + .children() + .clearQueue() + .css('opacity', 1) + .animate({ + opacity : 0 + }, 100, 'easeOutQuad', dropdown.event.resetStyle) + .end() + .delay(50) + .slideUp(100, 'easeOutQuad', function() { + $.proxy(dropdown.event.resetStyle, this)(); + callback(); + }) + ; + } + else if(settings.transition == 'fade') { + $currentMenu + .show() + .clearQueue() + .fadeOut(150, function() { + $.proxy(dropdown.event.resetStyle, this)(); + callback(); + }) + ; + } + else { + dropdown.error(error.transition); + } + } + } + }, + + show: function() { + dropdown.debug('Checking if dropdown can show'); + if( dropdown.is.hidden() ) { + dropdown.hideOthers(); + dropdown.set.active(); + dropdown.animate.show(dropdown.set.visible); + if( dropdown.can.click() ) { + dropdown.bind.intent(); + } + $.proxy(settings.onShow, element)(); + } + }, + + hide: function() { + if( dropdown.is.visible() ) { + dropdown.debug('Hiding dropdown'); + if( dropdown.can.click() ) { + dropdown.unbind.intent(); + } + dropdown.remove.active(); + dropdown.animate.hide(dropdown.remove.visible); + $.proxy(settings.onHide, element)(); + } + }, + + delay: { + show: function() { + dropdown.verbose('Delaying show event to ensure user intent'); + clearTimeout(dropdown.timer); + dropdown.timer = setTimeout(dropdown.show, settings.delay.show); + }, + hide: function() { + dropdown.verbose('Delaying hide event to ensure user intent'); + clearTimeout(dropdown.timer); + dropdown.timer = setTimeout(dropdown.hide, settings.delay.hide); + } + }, + + hideOthers: function() { + dropdown.verbose('Finding other dropdowns to hide'); + $allDropdowns + .not($dropdown) + .has(selector.menu + ':visible') + .dropdown('hide') + ; + }, + + toggle: function() { + dropdown.verbose('Toggling menu visibility'); + if( dropdown.is.hidden() ) { + dropdown.show(); + } + else { + dropdown.hide(); + } + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, dropdown, name); + } + else { + dropdown[name] = value; + } + } + else { + return dropdown[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + dropdown.performance.log(arguments); + } + else { + dropdown.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + dropdown.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + dropdown.performance.log(arguments); + } + else { + dropdown.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + dropdown.verbose.apply(console, arguments); + } + } + }, + error: function() { + dropdown.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + dropdown.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(dropdown.performance.timer); + dropdown.performance.timer = setTimeout(dropdown.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(dropdown.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(dropdownSelector) { + title += ' \'' + dropdownSelector + '\''; + } + title += ' ' + '(' + $allDropdowns.size() + ')'; + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + } + else { + dropdown.error(error.method); + } + }); + } + if ( $.isFunction( found ) ) { + return found.apply(context, passedArguments); + } + return found || false; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + dropdown.initialize(); + } + invokedResponse = dropdown.invoke(query); + } + else { + if(instance !== undefined) { + dropdown.destroy(); + } + dropdown.initialize(); + } + }) + ; + + return (invokedResponse) + ? invokedResponse + : this + ; +}; + +$.fn.dropdown.settings = { + + name : 'Dropdown', + namespace : 'dropdown', + + verbose : true, + debug : true, + performance : true, + + on : 'click', + action : 'hide', + + delay: { + show: 200, + hide: 300 + }, + + transition : 'slide down', + duration : 250, + + onChange : function(){}, + onShow : function(){}, + onHide : function(){}, + + error : { + action : 'You called a dropdown action that was not defined', + method : 'The method you called is not defined.', + transition : 'The requested transition was not found' + }, + + metadata: { + text : 'text', + value : 'value' + }, + + selector : { + menu : '.menu', + item : '.menu > .item', + text : '> .text', + input : '> input[type="hidden"]' + }, + + className : { + active : 'active', + placeholder : 'default', + disabled : 'disabled', + visible : 'visible' + } + +}; + +})( jQuery, window , document ); +/* + * # Semantic - Modal + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.modal = function(parameters) { + var + $allModals = $(this), + $document = $(document), + + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.modal.settings, parameters) + : $.fn.modal.settings, + + selector = settings.selector, + className = settings.className, + namespace = settings.namespace, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + moduleSelector = $allModals.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + + invokedResponse + ; + + $allModals + .each(function() { + var + $modal = $(this), + $context = $(settings.context), + $otherModals = $allModals.not($modal), + $closeButton = $modal.find(selector.closeButton), + + $dimmer, + + element = this, + instance = $modal.data(moduleNamespace), + modal + ; + + modal = { + + initialize: function() { + modal.verbose('Attaching events'); + $closeButton + .on('click', modal.event.close) + ; + modal.cache.sizes(); + + modal.verbose('Creating dimmer'); + $context + .dimmer({ + closable: settings.closable, + duration: settings.duration, + onShow: function() { + modal.add.keyboardShortcuts(); + $.proxy(settings.onShow, this)(); + }, + onHide: function() { + if($modal.is(':visible')) { + $context.off('.dimmer'); + modal.hide(); + $.proxy(settings.onHide, this)(); + } + modal.remove.keyboardShortcuts(); + } + }) + ; + $dimmer = $context.children(selector.dimmer); + if( $modal.parent()[0] !== $dimmer[0] ) { + modal.debug('Moving element inside dimmer', $context); + $modal = $modal + .detach() + .appendTo($dimmer) + ; + } + modal.instantiate(); + }, + + instantiate: function() { + modal.verbose('Storing instance of modal'); + instance = modal; + $modal + .data(moduleNamespace, instance) + ; + }, + + destroy: function() { + modal.verbose('Destroying previous modal'); + $modal + .off(eventNamespace) + ; + }, + + event: { + close: function() { + modal.verbose('Close button pressed'); + $context.dimmer('hide'); + }, + keyboard: function(event) { + var + keyCode = event.which, + escapeKey = 27 + ; + if(keyCode == escapeKey) { + modal.debug('Escape key pressed hiding modal'); + $context.dimmer('hide'); + event.preventDefault(); + } + }, + resize: function() { + modal.cache.sizes(); + if( $modal.is(':visible') ) { + modal.set.type(); + modal.set.position(); + } + } + }, + + toggle: function() { + if( modal.is.active() ) { + modal.hide(); + } + else { + modal.show(); + } + }, + + show: function() { + modal.debug('Showing modal'); + modal.set.type(); + modal.set.position(); + modal.hideAll(); + if(settings.transition && $.fn.transition !== undefined) { + $modal + .transition(settings.transition + ' in', settings.duration, modal.set.active) + ; + } + else { + $modal + .fadeIn(settings.duration, settings.easing, modal.set.active) + ; + } + modal.debug('Triggering dimmer'); + $context.dimmer('show'); + }, + + hide: function() { + modal.debug('Hiding modal'); + // remove keyboard detection + $document + .off('keyup.' + namespace) + ; + if(settings.transition && $.fn.transition !== undefined) { + $modal + .transition(settings.transition + ' out', settings.duration, modal.remove.active) + ; + } + else { + $modal + .fadeOut(settings.duration, settings.easing, modal.remove.active) + ; + } + }, + + hideAll: function() { + $otherModals + .filter(':visible') + .modal('hide') + ; + }, + + add: { + keyboardShortcuts: function() { + modal.verbose('Adding keyboard shortcuts'); + $document + .on('keyup' + eventNamespace, modal.event.keyboard) + ; + } + }, + + remove: { + active: function() { + $modal.removeClass(className.active); + }, + keyboardShortcuts: function() { + modal.verbose('Removing keyboard shortcuts'); + $document + .off('keyup' + eventNamespace) + ; + } + }, + + cache: { + sizes: function() { + modal.cache = { + height : $modal.outerHeight() + settings.offset, + contextHeight : (settings.context == 'body') + ? $(window).height() + : $context.height() + }; + console.log($modal); + modal.debug('Caching modal and container sizes', modal.cache); + } + }, + + can: { + fit: function() { + return (modal.cache.height < modal.cache.contextHeight); + } + }, + + is: { + active: function() { + return $modal.hasClass(className.active); + } + }, + + set: { + active: function() { + $modal.addClass('active'); + }, + type: function() { + if(modal.can.fit()) { + modal.verbose('Modal fits on screen'); + $modal.removeClass(className.scrolling); + } + else { + modal.verbose('Modal cannot fit on screen setting to scrolling'); + $modal.addClass(className.scrolling); + } + }, + position: function() { + modal.verbose('Centering modal on page', modal.cache.height / 2); + if(modal.can.fit()) { + $modal + .css({ + marginTop: -(modal.cache.height / 2) + }) + ; + } + else { + $modal + .css({ + top: $context.prop('scrollTop') + }) + ; + } + } + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, modal, name); + } + else { + modal[name] = value; + } + } + else { + return modal[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + modal.performance.log(arguments); + } + else { + modal.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + modal.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + modal.performance.log(arguments); + } + else { + modal.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + modal.verbose.apply(console, arguments); + } + } + }, + error: function() { + modal.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + modal.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(modal.performance.timer); + modal.performance.timer = setTimeout(modal.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(modal.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + modal.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + modal.initialize(); + } + invokedResponse = modal.invoke(query); + } + else { + if(instance !== undefined) { + modal.destroy(); + } + modal.initialize(); + } + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.modal.settings = { + + name : 'Modal', + namespace : 'modal', + verbose : true, + debug : true, + performance : true, + + offset : 0, + transition : 'scale', + duration : 500, + easing : 'easeOutExpo', + + closable : true, + context : 'body', + + onShow : function(){}, + onHide : function(){}, + + selector : { + closeButton : '.close, .actions .button', + dimmer: '.ui.dimmer' + }, + error : { + method : 'The method you called is not defined.' + }, + className : { + scrolling : 'scrolling' + }, +}; + + +})( jQuery, window , document ); +/* + * # Semantic - Nag + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ($, window, document, undefined) { + +$.fn.nag = function(parameters) { + var + $allModules = $(this), + settings = $.extend(true, {}, $.fn.nag.settings, parameters), + + className = settings.className, + selector = settings.selector, + error = settings.error, + namespace = settings.namespace, + + eventNamespace = '.' + namespace, + moduleNamespace = namespace + '-module', + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + $(this) + .each(function() { + var + $module = $(this), + + $close = $module.find(selector.close), + $context = $(settings.context), + + + element = this, + instance = $module.data(moduleNamespace), + + moduleOffset, + moduleHeight, + + contextWidth, + contextHeight, + contextOffset, + + yOffset, + yPosition, + + timer, + module, + + requestAnimationFrame = window.requestAnimationFrame + || window.mozRequestAnimationFrame + || window.webkitRequestAnimationFrame + || window.msRequestAnimationFrame + || function(callback) { setTimeout(callback, 0); } + ; + module = { + + initialize: function() { + module.verbose('Initializing element'); + // calculate module offset once + moduleOffset = $module.offset(); + moduleHeight = $module.outerHeight(); + contextWidth = $context.outerWidth(); + contextHeight = $context.outerHeight(); + contextOffset = $context.offset(); + + $module + .data(moduleNamespace, module) + ; + $close + .on('click' + eventNamespace, module.dismiss) + ; + // lets avoid javascript if we dont need to reposition + if(settings.context == window && settings.position == 'fixed') { + $module + .addClass(className.fixed) + ; + } + if(settings.sticky) { + module.verbose('Adding scroll events'); + // retrigger on scroll for absolute + if(settings.position == 'absolute') { + $context + .on('scroll' + eventNamespace, module.event.scroll) + .on('resize' + eventNamespace, module.event.scroll) + ; + } + // fixed is always relative to window + else { + $(window) + .on('scroll' + eventNamespace, module.event.scroll) + .on('resize' + eventNamespace, module.event.scroll) + ; + } + // fire once to position on init + $.proxy(module.event.scroll, this)(); + } + + if(settings.displayTime > 0) { + setTimeout(module.hide, settings.displayTime); + } + if(module.should.show()) { + if( !$module.is(':visible') ) { + module.show(); + } + } + else { + module.hide(); + } + }, + + destroy: function() { + module.verbose('Destroying instance'); + $module + .removeData(moduleNamespace) + .off(eventNamespace) + ; + if(settings.sticky) { + $context + .off(eventNamespace) + ; + } + }, + + refresh: function() { + module.debug('Refreshing cached calculations'); + moduleOffset = $module.offset(); + moduleHeight = $module.outerHeight(); + contextWidth = $context.outerWidth(); + contextHeight = $context.outerHeight(); + contextOffset = $context.offset(); + }, + + show: function() { + module.debug('Showing nag', settings.animation.show); + if(settings.animation.show == 'fade') { + $module + .fadeIn(settings.duration, settings.easing) + ; + } + else { + $module + .slideDown(settings.duration, settings.easing) + ; + } + }, + + hide: function() { + module.debug('Showing nag', settings.animation.hide); + if(settings.animation.show == 'fade') { + $module + .fadeIn(settings.duration, settings.easing) + ; + } + else { + $module + .slideUp(settings.duration, settings.easing) + ; + } + }, + + onHide: function() { + module.debug('Removing nag', settings.animation.hide); + $module.remove(); + if (settings.onHide) { + settings.onHide(); + } + }, + + stick: function() { + module.refresh(); + + if(settings.position == 'fixed') { + var + windowScroll = $(window).prop('pageYOffset') || $(window).scrollTop(), + fixedOffset = ( $module.hasClass(className.bottom) ) + ? contextOffset.top + (contextHeight - moduleHeight) - windowScroll + : contextOffset.top - windowScroll + ; + $module + .css({ + position : 'fixed', + top : fixedOffset, + left : contextOffset.left, + width : contextWidth - settings.scrollBarWidth + }) + ; + } + else { + $module + .css({ + top : yPosition + }) + ; + } + }, + unStick: function() { + $module + .css({ + top : '' + }) + ; + }, + dismiss: function(event) { + if(settings.storageMethod) { + module.storage.set(settings.storedKey, settings.storedValue); + } + module.hide(); + event.stopImmediatePropagation(); + event.preventDefault(); + }, + + should: { + show: function() { + if(settings.persist) { + module.debug('Persistent nag is set, can show nag'); + return true; + } + if(module.storage.get(settings.storedKey) != settings.storedValue) { + module.debug('Stored value is not set, can show nag', module.storage.get(settings.storedKey)); + return true; + } + module.debug('Stored value is set, cannot show nag', module.storage.get(settings.storedKey)); + return false; + }, + stick: function() { + yOffset = $context.prop('pageYOffset') || $context.scrollTop(); + yPosition = ( $module.hasClass(className.bottom) ) + ? (contextHeight - $module.outerHeight() ) + yOffset + : yOffset + ; + // absolute position calculated when y offset met + if(yPosition > moduleOffset.top) { + return true; + } + else if(settings.position == 'fixed') { + return true; + } + return false; + } + }, + + storage: { + + set: function(key, value) { + module.debug('Setting stored value', key, value, settings.storageMethod); + if(settings.storageMethod == 'local' && window.store !== undefined) { + window.store.set(key, value); + } + // store by cookie + else if($.cookie !== undefined) { + $.cookie(key, value); + } + else { + module.error(error.noStorage); + } + }, + get: function(key) { + module.debug('Getting stored value', key, settings.storageMethod); + if(settings.storageMethod == 'local' && window.store !== undefined) { + return window.store.get(key); + } + // get by cookie + else if($.cookie !== undefined) { + return $.cookie(key); + } + else { + module.error(error.noStorage); + } + } + + }, + + event: { + scroll: function() { + if(timer !== undefined) { + clearTimeout(timer); + } + timer = setTimeout(function() { + if(module.should.stick() ) { + requestAnimationFrame(module.stick); + } + else { + module.unStick(); + } + }, settings.lag); + } + }, + setting: function(name, value) { + module.debug('Changing setting', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + module.debug('Changing internal', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + + }) + ; + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.nag.settings = { + + name : 'Nag', + + verbose : true, + debug : true, + performance : true, + + namespace : 'Nag', + + // allows cookie to be overriden + persist : false, + + // set to zero to manually dismiss, otherwise hides on its own + displayTime : 0, + + animation : { + show: 'slide', + hide: 'slide' + }, + + // method of stickyness + position : 'fixed', + scrollBarWidth : 18, + + // type of storage to use + storageMethod : 'cookie', + + // value to store in dismissed localstorage/cookie + storedKey : 'nag', + storedValue : 'dismiss', + + // need to calculate stickyness on scroll + sticky : false, + + // how often to check scroll event + lag : 0, + + // context for scroll event + context : window, + + error: { + noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state', + method : 'The method you called is not defined.' + }, + + className : { + bottom : 'bottom', + fixed : 'fixed' + }, + + selector : { + close: '.icon.close' + }, + + speed : 500, + easing : 'easeOutQuad', + + onHide: function() {} + +}; + +})( jQuery, window , document ); + +/* + * # Semantic - Popup + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ($, window, document, undefined) { + +$.fn.popup = function(parameters) { + var + $allModules = $(this), + + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.popup.settings, parameters) + : $.fn.popup.settings, + + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + + invokedResponse + ; + $allModules + .each(function() { + var + $module = $(this), + + $window = $(window), + $offsetParent = $module.offsetParent(), + $popup = (settings.inline) + ? $module.next(settings.selector.popup) + : $window.children(settings.selector.popup).last(), + + searchDepth = 0, + + eventNamespace = '.' + settings.namespace, + moduleNamespace = settings.namespace + '-module', + + selector = settings.selector, + className = settings.className, + error = settings.error, + metadata = settings.metadata, + namespace = settings.namespace, + + element = this, + instance = $module.data(moduleNamespace), + module + ; + + module = { + + // binds events + initialize: function() { + module.debug('Initializing module', $module); + if(settings.on == 'hover') { + $module + .on('mouseenter' + eventNamespace, module.event.mouseenter) + .on('mouseleave' + eventNamespace, module.event.mouseleave) + ; + } + else { + $module + .on(settings.on + '' + eventNamespace, module.event[settings.on]) + ; + } + $window + .on('resize' + eventNamespace, module.event.resize) + ; + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, instance) + ; + }, + + refresh: function() { + $popup = (settings.inline) + ? $module.next(selector.popup) + : $window.children(selector.popup).last() + ; + $offsetParent = $module.offsetParent(); + }, + + destroy: function() { + module.debug('Destroying previous module'); + $module + .off(eventNamespace) + .removeData(moduleNamespace) + ; + }, + + event: { + mouseenter: function(event) { + var element = this; + module.timer = setTimeout(function() { + $.proxy(module.toggle, element)(); + if( $(element).hasClass(className.visible) ) { + event.stopPropagation(); + } + }, settings.delay); + }, + mouseleave: function() { + clearTimeout(module.timer); + if( $module.is(':visible') ) { + module.hide(); + } + }, + click: function(event) { + $.proxy(module.toggle, this)(); + if( $(this).hasClass(className.visible) ) { + event.stopPropagation(); + } + }, + resize: function() { + if( $popup.is(':visible') ) { + module.position(); + } + } + }, + + // generates popup html from metadata + create: function() { + module.debug('Creating pop-up html'); + var + html = $module.data(metadata.html) || settings.html, + variation = $module.data(metadata.variation) || settings.variation, + title = $module.data(metadata.title) || settings.title, + content = $module.data(metadata.content) || $module.attr('title') || settings.content + ; + if(html || content || title) { + if(!html) { + html = settings.template({ + title : title, + content : content + }); + } + $popup = $('
') + .addClass(className.popup) + .addClass(variation) + .html(html) + ; + if(settings.inline) { + module.verbose('Inserting popup element inline'); + $popup + .insertAfter($module) + ; + } + else { + module.verbose('Appending popup element to body'); + $popup + .appendTo( $('body') ) + ; + } + $.proxy(settings.onInit, $popup)(); + } + else { + module.error(error.content); + } + }, + + remove: function() { + module.debug('Removing popup'); + $popup + .remove() + ; + }, + + get: { + offstagePosition: function() { + var + boundary = { + top : $(window).scrollTop(), + bottom : $(window).scrollTop() + $(window).height(), + left : 0, + right : $(window).width() + }, + popup = { + width : $popup.width(), + height : $popup.outerHeight(), + position : $popup.offset() + }, + offstage = {}, + offstagePositions = [] + ; + if(popup.position) { + offstage = { + top : (popup.position.top < boundary.top), + bottom : (popup.position.top + popup.height > boundary.bottom), + right : (popup.position.left + popup.width > boundary.right), + left : (popup.position.left < boundary.left) + }; + } + // return only boundaries that have been surpassed + $.each(offstage, function(direction, isOffstage) { + if(isOffstage) { + offstagePositions.push(direction); + } + }); + return (offstagePositions.length > 0) + ? offstagePositions.join(' ') + : false + ; + }, + nextPosition: function(position) { + switch(position) { + case 'top left': + position = 'bottom left'; + break; + case 'bottom left': + position = 'top right'; + break; + case 'top right': + position = 'bottom right'; + break; + case 'bottom right': + position = 'top center'; + break; + case 'top center': + position = 'bottom center'; + break; + case 'bottom center': + position = 'right center'; + break; + case 'right center': + position = 'left center'; + break; + case 'left center': + position = 'top center'; + break; + } + return position; + } + }, + + // determines popup state + toggle: function() { + $module = $(this); + module.debug('Toggling pop-up'); + // refresh state of module + module.refresh(); + if( !$module.hasClass(className.visible) ) { + module.hideAll(); + module.show(); + } + else { + module.hide(); + } + }, + + position: function(position, arrowOffset) { + var + windowWidth = $(window).width(), + windowHeight = $(window).height(), + width = $module.outerWidth(), + height = $module.outerHeight(), + popupWidth = $popup.width(), + popupHeight = $popup.outerHeight(), + + offset = (settings.inline) + ? $module.position() + : $module.offset(), + parentWidth = (settings.inline) + ? $offsetParent.outerWidth() + : $window.outerWidth(), + parentHeight = (settings.inline) + ? $offsetParent.outerHeight() + : $window.outerHeight(), + + positioning, + offstagePosition + ; + position = position || $module.data(metadata.position) || settings.position; + arrowOffset = arrowOffset || $module.data(metadata.arrowOffset) || settings.arrowOffset; + module.debug('Calculating offset for position', position); + switch(position) { + case 'top left': + positioning = { + top : 'auto', + bottom : parentHeight - offset.top + settings.distanceAway, + left : offset.left + arrowOffset + }; + break; + case 'top center': + positioning = { + bottom : parentHeight - offset.top + settings.distanceAway, + left : offset.left + (width / 2) - (popupWidth / 2) + arrowOffset, + top : 'auto', + right : 'auto' + }; + break; + case 'top right': + positioning = { + bottom : parentHeight - offset.top + settings.distanceAway, + right : parentWidth - offset.left - width - arrowOffset, + top : 'auto', + left : 'auto' + }; + break; + case 'left center': + positioning = { + top : offset.top + (height / 2) - (popupHeight / 2), + right : parentWidth - offset.left + settings.distanceAway - arrowOffset, + left : 'auto', + bottom : 'auto' + }; + break; + case 'right center': + positioning = { + top : offset.top + (height / 2) - (popupHeight / 2), + left : offset.left + width + settings.distanceAway + arrowOffset, + bottom : 'auto', + right : 'auto' + }; + break; + case 'bottom left': + positioning = { + top : offset.top + height + settings.distanceAway, + left : offset.left + arrowOffset, + bottom : 'auto', + right : 'auto' + }; + break; + case 'bottom center': + positioning = { + top : offset.top + height + settings.distanceAway, + left : offset.left + (width / 2) - (popupWidth / 2) + arrowOffset, + bottom : 'auto', + right : 'auto' + }; + break; + case 'bottom right': + positioning = { + top : offset.top + height + settings.distanceAway, + right : parentWidth - offset.left - width - arrowOffset, + left : 'auto', + bottom : 'auto' + }; + break; + } + // true width on popup, avoid rounding error + $.extend(positioning, { + width: $popup.width() + 1 + }); + // tentatively place on stage + $popup + .removeAttr('style') + .removeClass('top right bottom left center') + .css(positioning) + .addClass(position) + .addClass(className.loading) + ; + // check if is offstage + offstagePosition = module.get.offstagePosition(); + // recursively find new positioning + if(offstagePosition) { + module.debug('Element is outside boundaries ', offstagePosition); + if(searchDepth < settings.maxSearchDepth) { + position = module.get.nextPosition(position); + searchDepth++; + module.debug('Trying new position: ', position); + return module.position(position); + } + else { + module.error(error.recursion); + searchDepth = 0; + return false; + } + } + else { + module.debug('Position is on stage', position); + searchDepth = 0; + return true; + } + }, + + show: function() { + module.debug('Showing pop-up', settings.transition); + if($popup.size() === 0) { + module.create(); + } + module.position(); + $module + .addClass(className.visible) + ; + $popup + .removeClass(className.loading) + ; + if(settings.transition && $.fn.transition !== undefined) { + $popup + .transition(settings.transition + ' in', settings.duration) + ; + } + else { + $popup + .stop() + .fadeIn(settings.duration, settings.easing) + ; + } + if(settings.on == 'click' && settings.clicktoClose) { + module.debug('Binding popup close event'); + $(document) + .on('click.' + namespace, module.gracefully.hide) + ; + } + $.proxy(settings.onShow, $popup)(); + }, + + hideAll: function() { + $(selector.popup) + .filter(':visible') + .popup('hide') + ; + }, + + hide: function() { + $module + .removeClass(className.visible) + ; + if($popup.is(':visible') ) { + module.debug('Hiding pop-up'); + if(settings.transition && $.fn.transition !== undefined) { + $popup + .transition(settings.transition + ' out', settings.duration) + ; + } + else { + $popup + .stop() + .fadeOut(settings.duration, settings.easing) + ; + } + } + if(settings.on == 'click' && settings.clicktoClose) { + $(document) + .off('click.' + namespace) + ; + } + $.proxy(settings.onHide, $popup)(); + if(!settings.inline) { + module.remove(); + } + }, + + gracefully: { + hide: function(event) { + // don't close on clicks inside popup + if( $(event.target).closest(selector.popup).size() === 0) { + module.hide(); + } + } + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.popup.settings = { + + name : 'Popup', + debug : true, + verbose : true, + performance : true, + namespace : 'popup', + + onInit : function(){}, + onShow : function(){}, + onHide : function(){}, + + variation : '', + content : false, + html : false, + title : false, + + on : 'hover', + clicktoClose : true, + + position : 'top center', + delay : 150, + inline : true, + + duration : 150, + easing : 'easeOutQuint', + transition : 'scale', + + distanceAway : 0, + arrowOffset : 0, + maxSearchDepth : 10, + + error: { + content : 'Your popup has no content specified', + method : 'The method you called is not defined.', + recursion : 'Popup attempted to reposition element to fit, but could not find an adequate position.' + }, + + metadata: { + arrowOffset : 'arrowOffset', + content : 'content', + html : 'html', + position : 'position', + title : 'title', + variation : 'variation' + }, + + className : { + popup : 'ui popup', + visible : 'visible', + loading : 'loading' + }, + + selector : { + popup : '.ui.popup' + }, + + template: function(text) { + var html = ''; + if(typeof text !== undefined) { + if(typeof text.title !== undefined && text.title) { + html += '
' + text.title + '
'; + } + if(typeof text.content !== undefined && text.content) { + html += '
' + text.content + '
'; + } + } + return html; + } + +}; + +})( jQuery, window , document ); + +/* + * # Semantic - Rating + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ($, window, document, undefined) { + +$.fn.rating = function(parameters) { + var + $allModules = $(this), + moduleSelector = $allModules.selector || '', + + settings = $.extend(true, {}, $.fn.rating.settings, parameters), + + namespace = settings.namespace, + className = settings.className, + metadata = settings.metadata, + selector = settings.selector, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + $allModules + .each(function() { + var + $module = $(this), + $icon = $module.find(selector.icon), + + element = this, + instance = $module.data(moduleNamespace), + module + ; + + module = { + + initialize: function() { + module.verbose('Initializing rating module'); + if(settings.interactive) { + $icon + .bind('mouseenter' + eventNamespace, module.event.mouseenter) + .bind('mouseleave' + eventNamespace, module.event.mouseleave) + .bind('click' + eventNamespace, module.event.click) + ; + } + if(settings.initialRating) { + module.debug('Setting initial rating'); + module.setRating(settings.initialRating); + } + if( $module.data(metadata.rating) ) { + module.debug('Rating found in metadata'); + module.setRating( $module.data(metadata.rating) ); + } + $module + .addClass(className.active) + ; + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Instantiating module', settings); + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + $module + .removeData(moduleNamespace) + ; + $icon + .off(eventNamespace) + ; + }, + + setRating: function(rating) { + var + $activeIcon = $icon.eq(rating - 1) + ; + module.verbose('Setting current rating to', rating); + $module + .removeClass(className.hover) + ; + $icon + .removeClass(className.hover) + ; + $activeIcon + .nextAll() + .removeClass(className.active) + ; + $activeIcon + .addClass(className.active) + .prevAll() + .addClass(className.active) + ; + $.proxy(settings.onRate, element)(); + }, + + event: { + mouseenter: function() { + var + $activeIcon = $(this) + ; + $activeIcon + .nextAll() + .removeClass(className.hover) + ; + $module + .addClass(className.hover) + ; + $activeIcon + .addClass(className.hover) + .prevAll() + .addClass(className.hover) + ; + }, + mouseleave: function() { + $module + .removeClass(className.hover) + ; + $icon + .removeClass(className.hover) + ; + }, + click: function() { + var + $activeIcon = $(this) + ; + module.setRating( $icon.index($activeIcon) + 1); + } + }, + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.rating.settings = { + + name : 'Rating', + namespace : 'rating', + + verbose : true, + debug : true, + performance : true, + + initialRating : 0, + interactive : true, + onRate : function(){}, + + error : { + method : 'The method you called is not defined' + }, + + metadata: { + rating: 'rating' + }, + + className : { + active : 'active', + hover : 'hover', + loading : 'loading' + }, + + selector : { + icon : '.icon' + } + +}; + +})( jQuery, window , document ); + +/* + * # Semantic - Search + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ($, window, document, undefined) { + +$.fn.search = function(source, parameters) { + var + $allModules = $(this), + settings = $.extend(true, {}, $.fn.search.settings, parameters), + + + className = settings.className, + selector = settings.selector, + error = settings.error, + namespace = settings.namespace, + + eventNamespace = '.' + namespace, + moduleNamespace = namespace + '-module', + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + $(this) + .each(function() { + var + $module = $(this), + $prompt = $module.find(selector.prompt), + $searchButton = $module.find(selector.searchButton), + $results = $module.find(selector.results), + $result = $module.find(selector.result), + $category = $module.find(selector.category), + + element = this, + instance = $module.data(moduleNamespace), + + module + ; + module = { + + initialize: function() { + module.verbose('Initializing module'); + var + prompt = $prompt[0], + inputEvent = (prompt.oninput !== undefined) + ? 'input' + : (prompt.onpropertychange !== undefined) + ? 'propertychange' + : 'keyup' + ; + // attach events + $prompt + .on('focus' + eventNamespace, module.event.focus) + .on('blur' + eventNamespace, module.event.blur) + .on('keydown' + eventNamespace, module.handleKeyboard) + ; + if(settings.automatic) { + $prompt + .on(inputEvent + eventNamespace, module.search.throttle) + ; + } + $searchButton + .on('click' + eventNamespace, module.search.query) + ; + $results + .on('click' + eventNamespace, selector.result, module.results.select) + ; + module.instantiate(); + }, + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, module) + ; + }, + destroy: function() { + module.verbose('Destroying instance'); + $module + .removeData(moduleNamespace) + ; + }, + event: { + focus: function() { + $module + .addClass(className.focus) + ; + module.results.show(); + }, + blur: function() { + module.search.cancel(); + $module + .removeClass(className.focus) + ; + module.results.hide(); + } + }, + handleKeyboard: function(event) { + var + // force latest jq dom + $result = $module.find(selector.result), + $category = $module.find(selector.category), + keyCode = event.which, + keys = { + backspace : 8, + enter : 13, + escape : 27, + upArrow : 38, + downArrow : 40 + }, + activeClass = className.active, + currentIndex = $result.index( $result.filter('.' + activeClass) ), + resultSize = $result.size(), + newIndex + ; + // search shortcuts + if(keyCode == keys.escape) { + module.verbose('Escape key pressed, blurring search field'); + $prompt + .trigger('blur') + ; + } + // result shortcuts + if($results.filter(':visible').size() > 0) { + if(keyCode == keys.enter) { + module.verbose('Enter key pressed, selecting active result'); + if( $result.filter('.' + activeClass).exists() ) { + $.proxy(module.results.select, $result.filter('.' + activeClass) )(); + event.preventDefault(); + return false; + } + } + else if(keyCode == keys.upArrow) { + module.verbose('Up key pressed, changing active result'); + newIndex = (currentIndex - 1 < 0) + ? currentIndex + : currentIndex - 1 + ; + $category + .removeClass(activeClass) + ; + $result + .removeClass(activeClass) + .eq(newIndex) + .addClass(activeClass) + .closest($category) + .addClass(activeClass) + ; + event.preventDefault(); + } + else if(keyCode == keys.downArrow) { + module.verbose('Down key pressed, changing active result'); + newIndex = (currentIndex + 1 >= resultSize) + ? currentIndex + : currentIndex + 1 + ; + $category + .removeClass(activeClass) + ; + $result + .removeClass(activeClass) + .eq(newIndex) + .addClass(activeClass) + .closest($category) + .addClass(activeClass) + ; + event.preventDefault(); + } + } + else { + // query shortcuts + if(keyCode == keys.enter) { + module.verbose('Enter key pressed, executing query'); + module.search.query(); + $searchButton + .addClass(className.down) + ; + $prompt + .one('keyup', function(){ + $searchButton + .removeClass(className.down) + ; + }) + ; + } + } + }, + search: { + cancel: function() { + var + xhr = $module.data('xhr') || false + ; + if( xhr && xhr.state() != 'resolved') { + module.debug('Cancelling last search'); + xhr.abort(); + } + }, + throttle: function() { + var + searchTerm = $prompt.val(), + numCharacters = searchTerm.length + ; + clearTimeout(module.timer); + if(numCharacters >= settings.minCharacters) { + module.timer = setTimeout(module.search.query, settings.searchThrottle); + } + else { + module.results.hide(); + } + }, + query: function() { + var + searchTerm = $prompt.val(), + cachedHTML = module.search.cache.read(searchTerm) + ; + if(cachedHTML) { + module.debug("Reading result for '" + searchTerm + "' from cache"); + module.results.add(cachedHTML); + } + else { + module.debug("Querying for '" + searchTerm + "'"); + if(typeof source == 'object') { + module.search.local(searchTerm); + } + else { + module.search.remote(searchTerm); + } + $.proxy(settings.onSearchQuery, $module)(searchTerm); + } + }, + local: function(searchTerm) { + var + results = [], + fullTextResults = [], + searchFields = $.isArray(settings.searchFields) + ? settings.searchFields + : [settings.searchFields], + + searchRegExp = new RegExp('(?:\s|^)' + searchTerm, 'i'), + fullTextRegExp = new RegExp(searchTerm, 'i'), + searchHTML + ; + $module + .addClass(className.loading) + ; + // iterate through search fields in array order + $.each(searchFields, function(index, field) { + $.each(source, function(label, thing) { + if(typeof thing[field] == 'string' && ($.inArray(thing, results) == -1) && ($.inArray(thing, fullTextResults) == -1) ) { + if( searchRegExp.test( thing[field] ) ) { + results.push(thing); + } + else if( fullTextRegExp.test( thing[field] ) ) { + fullTextResults.push(thing); + } + } + }); + }); + searchHTML = module.results.generate({ + results: $.merge(results, fullTextResults) + }); + $module + .removeClass(className.loading) + ; + module.search.cache.write(searchTerm, searchHTML); + module.results.add(searchHTML); + }, + remote: function(searchTerm) { + var + apiSettings = { + stateContext : $module, + url : source, + urlData: { query: searchTerm }, + success : function(response) { + searchHTML = module.results.generate(response); + module.search.cache.write(searchTerm, searchHTML); + module.results.add(searchHTML); + }, + failure : module.error + }, + searchHTML + ; + module.search.cancel(); + module.debug('Executing search'); + $.extend(true, apiSettings, settings.apiSettings); + $.api(apiSettings); + }, + + cache: { + read: function(name) { + var + cache = $module.data('cache') + ; + return (settings.cache && (typeof cache == 'object') && (cache[name] !== undefined) ) + ? cache[name] + : false + ; + }, + write: function(name, value) { + var + cache = ($module.data('cache') !== undefined) + ? $module.data('cache') + : {} + ; + cache[name] = value; + $module + .data('cache', cache) + ; + } + } + }, + + results: { + generate: function(response) { + module.debug('Generating html from response', response); + var + template = settings.templates[settings.type], + html = '' + ; + if(($.isPlainObject(response.results) && !$.isEmptyObject(response.results)) || ($.isArray(response.results) && response.results.length > 0) ) { + if(settings.maxResults > 0) { + response.results = $.makeArray(response.results).slice(0, settings.maxResults); + } + if(response.results.length > 0) { + if($.isFunction(template)) { + html = template(response); + } + else { + module.error(error.noTemplate, false); + } + } + } + else { + html = module.message(error.noResults, 'empty'); + } + $.proxy(settings.onResults, $module)(response); + return html; + }, + add: function(html) { + if(settings.onResultsAdd == 'default' || $.proxy(settings.onResultsAdd, $results)(html) == 'default') { + $results + .html(html) + ; + } + module.results.show(); + }, + show: function() { + if( ($results.filter(':visible').size() === 0) && ($prompt.filter(':focus').size() > 0) && $results.html() !== '') { + $results + .stop() + .fadeIn(200) + ; + $.proxy(settings.onResultsOpen, $results)(); + } + }, + hide: function() { + if($results.filter(':visible').size() > 0) { + $results + .stop() + .fadeOut(200) + ; + $.proxy(settings.onResultsClose, $results)(); + } + }, + select: function(event) { + module.debug('Search result selected'); + var + $result = $(this), + $title = $result.find('.title'), + title = $title.html() + ; + if(settings.onSelect == 'default' || $.proxy(settings.onSelect, this)(event) == 'default') { + var + $link = $result.find('a[href]').eq(0), + href = $link.attr('href') || false, + target = $link.attr('target') || false + ; + module.results.hide(); + $prompt + .val(title) + ; + if(href) { + if(target == '_blank' || event.ctrlKey) { + window.open(href); + } + else { + window.location.href = (href); + } + } + } + } + }, + + setting: function(name, value) { + module.debug('Changing setting', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + module.debug('Changing internal', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.search.settings = { + + name : 'Search Module', + namespace : 'search', + + debug : true, + verbose : true, + performance : true, + + // onSelect default action is defined in module + onSelect : 'default', + onResultsAdd : 'default', + + onSearchQuery : function(){}, + onResults : function(response){}, + + onResultsOpen : function(){}, + onResultsClose : function(){}, + + automatic : 'true', + type : 'simple', + minCharacters : 3, + searchThrottle : 300, + maxResults : 7, + cache : true, + + searchFields : [ + 'title', + 'description' + ], + + // api config + apiSettings: { + + }, + + className: { + active : 'active', + down : 'down', + focus : 'focus', + empty : 'empty', + loading : 'loading' + }, + + error : { + noResults : 'Your search returned no results', + logging : 'Error in debug logging, exiting.', + noTemplate : 'A valid template name was not specified.', + serverError : 'There was an issue with querying the server.', + method : 'The method you called is not defined.' + }, + + selector : { + prompt : '.prompt', + searchButton : '.search.button', + results : '.results', + category : '.category', + result : '.result' + }, + + templates: { + message: function(message, type) { + var + html = '' + ; + if(message !== undefined && type !== undefined) { + html += '' + + '
' + ; + // message type + if(type == 'empty') { + html += '' + + '
No Results
' + + '
' + message + '
' + ; + } + else { + html += '
' + message + '
'; + } + html += '
'; + } + return html; + }, + categories: function(response) { + var + html = '' + ; + if(response.results !== undefined) { + // each category + $.each(response.results, function(index, category) { + if(category.results !== undefined && category.results.length > 0) { + html += '' + + '
' + + '
' + category.name + '
' + ; + // each item inside category + $.each(category.results, function(index, result) { + html += '
'; + html += ''; + if(result.image !== undefined) { + html+= '' + + '
' + + ' ' + + '
' + ; + } + html += '
'; + if(result.price !== undefined) { + html+= '
' + result.price + '
'; + } + if(result.title !== undefined) { + html+= '
' + result.title + '
'; + } + if(result.description !== undefined) { + html+= '
' + result.description + '
'; + } + html += '' + + '
' + + '
' + ; + }); + html += '' + + '
' + ; + } + }); + if(response.resultPage) { + html += '' + + '' + + response.resultPage.text + + ''; + } + return html; + } + return false; + }, + simple: function(response) { + var + html = '' + ; + if(response.results !== undefined) { + + // each result + $.each(response.results, function(index, result) { + html += ''; + if(result.image !== undefined) { + html+= '' + + '
' + + ' ' + + '
' + ; + } + html += '
'; + if(result.price !== undefined) { + html+= '
' + result.price + '
'; + } + if(result.title !== undefined) { + html+= '
' + result.title + '
'; + } + if(result.description !== undefined) { + html+= '
' + result.description + '
'; + } + html += '' + + '
' + + '
' + ; + }); + + if(response.resultPage) { + html += '' + + '' + + response.resultPage.text + + ''; + } + return html; + } + return false; + } + } +}; + +})( jQuery, window , document ); +/* + * # Semantic - Shape + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.shape = function(parameters) { + var + $allModules = $(this), + + moduleSelector = $allModules.selector || '', + settings = $.extend(true, {}, $.fn.shape.settings, parameters), + + // internal aliases + namespace = settings.namespace, + selector = settings.selector, + error = settings.error, + className = settings.className, + + // define namespaces for modules + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + + $allModules + .each(function() { + var + // selector cache + $module = $(this), + $sides = $module.find(selector.sides), + $side = $module.find(selector.side), + + // private variables + $activeSide, + $nextSide, + + // standard module + element = this, + instance = $module.data(moduleNamespace), + module + ; + + module = { + + initialize: function() { + module.verbose('Initializing module for', element); + module.set.defaultSide(); + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, instance) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module for', element); + $module + .removeData(moduleNamespace) + .off(eventNamespace) + ; + }, + + refresh: function() { + module.verbose('Refreshing selector cache for', element); + $module = $(element); + $sides = $(this).find(selector.shape); + $side = $(this).find(selector.side); + }, + + repaint: function() { + module.verbose('Forcing repaint event'); + var + shape = $sides.get(0) || document.createElement('div'), + fakeAssignment = shape.offsetWidth + ; + }, + + animate: function(propertyObject, callback) { + module.verbose('Animating box with properties', propertyObject); + callback = callback || function(event) { + module.verbose('Executing animation callback'); + if(event !== undefined) { + event.stopPropagation(); + } + module.reset(); + module.set.active(); + }; + if(settings.useCSS) { + if(module.get.transitionEvent()) { + module.verbose('Starting CSS animation'); + $module + .addClass(className.animating) + ; + module.set.stageSize(); + module.repaint(); + $module + .addClass(className.css) + ; + $activeSide + .addClass(className.hidden) + ; + $sides + .css(propertyObject) + .one(module.get.transitionEvent(), callback) + ; + } + else { + callback(); + } + } + else { + // not yet supported until .animate() is extended to allow RotateX/Y + module.verbose('Starting javascript animation'); + $module + .addClass(className.animating) + .removeClass(className.css) + ; + module.set.stageSize(); + module.repaint(); + $activeSide + .animate({ + opacity: 0 + }, settings.duration, settings.easing) + ; + $sides + .animate(propertyObject, settings.duration, settings.easing, callback) + ; + } + }, + + queue: function(method) { + module.debug('Queueing animation of', method); + $sides + .one(module.get.transitionEvent(), function() { + module.debug('Executing queued animation'); + setTimeout(function(){ + $module.shape(method); + }, 0); + }) + ; + }, + + reset: function() { + module.verbose('Animating states reset'); + $module + .removeClass(className.css) + .removeClass(className.animating) + .attr('style', '') + .removeAttr('style') + ; + // removeAttr style does not consistently work in safari + $sides + .attr('style', '') + .removeAttr('style') + ; + $side + .attr('style', '') + .removeAttr('style') + .removeClass(className.hidden) + ; + $nextSide + .removeClass(className.animating) + .attr('style', '') + .removeAttr('style') + ; + }, + + is: { + animating: function() { + return $module.hasClass(className.animating); + } + }, + + get: { + + transform: { + up: function() { + var + translate = { + y: -(($activeSide.outerHeight() - $nextSide.outerHeight()) / 2), + z: -($activeSide.outerHeight() / 2) + } + ; + return { + transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(-90deg)' + }; + }, + + down: function() { + var + translate = { + y: -(($activeSide.outerHeight() - $nextSide.outerHeight()) / 2), + z: -($activeSide.outerHeight() / 2) + } + ; + return { + transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(90deg)' + }; + }, + + left: function() { + var + translate = { + x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2), + z : -($activeSide.outerWidth() / 2) + } + ; + return { + transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(90deg)' + }; + }, + + right: function() { + var + translate = { + x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2), + z : -($activeSide.outerWidth() / 2) + } + ; + return { + transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(-90deg)' + }; + }, + + over: function() { + var + translate = { + x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2) + } + ; + return { + transform: 'translateX(' + translate.x + 'px) rotateY(180deg)' + }; + }, + + back: function() { + var + translate = { + x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2) + } + ; + return { + transform: 'translateX(' + translate.x + 'px) rotateY(-180deg)' + }; + } + }, + + transitionEvent: function() { + var + element = document.createElement('element'), + transitions = { + 'transition' :'transitionend', + 'OTransition' :'oTransitionEnd', + 'MozTransition' :'transitionend', + 'WebkitTransition' :'webkitTransitionEnd' + }, + transition + ; + for(transition in transitions){ + if( element.style[transition] !== undefined ){ + return transitions[transition]; + } + } + }, + + nextSide: function() { + return ( $activeSide.next(selector.side).size() > 0 ) + ? $activeSide.next(selector.side) + : $module.find(selector.side).first() + ; + } + + }, + + set: { + + defaultSide: function() { + $activeSide = $module.find('.' + settings.className.active); + $nextSide = ( $activeSide.next(selector.side).size() > 0 ) + ? $activeSide.next(selector.side) + : $module.find(selector.side).first() + ; + module.verbose('Active side set to', $activeSide); + module.verbose('Next side set to', $nextSide); + }, + + stageSize: function() { + var + stage = { + width : $nextSide.outerWidth(), + height : $nextSide.outerHeight() + } + ; + module.verbose('Resizing stage to fit new content', stage); + $module + .css({ + width : stage.width, + height : stage.height + }) + ; + }, + + nextSide: function(selector) { + $nextSide = $module.find(selector); + if($nextSide.size() === 0) { + module.error(error.side); + } + module.verbose('Next side manually set to', $nextSide); + }, + + active: function() { + module.verbose('Setting new side to active', $nextSide); + $side + .removeClass(className.active) + ; + $nextSide + .addClass(className.active) + ; + $.proxy(settings.onChange, $nextSide)(); + module.set.defaultSide(); + } + }, + + flip: { + + up: function() { + module.debug('Flipping up', $nextSide); + if( !module.is.animating() ) { + module.stage.above(); + module.animate( module.get.transform.up() ); + } + else { + module.queue('flip up'); + } + }, + + down: function() { + module.debug('Flipping down', $nextSide); + if( !module.is.animating() ) { + module.stage.below(); + module.animate( module.get.transform.down() ); + } + else { + module.queue('flip down'); + } + }, + + left: function() { + module.debug('Flipping left', $nextSide); + if( !module.is.animating() ) { + module.stage.left(); + module.animate(module.get.transform.left() ); + } + else { + module.queue('flip left'); + } + }, + + right: function() { + module.debug('Flipping right', $nextSide); + if( !module.is.animating() ) { + module.stage.right(); + module.animate(module.get.transform.right() ); + } + else { + module.queue('flip right'); + } + }, + + over: function() { + module.debug('Flipping over', $nextSide); + if( !module.is.animating() ) { + module.stage.behind(); + module.animate(module.get.transform.over() ); + } + else { + module.queue('flip over'); + } + }, + + back: function() { + module.debug('Flipping back', $nextSide); + if( !module.is.animating() ) { + module.stage.behind(); + module.animate(module.get.transform.back() ); + } + else { + module.queue('flip back'); + } + } + + }, + + stage: { + + above: function() { + var + box = { + origin : (($activeSide.outerHeight() - $nextSide.outerHeight()) / 2), + depth : { + active : ($nextSide.outerHeight() / 2), + next : ($activeSide.outerHeight() / 2) + } + } + ; + module.verbose('Setting the initial animation position as above', $nextSide, box); + $activeSide + .css({ + 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)' + }) + ; + $nextSide + .addClass(className.animating) + .css({ + 'display' : 'block', + 'top' : box.origin + 'px', + 'transform' : 'rotateX(90deg) translateZ(' + box.depth.next + 'px)' + }) + ; + }, + + below: function() { + var + box = { + origin : (($activeSide.outerHeight() - $nextSide.outerHeight()) / 2), + depth : { + active : ($nextSide.outerHeight() / 2), + next : ($activeSide.outerHeight() / 2) + } + } + ; + module.verbose('Setting the initial animation position as below', $nextSide, box); + $activeSide + .css({ + 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)' + }) + ; + $nextSide + .addClass(className.animating) + .css({ + 'display' : 'block', + 'top' : box.origin + 'px', + 'transform' : 'rotateX(-90deg) translateZ(' + box.depth.next + 'px)' + }) + ; + }, + + left: function() { + var + box = { + origin : ( ( $activeSide.outerWidth() - $nextSide.outerWidth() ) / 2), + depth : { + active : ($nextSide.outerWidth() / 2), + next : ($activeSide.outerWidth() / 2) + } + } + ; + module.verbose('Setting the initial animation position as left', $nextSide, box); + $activeSide + .css({ + 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)' + }) + ; + $nextSide + .addClass(className.animating) + .css({ + 'display' : 'block', + 'left' : box.origin + 'px', + 'transform' : 'rotateY(-90deg) translateZ(' + box.depth.next + 'px)' + }) + ; + }, + + right: function() { + var + box = { + origin : ( ( $activeSide.outerWidth() - $nextSide.outerWidth() ) / 2), + depth : { + active : ($nextSide.outerWidth() / 2), + next : ($activeSide.outerWidth() / 2) + } + } + ; + module.verbose('Setting the initial animation position as left', $nextSide, box); + $activeSide + .css({ + 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)' + }) + ; + $nextSide + .addClass(className.animating) + .css({ + 'display' : 'block', + 'left' : box.origin + 'px', + 'transform' : 'rotateY(90deg) translateZ(' + box.depth.next + 'px)' + }) + ; + }, + + behind: function() { + var + box = { + origin : ( ( $activeSide.outerWidth() - $nextSide.outerWidth() ) / 2), + depth : { + active : ($nextSide.outerWidth() / 2), + next : ($activeSide.outerWidth() / 2) + } + } + ; + module.verbose('Setting the initial animation position as behind', $nextSide, box); + $activeSide + .css({ + 'transform' : 'rotateY(0deg)' + }) + ; + $nextSide + .addClass(className.animating) + .css({ + 'display' : 'block', + 'left' : box.origin + 'px', + 'transform' : 'rotateY(-180deg)' + }) + ; + } + }, + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.shape.settings = { + + // module info + name : 'Shape', + + // debug content outputted to console + debug : true, + + // verbose debug output + verbose : true, + + // performance data output + performance: true, + + // event namespace + namespace : 'shape', + + // callback occurs on side change + beforeChange : function() {}, + onChange : function() {}, + + // use css animation (currently only true is supported) + useCSS : true, + + // animation duration (useful only with future js animations) + duration : 1000, + easing : 'easeInOutQuad', + + // possible errors + error: { + side : 'You tried to switch to a side that does not exist.', + method : 'The method you called is not defined' + }, + + // classnames used + className : { + css : 'css', + animating : 'animating', + hidden : 'hidden', + active : 'active' + }, + + // selectors used + selector : { + sides : '.sides', + side : '.side' + } + +}; + + +})( jQuery, window , document ); +/* + * # Semantic - Dropdown + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.sidebar = function(parameters) { + var + $allModules = $(this), + + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.sidebar.settings, parameters) + : $.fn.sidebar.settings, + + selector = settings.selector, + className = settings.className, + namespace = settings.namespace, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + + $allModules + .each(function() { + var + $module = $(this), + + $body = $('body'), + $head = $('head'), + $style = $('style[title=' + namespace + ']'), + + element = this, + instance = $module.data(moduleNamespace), + module + ; + + module = { + + initialize: function() { + module.debug('Initializing sidebar', $module); + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module for', $module); + $module + .off(eventNamespace) + .removeData(moduleNamespace) + ; + }, + + refresh: function() { + module.verbose('Refreshing selector cache'); + $style = $('style[title=' + namespace + ']'); + }, + + attach: { + + events: function(selector, event) { + var + $toggle = $(selector) + ; + event = $.isFunction(module[event]) + ? module[event] + : module.toggle + ; + if($toggle.size() > 0) { + module.debug('Attaching sidebar events to element', selector, event); + $toggle + .off(eventNamespace) + .on('click' + eventNamespace, event) + ; + } + else { + module.error(error.notFound); + } + } + + }, + + show: function() { + module.debug('Showing sidebar'); + if(module.is.closed()) { + if(!settings.overlay) { + module.pushPage(); + } + module.set.active(); + } + else { + module.debug('Sidebar is already visible'); + } + }, + + hide: function() { + if(module.is.open()) { + if(!settings.overlay) { + module.pullPage(); + module.remove.pushed(); + } + module.remove.active(); + } + }, + + toggle: function() { + if(module.is.closed()) { + module.show(); + } + else { + module.hide(); + } + }, + + pushPage: function() { + var + direction = module.get.direction(), + distance = (module.is.vertical()) + ? $module.outerHeight() + : $module.outerWidth() + ; + if(settings.useCSS) { + module.debug('Using CSS to animate body'); + module.add.bodyCSS(direction, distance); + module.set.pushed(); + } + else { + module.animatePage(direction, distance, module.set.pushed); + } + }, + + pullPage: function() { + var + direction = module.get.direction() + ; + if(settings.useCSS) { + module.debug('Resetting body position css'); + module.remove.bodyCSS(); + } + else { + module.debug('Resetting body position using javascript'); + module.animatePage(direction, 0); + } + module.remove.pushed(); + }, + + animatePage: function(direction, distance) { + var + animateSettings = {} + ; + animateSettings['padding-' + direction] = distance; + module.debug('Using javascript to animate body', animateSettings); + $body + .animate(animateSettings, settings.duration, module.set.pushed) + ; + }, + + add: { + bodyCSS: function(direction, distance) { + var + style + ; + if(direction !== className.bottom) { + style = '' + + '' + ; + } + $head.append(style); + module.debug('Adding body css to head', $style); + } + }, + + remove: { + bodyCSS: function() { + module.debug('Removing body css styles', $style); + module.refresh(); + $style.remove(); + }, + active: function() { + $module.removeClass(className.active); + }, + pushed: function() { + module.verbose('Removing body push state', module.get.direction()); + $body + .removeClass(className[ module.get.direction() ]) + .removeClass(className.pushed) + ; + } + }, + + set: { + active: function() { + $module.addClass(className.active); + }, + pushed: function() { + module.verbose('Adding body push state', module.get.direction()); + $body + .addClass(className[ module.get.direction() ]) + .addClass(className.pushed) + ; + } + }, + + get: { + direction: function() { + if($module.hasClass(className.top)) { + return className.top; + } + else if($module.hasClass(className.right)) { + return className.right; + } + else if($module.hasClass(className.bottom)) { + return className.bottom; + } + else { + return className.left; + } + }, + transitionEvent: function() { + var + element = document.createElement('element'), + transitions = { + 'transition' :'transitionend', + 'OTransition' :'oTransitionEnd', + 'MozTransition' :'transitionend', + 'WebkitTransition' :'webkitTransitionEnd' + }, + transition + ; + for(transition in transitions){ + if( element.style[transition] !== undefined ){ + return transitions[transition]; + } + } + } + }, + + is: { + open: function() { + return $module.is(':animated') || $module.hasClass(className.active); + }, + closed: function() { + return !module.is.open(); + }, + vertical: function() { + return $module.hasClass(className.top); + } + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.sidebar.settings = { + + name : 'Sidebar', + namespace : 'sidebar', + + verbose : true, + debug : true, + performance : true, + + useCSS : true, + overlay : false, + duration : 300, + + side : 'left', + + onChange : function(){}, + onShow : function(){}, + onHide : function(){}, + + className: { + active : 'active', + pushed : 'pushed', + top : 'top', + left : 'left', + right : 'right', + bottom : 'bottom' + }, + + error : { + method : 'The method you called is not defined.', + notFound : 'There were no elements that matched the specified selector' + } + +}; + +})( jQuery, window , document ); +/* + * # Semantic - Tab + * http://github.com/jlukic/semantic-ui/ + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + + +;(function ($, window, document, undefined) { + + $.fn.tab = function(parameters) { + + var + settings = $.extend(true, {}, $.fn.tab.settings, parameters), + + $module = $(this), + $tabs = $(settings.context).find(settings.selector.tabs), + + moduleSelector = $module.selector || '', + + cache = {}, + firstLoad = true, + recursionDepth = 0, + + activeTabPath, + parameterArray, + historyEvent, + + element = this, + time = new Date().getTime(), + performance = [], + + className = settings.className, + metadata = settings.metadata, + error = settings.error, + + eventNamespace = '.' + settings.namespace, + moduleNamespace = settings.namespace + '-module', + + instance = $module.data(moduleNamespace), + + query = arguments[0], + methodInvoked = (instance !== undefined && typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + + module, + invokedResponse + ; + + module = { + + initialize: function() { + module.debug('Initializing Tabs', $module); + // attach history events + if(settings.history) { + if( $.address === undefined ) { + module.error(error.state); + return false; + } + else if(settings.path === false) { + module.error(error.path); + return false; + } + else { + if(settings.auto) { + settings.apiSettings = { + url: settings.path + '/{$tab}' + }; + } + module.verbose('Address library found adding state change event'); + $.address + .state(settings.path) + .unbind('change') + .bind('change', module.event.history.change) + ; + } + } + // attach events if navigation wasn't set to window + if( !$.isWindow( element ) ) { + $module + .on('click' + eventNamespace, module.event.click) + ; + } + module.instantiate(); + }, + + instantiate: function () { + module.verbose('Storing instance of module', module); + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.debug('Destroying tabs', $module); + $module + .off(eventNamespace) + ; + }, + + event: { + click: function() { + module.debug('Navigation clicked'); + var + tabPath = $(this).data(metadata.tab) + ; + if(tabPath !== undefined) { + if(settings.history) { + $.address.value(tabPath); + } + else { + module.changeTab(tabPath); + } + } + else { + module.debug('No tab specified'); + } + }, + history: { + change: function(event) { + var + tabPath = event.pathNames.join('/') || module.get.initialPath(), + pageTitle = settings.templates.determineTitle(tabPath) || false + ; + module.debug('History change event', tabPath, event); + historyEvent = event; + if(tabPath !== undefined) { + module.changeTab(tabPath); + } + if(pageTitle) { + $.address.title(pageTitle); + } + } + } + }, + + refresh: function() { + if(activeTabPath) { + module.debug('Refreshing tab', activeTabPath); + module.changeTab(activeTabPath); + } + }, + + cache: { + + read: function(cacheKey) { + return (cacheKey !== undefined) + ? cache[cacheKey] + : false + ; + }, + add: function(cacheKey, content) { + cacheKey = cacheKey || activeTabPath; + module.debug('Adding cached content for', cacheKey); + cache[cacheKey] = content; + }, + remove: function(cacheKey) { + cacheKey = cacheKey || activeTabPath; + module.debug('Removing cached content for', cacheKey); + delete cache[cacheKey]; + } + }, + + changeTab: function(tabPath) { + var + pushStateAvailable = (window.history && window.history.pushState), + shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad), + remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ), + // only get default path if not remote content + pathArray = (remoteContent && !shouldIgnoreLoad) + ? module.utilities.pathToArray(tabPath) + : module.get.defaultPathArray(tabPath), + tabPath = module.utilities.arrayToPath(pathArray) + ; + module.deactivate.all(); + $.each(pathArray, function(index, tab) { + var + currentPathArray = pathArray.slice(0, index + 1), + currentPath = module.utilities.arrayToPath(currentPathArray), + + isTab = module.is.tab(currentPath), + isLastIndex = (index + 1 == pathArray.length), + + $tab = module.get.tabElement(currentPath), + nextPathArray, + nextPath, + isLastTab + ; + module.verbose('Looking for tab', tab); + if(isTab) { + module.verbose('Tab was found', tab); + + // scope up + activeTabPath = currentPath; + parameterArray = module.utilities.filterArray(pathArray, currentPathArray); + + if(isLastIndex) { + isLastTab = true; + } + else { + nextPathArray = pathArray.slice(0, index + 2); + nextPath = module.utilities.arrayToPath(nextPathArray); + isLastTab = ( !module.is.tab(nextPath) ); + if(isLastTab) { + module.verbose('Tab parameters found', nextPathArray); + } + } + if(isLastTab && remoteContent) { + if(!shouldIgnoreLoad) { + module.activate.navigation(currentPath); + module.content.fetch(currentPath, tabPath); + } + else { + module.debug('Ignoring remote content on first tab load', currentPath); + firstLoad = false; + module.cache.add(tabPath, $tab.html()); + module.activate.all(currentPath); + $.proxy(settings.onTabInit, $tab)(currentPath, parameterArray, historyEvent); + $.proxy(settings.onTabLoad, $tab)(currentPath, parameterArray, historyEvent); + } + return false; + } + else { + module.debug('Opened local tab', currentPath); + module.activate.all(currentPath); + $.proxy(settings.onTabLoad, $tab)(currentPath, parameterArray, historyEvent); + } + } + else { + module.error(error.missingTab, tab); + return false; + } + }); + }, + + content: { + + fetch: function(tabPath, fullTabPath) { + var + $tab = module.get.tabElement(tabPath), + fullTabPath = fullTabPath || tabPath, + cachedContent = module.cache.read(fullTabPath), + apiSettings = { + dataType : 'html', + stateContext : $tab, + success : function(response) { + module.cache.add(fullTabPath, response); + module.content.update(tabPath, response); + if(tabPath == activeTabPath) { + module.debug('Content loaded', tabPath); + module.activate.tab(tabPath); + } + else { + module.debug('Content loaded in background', tabPath); + } + $.proxy(settings.onTabInit, $tab)(tabPath, parameterArray, historyEvent); + $.proxy(settings.onTabLoad, $tab)(tabPath, parameterArray, historyEvent); + }, + urlData: { tab: fullTabPath } + }, + request = $tab.data(metadata.promise) || false, + existingRequest = ( request && request.state() === 'pending' ) + ; + if(settings.cache && cachedContent) { + module.debug('Showing existing content', fullTabPath); + module.content.update(tabPath, cachedContent); + module.activate.tab(tabPath); + $.proxy(settings.onTabLoad, $tab)(tabPath, parameterArray, historyEvent); + } + else if(existingRequest) { + module.debug('Content is already loading', fullTabPath); + $tab + .addClass(className.loading) + ; + } + else if($.api !== undefined) { + module.debug('Retrieving remote content', fullTabPath); + $.api( $.extend(true, { headers: { 'X-Remote': true } }, settings.apiSettings, apiSettings) ); + } + else { + module.error(error.api); + } + }, + + update: function(tabPath, html) { + module.debug('Updating html for', tabPath); + var + $tab = module.get.tabElement(tabPath) + ; + $tab + .html(html) + ; + } + }, + + activate: { + all: function(tabPath) { + module.activate.tab(tabPath); + module.activate.navigation(tabPath); + }, + tab: function(tabPath) { + var + $tab = module.get.tabElement(tabPath) + ; + module.verbose('Showing tab content for', $tab); + $tab.addClass(className.active); + }, + navigation: function(tabPath) { + var + $navigation = module.get.navElement(tabPath) + ; + module.verbose('Activating tab navigation for', $navigation, tabPath); + $navigation.addClass(className.active); + } + }, + + deactivate: { + all: function() { + module.deactivate.navigation(); + module.deactivate.tabs(); + }, + navigation: function() { + $module + .removeClass(className.active) + ; + }, + tabs: function() { + $tabs + .removeClass(className.active + ' ' + className.loading) + ; + } + }, + + is: { + tab: function(tabName) { + return (tabName !== undefined) + ? ( module.get.tabElement(tabName).size() > 0 ) + : false + ; + } + }, + + get: { + initialPath: function() { + return $module.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab); + }, + path: function() { + return $.address.value(); + }, + // adds default tabs to tab path + defaultPathArray: function(tabPath) { + return module.utilities.pathToArray( module.get.defaultPath(tabPath) ); + }, + defaultPath: function(tabPath) { + var + $defaultNav = $module.filter('[data-' + metadata.tab + '^="' + tabPath + '/"]').eq(0), + defaultTab = $defaultNav.data(metadata.tab) || false + ; + if( defaultTab ) { + module.debug('Found default tab', defaultTab); + if(recursionDepth < settings.maxDepth) { + recursionDepth++; + return module.get.defaultPath(defaultTab); + } + module.error(error.recursion); + } + else { + module.debug('No default tabs found for', tabPath); + } + recursionDepth = 0; + return tabPath; + }, + navElement: function(tabPath) { + tabPath = tabPath || activeTabPath; + return $module.filter('[data-' + metadata.tab + '="' + tabPath + '"]'); + }, + tabElement: function(tabPath) { + var + $fullPathTab, + $simplePathTab, + tabPathArray, + lastTab + ; + tabPath = tabPath || activeTabPath; + tabPathArray = module.utilities.pathToArray(tabPath); + lastTab = module.utilities.last(tabPathArray); + $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + lastTab + '"]'); + $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + tabPath + '"]'); + return ($fullPathTab.size() > 0) + ? $fullPathTab + : $simplePathTab + ; + }, + tab: function() { + return activeTabPath; + } + }, + + utilities: { + filterArray: function(keepArray, removeArray) { + return $.grep(keepArray, function(keepValue) { + return ( $.inArray(keepValue, removeArray) == -1); + }); + }, + last: function(array) { + return $.isArray(array) + ? array[ array.length - 1] + : false + ; + }, + pathToArray: function(pathName) { + if(pathName === undefined) { + pathName = activeTabPath; + } + return typeof pathName == 'string' + ? pathName.split('/') + : [pathName] + ; + }, + arrayToPath: function(pathArray) { + return $.isArray(pathArray) + ? pathArray.join('/') + : false + ; + } + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; + + }; + + // shortcut for tabbed content with no defined navigation + $.tab = function(settings) { + $(window).tab(settings); + }; + + $.fn.tab.settings = { + + name : 'Tab', + verbose : true, + debug : true, + performance : true, + namespace : 'tab', + + // only called first time a tab's content is loaded (when remote source) + onTabInit : function(tabPath, parameterArray, historyEvent) {}, + // called on every load + onTabLoad : function(tabPath, parameterArray, historyEvent) {}, + + templates : { + determineTitle: function(tabArray) {} + }, + + // uses pjax style endpoints fetching content from same url with remote-content headers + auto : false, + + history : false, + path : false, + + context : 'body', + + // max depth a tab can be nested + maxDepth : 25, + // dont load content on first load + ignoreFirstLoad : true, + // load tab content new every tab click + alwaysRefresh : false, + // cache the content requests to pull locally + cache : true, + // settings for api call + apiSettings : false, + + error: { + api : 'You attempted to load content without API module', + noContent : 'The tab you specified is missing a content url.', + method : 'The method you called is not defined', + state : 'The state library has not been initialized', + missingTab : 'Tab cannot be found', + path : 'History enabled, but no path was specified', + recursion : 'Max recursive depth reached' + }, + + metadata : { + tab : 'tab', + loaded : 'loaded', + promise: 'promise' + }, + + className : { + loading : 'loading', + active : 'active' + }, + + selector : { + tabs : '.tab' + } + + }; + +})( jQuery, window , document ); + +/* + * # Semantic - Transition + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.transition = function() { + var + $allModules = $(this), + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + moduleArguments = arguments, + query = moduleArguments[0], + queryArguments = [].slice.call(arguments, 1), + methodInvoked = (typeof query === 'string'), + + requestAnimationFrame = window.requestAnimationFrame + || window.mozRequestAnimationFrame + || window.webkitRequestAnimationFrame + || window.msRequestAnimationFrame + || function(callback) { setTimeout(callback, 0); }, + + invokedResponse + ; + $allModules + .each(function() { + var + $module = $(this), + element = this, + + // set at run time + settings, + instance, + + error, + className, + metadata, + animationEnd, + animationName, + + namespace, + moduleNamespace, + module + ; + + module = { + + initialize: function() { + // get settings + settings = module.get.settings.apply(element, moduleArguments); + module.verbose('Converted arguments into settings object', settings); + + // set shortcuts + error = settings.error; + className = settings.className; + namespace = settings.namespace; + metadata = settings.metadata; + moduleNamespace = 'module-' + namespace; + + animationEnd = module.get.animationEvent(); + animationName = module.get.animationName(); + + instance = $module.data(moduleNamespace); + + if(instance === undefined) { + module.instantiate(); + } + if(methodInvoked) { + methodInvoked = module.invoke(query); + } + // no internal method was found matching query or query not made + if(methodInvoked === false) { + module.animate(); + } + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, instance) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module for', element); + $module + .removeData(moduleNamespace) + ; + }, + + animate: function(overrideSettings) { + settings = overrideSettings || settings; + module.debug('Preparing animation', settings.animation); + if(module.is.animating()) { + if(settings.queue) { + module.queue(settings.animation); + } + return false; + } + module.save.conditions(); + module.set.duration(settings.duration); + module.set.animating(); + module.repaint(); + $module + .addClass(className.transition) + .addClass(settings.animation) + .one(animationEnd, module.complete) + ; + if(!module.has.direction() && module.can.transition()) { + module.set.direction(); + } + if(!module.can.animate()) { + module.restore.conditions(); + module.error(error.noAnimation); + return false; + } + module.show(); + module.debug('Starting tween', settings.animation, $module.attr('class')); + }, + + queue: function(animation) { + module.debug('Queueing animation of', animation); + instance.queuing = true; + $module + .one(animationEnd, function() { + instance.queuing = false; + module.animate.apply(this, settings); + }) + ; + }, + + complete: function () { + module.verbose('CSS animation complete', settings.animation); + if(!module.is.looping()) { + if($module.hasClass(className.outward)) { + module.restore.conditions(); + module.hide(); + } + else if($module.hasClass(className.inward)) { + module.restore.conditions(); + module.show(); + } + else { + module.restore.conditions(); + } + module.remove.animating(); + } + $.proxy(settings.complete, this)(); + }, + + repaint: function(fakeAssignment) { + module.verbose('Forcing repaint event'); + fakeAssignment = element.offsetWidth; + }, + + has: { + direction: function(animation) { + animation = animation || settings.animation; + if( $module.hasClass(className.inward) || $module.hasClass(className.outward) ) { + return true; + } + } + }, + + set: { + + animating: function() { + $module.addClass(className.animating); + }, + + direction: function() { + if($module.is(':visible')) { + module.debug('Automatically determining the direction of animation', 'Outward'); + $module + .addClass(className.outward) + .removeClass(className.inward) + ; + } + else { + module.debug('Automatically determining the direction of animation', 'Inward'); + $module + .addClass(className.inward) + .removeClass(className.outward) + ; + } + }, + + looping: function() { + module.debug('Transition set to loop'); + $module + .addClass(className.looping) + ; + }, + + duration: function(duration) { + duration = duration || settings.duration; + duration = (typeof duration == 'number') + ? duration + 'ms' + : duration + ; + module.verbose('Setting animation duration', duration); + $module + .css({ + '-webkit-animation-duration': duration, + '-moz-animation-duration': duration, + '-ms-animation-duration': duration, + '-o-animation-duration': duration, + 'animation-duration': duration + }) + ; + } + }, + + save: { + conditions: function() { + module.cache = { + className : $module.attr('class'), + style : $module.attr('style') + }; + module.verbose('Saving original attributes', module.cache); + } + }, + + restore: { + conditions: function() { + if(typeof module.cache === undefined) { + module.error(error.cache); + return false; + } + if(module.cache.className) { + $module.attr('class', module.cache.className); + } + else { + $module.removeAttr('class'); + } + if(module.cache.style) { + $module.attr('style', module.cache.style); + } + else { + $module.removeAttr('style'); + } + if(module.is.looping()) { + module.remove.looping(); + } + module.verbose('Restoring original attributes', module.cache); + } + }, + + remove: { + + animating: function() { + $module.removeClass(className.animating); + }, + + looping: function() { + module.debug('Transitions are no longer looping'); + $module + .removeClass(className.looping) + ; + module.repaint(); + } + + }, + + get: { + + settings: function(animation, duration, complete) { + // single settings object + if($.isPlainObject(animation)) { + return $.extend(true, {}, $.fn.transition.settings, animation); + } + // all arguments provided + else if(typeof complete == 'function') { + return $.extend(true, {}, $.fn.transition.settings, { + animation : animation, + complete : complete, + duration : duration + }); + } + // only duration provided + else if(typeof duration == 'string' || typeof duration == 'number') { + return $.extend(true, {}, $.fn.transition.settings, { + animation : animation, + duration : duration + }); + } + // duration is actually settings object + else if(typeof duration == 'object') { + return $.extend(true, {}, $.fn.transition.settings, duration, { + animation : animation + }); + } + // duration is actually callback + else if(typeof duration == 'function') { + return $.extend(true, {}, $.fn.transition.settings, { + animation : animation, + complete : duration + }); + } + // only animation provided + else { + return $.extend(true, {}, $.fn.transition.settings, { + animation : animation + }); + } + return $.fn.transition.settings; + }, + + animationName: function() { + var + element = document.createElement('div'), + animations = { + 'animation' :'animationName', + 'OAnimation' :'oAnimationName', + 'MozAnimation' :'mozAnimationName', + 'WebkitAnimation' :'webkitAnimationName' + }, + animation + ; + for(animation in animations){ + if( element.style[animation] !== undefined ){ + module.verbose('Determining animation vendor name property', animations[animation]); + return animations[animation]; + } + } + return false; + }, + + animationEvent: function() { + var + element = document.createElement('div'), + animations = { + 'animation' :'animationend', + 'OAnimation' :'oAnimationEnd', + 'MozAnimation' :'mozAnimationEnd', + 'WebkitAnimation' :'webkitAnimationEnd' + }, + animation + ; + for(animation in animations){ + if( element.style[animation] !== undefined ){ + module.verbose('Determining animation vendor end event', animations[animation]); + return animations[animation]; + } + } + return false; + } + + }, + + can: { + animate: function() { + if($module.css(animationName) !== 'none') { + module.debug('CSS definition found'); + return true; + } + else { + module.debug('Unable to find css definition'); + return false; + } + }, + transition: function() { + var + $clone = $('
').addClass( $module.attr('class') ).appendTo($('body')), + currentAnimation = $clone.css(animationName), + inAnimation = $clone.addClass(className.inward).css(animationName) + ; + if(currentAnimation != inAnimation) { + module.debug('In/out transitions exist'); + $clone.remove(); + return true; + } + else { + module.debug('Static animation found'); + $clone.remove(); + return false; + } + } + }, + + is: { + animating: function() { + return $module.hasClass(className.animating); + }, + looping: function() { + return $module.hasClass(className.looping); + }, + visible: function() { + return $module.is(':visible'); + } + }, + + hide: function() { + module.verbose('Hiding element'); + $module + .removeClass(className.visible) + .addClass(className.transition) + .addClass(className.hidden) + ; + }, + show: function() { + module.verbose('Showing element'); + $module + .removeClass(className.hidden) + .addClass(className.transition) + .addClass(className.visible) + ; + }, + + start: function() { + module.verbose('Starting animation'); + $module.removeClass(className.disabled); + }, + + stop: function() { + module.debug('Stopping animation'); + $module.addClass(className.disabled); + }, + + toggle: function() { + module.debug('Toggling play status'); + $module.toggleClass(className.disabled); + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found || false; + } + }; + module.initialize(); + }) + ; + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.transition.settings = { + + // module info + name : 'Transition', + + // debug content outputted to console + debug : true, + + // verbose debug output + verbose : true, + + // performance data output + performance : true, + + // event namespace + namespace : 'transition', + + // animation complete event + complete : function() {}, + + // animation duration + animation : 'fade', + duration : '700ms', + + // queue up animations + queue : true, + + className : { + transition : 'ui transition', + animating : 'animating', + looping : 'looping', + loading : 'loading', + disabled : 'disabled', + hidden : 'hidden', + visible : 'visible', + inward : 'in', + outward : 'out' + }, + + // possible errors + error: { + noAnimation : 'There is no css animation matching the one you specified.', + method : 'The method you called is not defined' + } + +}; + + +})( jQuery, window , document ); + +/* ****************************** + Module - Video + Author: Jack Lukic + + This is a video playlist and video embed plugin which helps + provide helpers for adding embed code for vimeo and youtube and + abstracting event handlers for each library + +****************************** */ + +;(function ($, window, document, undefined) { + +$.fn.video = function(parameters) { + + var + $allModules = $(this), + + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.video.settings, parameters) + : $.fn.video.settings, + + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + + selector = settings.selector, + className = settings.className, + error = settings.error, + metadata = settings.metadata, + namespace = settings.namespace, + + eventNamespace = '.' + namespace, + moduleNamespace = namespace + '-module', + + invokedResponse + ; + + $allModules + .each(function() { + var + $module = $(this), + $placeholder = $module.find(selector.placeholder), + $playButton = $module.find(selector.playButton), + $embed = $module.find(selector.embed), + + element = this, + instance = $module.data(moduleNamespace), + module + ; + + module = { + + initialize: function() { + module.debug('Initializing video'); + $placeholder + .on('click' + eventNamespace, module.play) + ; + $playButton + .on('click' + eventNamespace, module.play) + ; + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.verbose('Destroying previous instance of video'); + $module + .removeData(moduleNamespace) + .off(eventNamespace) + ; + }, + + // sets new video + change: function(source, id, url) { + module.debug('Changing video to ', source, id, url); + $module + .data(metadata.source, source) + .data(metadata.id, id) + .data(metadata.url, url) + ; + settings.onChange(); + }, + + // clears video embed + reset: function() { + module.debug('Clearing video embed and showing placeholder'); + $module + .removeClass(className.active) + ; + $embed + .html(' ') + ; + $placeholder + .show() + ; + settings.onReset(); + }, + + // plays current video + play: function() { + module.debug('Playing video'); + var + source = $module.data(metadata.source) || false, + url = $module.data(metadata.url) || false, + id = $module.data(metadata.id) || false + ; + $embed + .html( module.generate.html(source, id, url) ) + ; + $module + .addClass(className.active) + ; + settings.onPlay(); + }, + + generate: { + // generates iframe html + html: function(source, id, url) { + module.debug('Generating embed html'); + var + width = (settings.width == 'auto') + ? $module.width() + : settings.width, + height = (settings.height == 'auto') + ? $module.height() + : settings.height, + html + ; + if(source && id) { + if(source == 'vimeo') { + html = '' + + '' + ; + } + else if(source == 'youtube') { + html = '' + + '' + ; + } + } + else if(url) { + html = '' + + '' + ; + } + else { + module.error(error.noVideo); + } + return html; + }, + + // generate url parameters + url: function(source) { + var + api = (settings.api) + ? 1 + : 0, + autoplay = (settings.autoplay) + ? 1 + : 0, + hd = (settings.hd) + ? 1 + : 0, + showUI = (settings.showUI) + ? 1 + : 0, + // opposite used for some params + hideUI = !(settings.showUI) + ? 1 + : 0, + url = '' + ; + if(source == 'vimeo') { + url = '' + + 'api=' + api + + '&title=' + showUI + + '&byline=' + showUI + + '&portrait=' + showUI + + '&autoplay=' + autoplay + ; + if(settings.color) { + url += '&color=' + settings.color; + } + } + if(source == 'ustream') { + url = '' + + 'autoplay=' + autoplay + ; + if(settings.color) { + url += '&color=' + settings.color; + } + } + else if(source == 'youtube') { + url = '' + + 'enablejsapi=' + api + + '&autoplay=' + autoplay + + '&autohide=' + hideUI + + '&hq=' + hd + + '&modestbranding=1' + ; + if(settings.color) { + url += '&color=' + settings.color; + } + } + return url; + } + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.video.settings = { + + name : 'Video', + namespace : 'video', + + debug : true, + verbose : true, + performance : true, + + metadata : { + source : 'source', + id : 'id', + url : 'url' + }, + + onPlay : function(){}, + onReset : function(){}, + onChange : function(){}, + + // callbacks not coded yet (needs to use jsapi) + onPause : function() {}, + onStop : function() {}, + + width : 'auto', + height : 'auto', + + autoplay : false, + color : '#442359', + hd : true, + showUI : false, + api : true, + + error : { + noVideo : 'No video specified', + method : 'The method you called is not defined' + }, + + className : { + active : 'active' + }, + + selector : { + embed : '.embed', + placeholder : '.placeholder', + playButton : '.play' + } +}; + + +})( jQuery, window , document ); diff --git a/node/Gruntfile.js b/node/Gruntfile.js index 003e7089f..005aff00b 100755 --- a/node/Gruntfile.js +++ b/node/Gruntfile.js @@ -258,10 +258,14 @@ module.exports = function(grunt) { concat: { options: { }, - all: { + css_uncompressed: { src: ["../build/uncompressed/**/*.css"], dest: "../build/packaged/css/semantic.css" }, + js_uncompressed: { + src: ["../build/uncompressed/**/*.js"], + dest: "../build/packaged/javascript/semantic.js" + }, }, cssmin: { diff --git a/node/src/files/build/packaged/javascript/semantic.js b/node/src/files/build/packaged/javascript/semantic.js new file mode 100644 index 000000000..2ac59e81e --- /dev/null +++ b/node/src/files/build/packaged/javascript/semantic.js @@ -0,0 +1,11048 @@ +/* + * # Semantic - Accordion + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ($, window, document, undefined) { + +$.fn.accordion = function(parameters) { + var + $allModules = $(this), + + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.accordion.settings, parameters) + : $.fn.accordion.settings, + + className = settings.className, + namespace = settings.namespace, + selector = settings.selector, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + $allModules + .each(function() { + var + $module = $(this), + $title = $module.find(selector.title), + $content = $module.find(selector.content), + + element = this, + instance = $module.data(moduleNamespace), + module + ; + + module = { + + initialize: function() { + module.debug('Initializing accordion with bound events', $module); + // initializing + $title + .on('click' + eventNamespace, module.event.click) + ; + module.instantiate(); + }, + + instantiate: function() { + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.debug('Destroying previous accordion for', $module); + $module + .removeData(moduleNamespace) + ; + $title + .off(eventNamespace) + ; + }, + + event: { + click: function() { + module.verbose('Title clicked', this); + var + $activeTitle = $(this), + index = $title.index($activeTitle) + ; + module.toggle(index); + }, + resetStyle: function() { + module.verbose('Resetting styles on element', this); + $(this) + .removeAttr('style') + .children() + .removeAttr('style') + ; + } + }, + + toggle: function(index) { + module.debug('Toggling content content at index', index); + var + $activeTitle = $title.eq(index), + $activeContent = $activeTitle.next($content), + contentIsOpen = $activeContent.is(':visible') + ; + if(contentIsOpen) { + if(settings.collapsible) { + module.close(index); + } + else { + module.debug('Cannot close accordion content collapsing is disabled'); + } + } + else { + module.open(index); + } + }, + + open: function(index) { + var + $activeTitle = $title.eq(index), + $activeContent = $activeTitle.next($content), + $previousTitle = $title.filter('.' + className.active), + $previousContent = $previousTitle.next($title), + contentIsOpen = ($previousTitle.size() > 0) + ; + if( !$activeContent.is(':animated') ) { + module.debug('Opening accordion content', $activeTitle); + if(settings.exclusive && contentIsOpen) { + $previousTitle + .removeClass(className.active) + ; + $previousContent + .stop() + .children() + .animate({ + opacity: 0 + }, settings.duration, module.event.resetStyle) + .end() + .slideUp(settings.duration , settings.easing, function() { + $previousContent + .removeClass(className.active) + .removeAttr('style') + .children() + .removeAttr('style') + ; + }) + ; + } + $activeTitle + .addClass(className.active) + ; + $activeContent + .stop() + .children() + .removeAttr('style') + .end() + .slideDown(settings.duration, settings.easing, function() { + $activeContent + .addClass(className.active) + .removeAttr('style') + ; + $.proxy(settings.onOpen, $activeContent)(); + $.proxy(settings.onChange, $activeContent)(); + }) + ; + } + }, + + close: function(index) { + var + $activeTitle = $title.eq(index), + $activeContent = $activeTitle.next($content) + ; + module.debug('Closing accordion content', $activeTitle); + $activeTitle + .removeClass(className.active) + ; + $activeContent + .removeClass(className.active) + .show() + .stop() + .children() + .animate({ + opacity: 0 + }, settings.duration, module.event.resetStyle) + .end() + .slideUp(settings.duration, settings.easing, function(){ + $activeContent + .removeAttr('style') + ; + $.proxy(settings.onClose, $activeContent)(); + $.proxy(settings.onChange, $activeContent)(); + }) + ; + }, + + setting: function(name, value) { + module.debug('Changing setting', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + module.debug('Changing internal', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.accordion.settings = { + name : 'Accordion', + namespace : 'accordion', + + debug : true, + verbose : true, + performance : true, + + exclusive : true, + collapsible : true, + + duration : 300, + easing : 'linear', + + onOpen : function(){}, + onClose : function(){}, + onChange : function(){}, + + error: { + method : 'The method you called is not defined' + }, + + className : { + active : 'active' + }, + + selector : { + title : '.title', + content : '.content' + }, + + +}; + +})( jQuery, window , document ); + +/* + * # Semantic - API + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + + $.api = $.fn.api = function(parameters) { + + var + settings = $.extend(true, {}, $.api.settings, parameters), + + // if this keyword isn't a jQuery object, create one + context = (typeof this != 'function') + ? this + : $('
'), + // context defines the element used for loading/error state + $context = (settings.stateContext) + ? $(settings.stateContext) + : $(context), + // module is the thing that initiates the api action, can be independent of context + $module = typeof this == 'object' + ? $(context) + : $context, + + element = this, + time = new Date().getTime(), + performance = [], + + moduleSelector = $module.selector || '', + moduleNamespace = settings.namespace + '-module', + + className = settings.className, + metadata = settings.metadata, + error = settings.error, + + instance = $module.data(moduleNamespace), + + query = arguments[0], + methodInvoked = (instance !== undefined && typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + + module, + invokedResponse + ; + + module = { + initialize: function() { + var + runSettings, + + loadingTimer = new Date().getTime(), + loadingDelay, + + promise, + url, + + formData = {}, + data, + + ajaxSettings = {}, + xhr + ; + + // serialize parent form if requested! + if(settings.serializeForm && $(this).toJSON() !== undefined) { + formData = module.get.formData(); + module.debug('Adding form data to API Request', formData); + $.extend(true, settings.data, formData); + } + + // let beforeSend change settings object + runSettings = $.proxy(settings.beforeSend, $module)(settings); + + // check for exit conditions + if(runSettings !== undefined && !runSettings) { + module.error(error.beforeSend); + module.reset(); + return; + } + + // get real url from template + url = module.get.url( module.get.templateURL() ); + + // exit conditions reached from missing url parameters + if( !url ) { + module.error(error.missingURL); + module.reset(); + return; + } + + // promise handles notification on api request, so loading min. delay can occur for all notifications + promise = + $.Deferred() + .always(function() { + if(settings.stateContext) { + $context + .removeClass(className.loading) + ; + } + $.proxy(settings.complete, $module)(); + }) + .done(function(response) { + module.debug('API request successful'); + // take a stab at finding success state if json + if(settings.dataType == 'json') { + if (response.error !== undefined) { + $.proxy(settings.failure, $context)(response.error, settings, $module); + } + else if ($.isArray(response.errors)) { + $.proxy(settings.failure, $context)(response.errors[0], settings, $module); + } + else { + $.proxy(settings.success, $context)(response, settings, $module); + } + } + // otherwise + else { + $.proxy(settings.success, $context)(response, settings, $module); + } + }) + .fail(function(xhr, status, httpMessage) { + var + errorMessage = (settings.error[status] !== undefined) + ? settings.error[status] + : httpMessage, + response + ; + // let em know unless request aborted + if(xhr !== undefined) { + // readyState 4 = done, anything less is not really sent + if(xhr.readyState !== undefined && xhr.readyState == 4) { + + // if http status code returned and json returned error, look for it + if( xhr.status != 200 && httpMessage !== undefined && httpMessage !== '') { + module.error(error.statusMessage + httpMessage); + } + else { + if(status == 'error' && settings.dataType == 'json') { + try { + response = $.parseJSON(xhr.responseText); + if(response && response.error !== undefined) { + errorMessage = response.error; + } + } + catch(error) { + module.error(error.JSONParse); + } + } + } + $context + .removeClass(className.loading) + .addClass(className.error) + ; + // show error state only for duration specified in settings + if(settings.errorLength > 0) { + setTimeout(function(){ + $context + .removeClass(className.error) + ; + }, settings.errorLength); + } + module.debug('API Request error:', errorMessage); + $.proxy(settings.failure, $context)(errorMessage, settings, this); + } + else { + module.debug('Request Aborted (Most likely caused by page change)'); + } + } + }) + ; + + // look for params in data + $.extend(true, ajaxSettings, settings, { + success : function(){}, + failure : function(){}, + complete : function(){}, + type : settings.method || settings.type, + data : data, + url : url, + beforeSend : settings.beforeXHR + }); + + if(settings.stateContext) { + $context + .addClass(className.loading) + ; + } + + if(settings.progress) { + module.verbose('Adding progress events'); + $.extend(true, ajaxSettings, { + xhr: function() { + var + xhr = new window.XMLHttpRequest() + ; + xhr.upload.addEventListener('progress', function(event) { + var + percentComplete + ; + if (event.lengthComputable) { + percentComplete = Math.round(event.loaded / event.total * 10000) / 100 + '%'; + $.proxy(settings.progress, $context)(percentComplete, event); + } + }, false); + xhr.addEventListener('progress', function(event) { + var + percentComplete + ; + if (event.lengthComputable) { + percentComplete = Math.round(event.loaded / event.total * 10000) / 100 + '%'; + $.proxy(settings.progress, $context)(percentComplete, event); + } + }, false); + return xhr; + } + }); + } + + module.verbose('Creating AJAX request with settings: ', ajaxSettings); + xhr = + $.ajax(ajaxSettings) + .always(function() { + // calculate if loading time was below minimum threshold + loadingDelay = ( settings.loadingLength - (new Date().getTime() - loadingTimer) ); + settings.loadingDelay = loadingDelay < 0 + ? 0 + : loadingDelay + ; + }) + .done(function(response) { + var + context = this + ; + setTimeout(function(){ + promise.resolveWith(context, [response]); + }, settings.loadingDelay); + }) + .fail(function(xhr, status, httpMessage) { + var + context = this + ; + // page triggers abort on navigation, dont show error + if(status != 'abort') { + setTimeout(function(){ + promise.rejectWith(context, [xhr, status, httpMessage]); + }, settings.loadingDelay); + } + else { + $context + .removeClass(className.error) + .removeClass(className.loading) + ; + } + }) + ; + if(settings.stateContext) { + $module + .data(metadata.promise, promise) + .data(metadata.xhr, xhr) + ; + } + }, + + get: { + formData: function() { + return $module + .closest('form') + .toJSON() + ; + }, + templateURL: function() { + var + action = $module.data(settings.metadata.action) || settings.action || false, + url + ; + if(action) { + module.debug('Creating url for: ', action); + if(settings.api[action] !== undefined) { + url = settings.api[action]; + } + else { + module.error(error.missingAction); + } + } + // override with url if specified + if(settings.url) { + url = settings.url; + module.debug('Getting url', url); + } + return url; + }, + url: function(url, urlData) { + var + urlVariables + ; + if(url) { + urlVariables = url.match(settings.regExpTemplate); + urlData = urlData || settings.urlData; + + if(urlVariables) { + module.debug('Looking for URL variables', urlVariables); + $.each(urlVariables, function(index, templateValue){ + var + term = templateValue.substr( 2, templateValue.length - 3), + termValue = ($.isPlainObject(urlData) && urlData[term] !== undefined) + ? urlData[term] + : ($module.data(term) !== undefined) + ? $module.data(term) + : urlData[term] + ; + module.verbose('Looking for variable', term, $module, $module.data(term), urlData[term]); + // remove optional value + if(termValue === false) { + module.debug('Removing variable from URL', urlVariables); + url = url.replace('/' + templateValue, ''); + } + // undefined condition + else if(termValue === undefined || !termValue) { + module.error(error.missingParameter + term); + url = false; + return false; + } + else { + url = url.replace(templateValue, termValue); + } + }); + } + } + return url; + } + }, + + // reset api request + reset: function() { + $module + .data(metadata.promise, false) + .data(metadata.xhr, false) + ; + $context + .removeClass(className.error) + .removeClass(className.loading) + ; + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; + }; + + // handle DOM attachment to API functionality + $.fn.apiButton = function(parameters) { + $(this) + .each(function(){ + var + // if only function passed it is success callback + $module = $(this), + selector = $(this).selector || '', + + settings = ( $.isFunction(parameters) ) + ? $.extend(true, {}, $.api.settings, $.fn.apiButton.settings, { stateContext: this, success: parameters }) + : $.extend(true, {}, $.api.settings, $.fn.apiButton.settings, { stateContext: this}, parameters), + module + ; + module = { + initialize: function() { + if(settings.context && selector !== '') { + $(settings.context) + .on(selector, 'click.' + settings.namespace, module.click) + ; + } + else { + $module + .on('click.' + settings.namespace, module.click) + ; + } + }, + click: function() { + if(!settings.filter || $(this).filter(settings.filter).size() === 0) { + $.proxy( $.api, this )(settings); + } + } + }; + module.initialize(); + }) + ; + return this; + }; + + $.api.settings = { + + name : 'API', + namespace : 'api', + + debug : true, + verbose : true, + performance : true, + + api : {}, + + beforeSend : function(settings) { + return settings; + }, + beforeXHR : function(xhr) {}, + success : function(response) {}, + complete : function(response) {}, + failure : function(errorCode) {}, + progress : false, + + error : { + missingAction : 'API action used but no url was defined', + missingURL : 'URL not specified for the API action', + missingParameter : 'Missing an essential URL parameter: ', + + timeout : 'Your request timed out', + error : 'There was an error with your request', + parseError : 'There was an error parsing your request', + JSONParse : 'JSON could not be parsed during error handling', + statusMessage : 'Server gave an error: ', + beforeSend : 'The before send function has aborted the request', + exitConditions : 'API Request Aborted. Exit conditions met' + }, + + className: { + loading : 'loading', + error : 'error' + }, + + metadata: { + action : 'action', + promise : 'promise', + xhr : 'xhr' + }, + + regExpTemplate: /\{\$([A-z]+)\}/g, + + action : false, + url : false, + urlData : false, + serializeForm : false, + + stateContext : false, + + method : 'get', + data : {}, + dataType : 'json', + cache : true, + + loadingLength : 200, + errorLength : 2000 + + }; + + $.fn.apiButton.settings = { + filter : '.disabled, .loading', + context : false, + stateContext : false + }; + +})( jQuery, window , document ); +/* + * # Semantic - Colorize + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + + $.fn.colorize = function(parameters) { + var + settings = $.extend(true, {}, $.fn.colorize.settings, parameters), + // hoist arguments + moduleArguments = arguments || false + ; + $(this) + .each(function(instanceIndex) { + + var + $module = $(this), + + mainCanvas = $('')[0], + imageCanvas = $('')[0], + overlayCanvas = $('')[0], + + backgroundImage = new Image(), + + // defs + mainContext, + imageContext, + overlayContext, + + image, + imageName, + + width, + height, + + // shortucts + colors = settings.colors, + paths = settings.paths, + namespace = settings.namespace, + error = settings.error, + + // boilerplate + instance = $module.data('module-' + namespace), + module + ; + + module = { + + checkPreconditions: function() { + module.debug('Checking pre-conditions'); + + if( !$.isPlainObject(colors) || $.isEmptyObject(colors) ) { + module.error(error.undefinedColors); + return false; + } + return true; + }, + + async: function(callback) { + if(settings.async) { + setTimeout(callback, 0); + } + else { + callback(); + } + }, + + getMetadata: function() { + module.debug('Grabbing metadata'); + image = $module.data('image') || settings.image || undefined; + imageName = $module.data('name') || settings.name || instanceIndex; + width = settings.width || $module.width(); + height = settings.height || $module.height(); + if(width === 0 || height === 0) { + module.error(error.undefinedSize); + } + }, + + initialize: function() { + module.debug('Initializing with colors', colors); + if( module.checkPreconditions() ) { + + module.async(function() { + module.getMetadata(); + module.canvas.create(); + + module.draw.image(function() { + module.draw.colors(); + module.canvas.merge(); + }); + $module + .data('module-' + namespace, module) + ; + }); + } + }, + + redraw: function() { + module.debug('Redrawing image'); + module.async(function() { + module.canvas.clear(); + module.draw.colors(); + module.canvas.merge(); + }); + }, + + change: { + color: function(colorName, color) { + module.debug('Changing color', colorName); + if(colors[colorName] === undefined) { + module.error(error.missingColor); + return false; + } + colors[colorName] = color; + module.redraw(); + } + }, + + canvas: { + create: function() { + module.debug('Creating canvases'); + + mainCanvas.width = width; + mainCanvas.height = height; + imageCanvas.width = width; + imageCanvas.height = height; + overlayCanvas.width = width; + overlayCanvas.height = height; + + mainContext = mainCanvas.getContext('2d'); + imageContext = imageCanvas.getContext('2d'); + overlayContext = overlayCanvas.getContext('2d'); + + $module + .append( mainCanvas ) + ; + mainContext = $module.children('canvas')[0].getContext('2d'); + }, + clear: function(context) { + module.debug('Clearing canvas'); + overlayContext.fillStyle = '#FFFFFF'; + overlayContext.fillRect(0, 0, width, height); + }, + merge: function() { + if( !$.isFunction(mainContext.blendOnto) ) { + module.error(error.missingPlugin); + return; + } + mainContext.putImageData( imageContext.getImageData(0, 0, width, height), 0, 0); + overlayContext.blendOnto(mainContext, 'multiply'); + } + }, + + draw: { + + image: function(callback) { + module.debug('Drawing image'); + callback = callback || function(){}; + if(image) { + backgroundImage.src = image; + backgroundImage.onload = function() { + imageContext.drawImage(backgroundImage, 0, 0); + callback(); + }; + } + else { + module.error(error.noImage); + callback(); + } + }, + + colors: function() { + module.debug('Drawing color overlays', colors); + $.each(colors, function(colorName, color) { + settings.onDraw(overlayContext, imageName, colorName, color); + }); + } + + }, + + debug: function(message, variableName) { + if(settings.debug) { + if(variableName !== undefined) { + console.info(settings.name + ': ' + message, variableName); + } + else { + console.info(settings.name + ': ' + message); + } + } + }, + error: function(errorMessage) { + console.warn(settings.name + ': ' + errorMessage); + }, + invoke: function(methodName, context, methodArguments) { + var + method + ; + methodArguments = methodArguments || Array.prototype.slice.call( arguments, 2 ); + + if(typeof methodName == 'string' && instance !== undefined) { + methodName = methodName.split('.'); + $.each(methodName, function(index, name) { + if( $.isPlainObject( instance[name] ) ) { + instance = instance[name]; + return true; + } + else if( $.isFunction( instance[name] ) ) { + method = instance[name]; + return true; + } + module.error(settings.error.method); + return false; + }); + } + return ( $.isFunction( method ) ) + ? method.apply(context, methodArguments) + : false + ; + } + + }; + if(instance !== undefined && moduleArguments) { + // simpler than invoke realizing to invoke itself (and losing scope due prototype.call() + if(moduleArguments[0] == 'invoke') { + moduleArguments = Array.prototype.slice.call( moduleArguments, 1 ); + } + return module.invoke(moduleArguments[0], this, Array.prototype.slice.call( moduleArguments, 1 ) ); + } + // initializing + module.initialize(); + }) + ; + return this; + }; + + $.fn.colorize.settings = { + name : 'Image Colorizer', + debug : true, + namespace : 'colorize', + + onDraw : function(overlayContext, imageName, colorName, color) {}, + + // whether to block execution while updating canvas + async : true, + // object containing names and default values of color regions + colors : {}, + + metadata: { + image : 'image', + name : 'name' + }, + + error: { + noImage : 'No tracing image specified', + undefinedColors : 'No default colors specified.', + missingColor : 'Attempted to change color that does not exist', + missingPlugin : 'Blend onto plug-in must be included', + undefinedHeight : 'The width or height of image canvas could not be automatically determined. Please specify a height.' + } + + }; + +})( jQuery, window , document ); + +/* + * # Semantic - Form Validation + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.form = function(fields, parameters) { + var + $allModules = $(this), + + settings = $.extend(true, {}, $.fn.form.settings, parameters), + validation = $.extend({}, $.fn.form.settings.defaults, fields), + + namespace = settings.namespace, + metadata = settings.metadata, + selector = settings.selector, + className = settings.className, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + $allModules + .each(function() { + var + $module = $(this), + $field = $(this).find(selector.field), + $group = $(this).find(selector.group), + $message = $(this).find(selector.message), + $prompt = $(this).find(selector.prompt), + $submit = $(this).find(selector.submit), + + formErrors = [], + + element = this, + instance = $module.data(moduleNamespace), + module + ; + + module = { + + initialize: function() { + module.verbose('Initializing form validation', $module, validation, settings); + if(settings.keyboardShortcuts) { + $field + .on('keydown' + eventNamespace, module.event.field.keydown) + ; + } + $module + .on('submit' + eventNamespace, module.validate.form) + ; + $field + .on('blur' + eventNamespace, module.event.field.blur) + ; + $submit + .on('click' + eventNamespace, module.submit) + ; + $field + .on(module.get.changeEvent() + eventNamespace, module.event.field.change) + ; + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module', instance); + $module + .off(eventNamespace) + .removeData(moduleNamespace) + ; + }, + + refresh: function() { + module.verbose('Refreshing selector cache'); + $field = $module.find(selector.field); + }, + + submit: function() { + module.verbose('Submitting form', $module); + $module + .submit() + ; + }, + + event: { + field: { + keydown: function(event) { + var + $field = $(this), + key = event.which, + keyCode = { + enter : 13, + escape : 27 + } + ; + if( key == keyCode.escape) { + module.verbose('Escape key pressed blurring field'); + $field + .blur() + ; + } + if(!event.ctrlKey && key == keyCode.enter && $field.is(selector.input) ) { + module.debug('Enter key pressed, submitting form'); + $submit + .addClass(className.down) + ; + $field + .one('keyup' + eventNamespace, module.event.field.keyup) + ; + event.preventDefault(); + return false; + } + }, + keyup: function() { + module.verbose('Doing keyboard shortcut form submit'); + $submit.removeClass(className.down); + module.submit(); + }, + blur: function() { + var + $field = $(this), + $fieldGroup = $field.closest($group) + ; + if( $fieldGroup.hasClass(className.error) ) { + module.debug('Revalidating field', $field, module.get.validation($field)); + module.validate.field( module.get.validation($field) ); + } + else if(settings.on == 'blur' || settings.on == 'change') { + module.validate.field( module.get.validation($field) ); + } + }, + change: function() { + var + $field = $(this), + $fieldGroup = $field.closest($group) + ; + if( $fieldGroup.hasClass(className.error) ) { + module.debug('Revalidating field', $field, module.get.validation($field)); + module.validate.field( module.get.validation($field) ); + } + else if(settings.on == 'change') { + module.validate.field( module.get.validation($field) ); + } + } + } + + }, + + get: { + changeEvent: function() { + return (document.createElement('input').oninput !== undefined) + ? 'input' + : (document.createElement('input').onpropertychange !== undefined) + ? 'propertychange' + : 'keyup' + ; + }, + field: function(identifier) { + module.verbose('Finding field with identifier', identifier); + if( $field.filter('#' + identifier).size() > 0 ) { + return $field.filter('#' + identifier); + } + else if( $field.filter('[name="' + identifier +'"]').size() > 0 ) { + return $field.filter('[name="' + identifier +'"]'); + } + else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').size() > 0 ) { + return $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]'); + } + return $(''); + }, + validation: function($field) { + var + rules + ; + $.each(validation, function(fieldName, field) { + if( module.get.field(field.identifier).get(0) == $field.get(0) ) { + rules = field; + } + }); + return rules || false; + } + }, + + has: { + + field: function(identifier) { + module.verbose('Checking for existence of a field with identifier', identifier); + if( $field.filter('#' + identifier).size() > 0 ) { + return true; + } + else if( $field.filter('[name="' + identifier +'"]').size() > 0 ) { + return true; + } + else if( $field.filter('[data-' + metadata.validate + '="'+ identifier +'"]').size() > 0 ) { + return true; + } + return false; + } + + }, + + add: { + prompt: function(field, errors) { + var + $field = module.get.field(field.identifier), + $fieldGroup = $field.closest($group), + $prompt = $fieldGroup.find(selector.prompt), + promptExists = ($prompt.size() !== 0) + ; + module.verbose('Adding inline error', field); + $fieldGroup + .addClass(className.error) + ; + if(settings.inline) { + if(!promptExists) { + $prompt = settings.templates.prompt(errors); + $prompt + .appendTo($fieldGroup) + ; + } + $prompt + .html(errors[0]) + ; + if(!promptExists) { + if(settings.transition && $.fn.transition !== undefined) { + module.verbose('Displaying error with css transition', settings.transition); + $prompt.transition(settings.transition + ' in', settings.duration); + } + else { + module.verbose('Displaying error with fallback javascript animation'); + $prompt + .fadeIn(settings.duration) + ; + } + } + } + }, + errors: function(errors) { + module.debug('Adding form error messages', errors); + $message + .html( settings.templates.error(errors) ) + ; + } + }, + + remove: { + prompt: function(field) { + var + $field = module.get.field(field.identifier), + $fieldGroup = $field.closest($group), + $prompt = $fieldGroup.find(selector.prompt) + ; + $fieldGroup + .removeClass(className.error) + ; + if(settings.inline && $prompt.is(':visible')) { + module.verbose('Removing prompt for field', field); + if(settings.transition && $.fn.transition !== undefined) { + $prompt.transition(settings.transition + ' out', settings.duration, function() { + $prompt.remove(); + }); + } + else { + $prompt + .fadeOut(settings.duration, function(){ + $prompt.remove(); + }) + ; + } + } + } + }, + + validate: { + + form: function(event) { + var + allValid = true + ; + // reset errors + formErrors = []; + $.each(validation, function(fieldName, field) { + if( !( module.validate.field(field) ) ) { + allValid = false; + } + }); + if(allValid) { + module.debug('Form has no validation errors, submitting'); + $module + .removeClass(className.error) + .addClass(className.success) + ; + $.proxy(settings.onSuccess, this)(event); + } + else { + module.debug('Form has errors'); + $module.addClass(className.error); + if(!settings.inline) { + module.add.errors(formErrors); + } + return $.proxy(settings.onFailure, this)(formErrors); + } + }, + + // takes a validation object and returns whether field passes validation + field: function(field) { + var + $field = module.get.field(field.identifier), + fieldValid = true, + fieldErrors = [] + ; + if(field.rules !== undefined) { + $.each(field.rules, function(index, rule) { + if( module.has.field(field.identifier) && !( module.validate.rule(field, rule) ) ) { + module.debug('Field is invalid', field.identifier, rule.type); + fieldErrors.push(rule.prompt); + fieldValid = false; + } + }); + } + if(fieldValid) { + module.remove.prompt(field, fieldErrors); + $.proxy(settings.onValid, $field)(); + } + else { + formErrors = formErrors.concat(fieldErrors); + module.add.prompt(field, fieldErrors); + $.proxy(settings.onInvalid, $field)(fieldErrors); + return false; + } + return true; + }, + + // takes validation rule and returns whether field passes rule + rule: function(field, validation) { + var + $field = module.get.field(field.identifier), + type = validation.type, + value = $field.val(), + + bracketRegExp = /\[(.*?)\]/i, + bracket = bracketRegExp.exec(type), + isValid = true, + ancillary, + functionType + ; + // if bracket notation is used, pass in extra parameters + if(bracket !== undefined && bracket !== null) { + ancillary = bracket[1]; + functionType = type.replace(bracket[0], ''); + isValid = $.proxy(settings.rules[functionType], $module)(value, ancillary); + } + // normal notation + else { + isValid = $.proxy(settings.rules[type], $field)(value); + } + return isValid; + } + }, + + setting: function(name, value) { + module.debug('Changing setting', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + module.debug('Changing internal', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.form.settings = { + + name : 'Form', + namespace : 'form', + + debug : true, + verbose : true, + performance : true, + + + keyboardShortcuts : true, + on : 'submit', + inline : false, + + transition : 'scale', + duration : 150, + + + onValid : function() {}, + onInvalid : function() {}, + onSuccess : function() { return true; }, + onFailure : function() { return false; }, + + metadata : { + validate: 'validate' + }, + + selector : { + message : '.error.message', + field : 'input, textarea, select', + group : '.field', + input : 'input', + prompt : '.prompt', + submit : '.submit' + }, + + className : { + error : 'error', + success : 'success', + down : 'down', + label : 'ui label prompt' + }, + + // errors + error: { + method : 'The method you called is not defined.' + }, + + + + templates: { + error: function(errors) { + var + html = '
    ' + ; + $.each(errors, function(index, value) { + html += '
  • ' + value + '
  • '; + }); + html += '
'; + return $(html); + }, + prompt: function(errors) { + return $('
') + .addClass('ui red pointing prompt label') + .html(errors[0]) + ; + } + }, + + rules: { + checked: function() { + return ($(this).filter(':checked').size() > 0); + }, + empty: function(value) { + return !(value === undefined || '' === value); + }, + email: function(value){ + var + emailRegExp = new RegExp("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?") + ; + return emailRegExp.test(value); + }, + length: function(value, requiredLength) { + return (value !== undefined) + ? (value.length >= requiredLength) + : false + ; + }, + not: function(value, notValue) { + return (value != notValue); + }, + contains: function(value, text) { + return (value.search(text) !== -1); + }, + is: function(value, text) { + return (value == text); + }, + maxLength: function(value, maxLength) { + return (value !== undefined) + ? (value.length <= maxLength) + : false + ; + }, + match: function(value, fieldIdentifier) { + // use either id or name of field + var + $form = $(this), + matchingValue + ; + if($form.find('#' + fieldIdentifier).size() > 0) { + matchingValue = $form.find('#' + fieldIdentifier).val(); + } + else if($form.find('[name=' + fieldIdentifier +']').size() > 0) { + matchingValue = $form.find('[name=' + fieldIdentifier + ']').val(); + } + else if( $form.find('[data-validate="'+ fieldIdentifier +'"]').size() > 0 ) { + matchingValue = $form.find('[data-validate="'+ fieldIdentifier +'"]').val(); + } + return (matchingValue !== undefined) + ? ( value.toString() == matchingValue.toString() ) + : false + ; + }, + url: function(value) { + var + urlRegExp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/ + ; + return urlRegExp.test(value); + } + } + +}; + +})( jQuery, window , document ); + +/* + * # Semantic - State + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.state = function(parameters) { + var + $allModules = $(this), + settings = $.extend(true, {}, $.fn.state.settings, parameters), + + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + + // shortcuts + error = settings.error, + metadata = settings.metadata, + className = settings.className, + namespace = settings.namespace, + states = settings.states, + text = settings.text, + + eventNamespace = '.' + namespace, + moduleNamespace = namespace + '-module', + + + invokedResponse + ; + $allModules + .each(function() { + var + $module = $(this), + + element = this, + instance = $module.data(moduleNamespace), + + module + ; + module = { + + initialize: function() { + module.verbose('Initializing module'); + + // allow module to guess desired state based on element + if(settings.automatic) { + module.add.defaults(); + } + + // bind events with delegated events + if(settings.context && moduleSelector !== '') { + if( module.allows('hover') ) { + $(element, settings.context) + .on(moduleSelector, 'mouseenter' + eventNamespace, module.enable.hover) + .on(moduleSelector, 'mouseleave' + eventNamespace, module.disable.hover) + ; + } + if( module.allows('down') ) { + $(element, settings.context) + .on(moduleSelector, 'mousedown' + eventNamespace, module.enable.down) + .on(moduleSelector, 'mouseup' + eventNamespace, module.disable.down) + ; + } + if( module.allows('focus') ) { + $(element, settings.context) + .on(moduleSelector, 'focus' + eventNamespace, module.enable.focus) + .on(moduleSelector, 'blur' + eventNamespace, module.disable.focus) + ; + } + $(settings.context) + .on(moduleSelector, 'mouseenter' + eventNamespace, module.change.text) + .on(moduleSelector, 'mouseleave' + eventNamespace, module.reset.text) + .on(moduleSelector, 'click' + eventNamespace, module.toggle.state) + ; + } + else { + if( module.allows('hover') ) { + $module + .on('mouseenter' + eventNamespace, module.enable.hover) + .on('mouseleave' + eventNamespace, module.disable.hover) + ; + } + if( module.allows('down') ) { + $module + .on('mousedown' + eventNamespace, module.enable.down) + .on('mouseup' + eventNamespace, module.disable.down) + ; + } + if( module.allows('focus') ) { + $module + .on('focus' + eventNamespace, module.enable.focus) + .on('blur' + eventNamespace, module.disable.focus) + ; + } + $module + .on('mouseenter' + eventNamespace, module.change.text) + .on('mouseleave' + eventNamespace, module.reset.text) + .on('click' + eventNamespace, module.toggle.state) + ; + } + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module', instance); + $module + .off(eventNamespace) + .removeData(moduleNamespace) + ; + }, + + refresh: function() { + module.verbose('Refreshing selector cache'); + $module = $(element); + }, + + add: { + defaults: function() { + var + userStates = parameters && $.isPlainObject(parameters.states) + ? parameters.states + : {} + ; + $.each(settings.defaults, function(type, typeStates) { + if( module.is[type] !== undefined && module.is[type]() ) { + module.verbose('Adding default states', type, element); + $.extend(settings.states, typeStates, userStates); + } + }); + } + }, + + is: { + + active: function() { + return $module.hasClass(className.active); + }, + loading: function() { + return $module.hasClass(className.loading); + }, + inactive: function() { + return !( $module.hasClass(className.active) ); + }, + + enabled: function() { + return !( $module.is(settings.filter.active) ); + }, + disabled: function() { + return ( $module.is(settings.filter.active) ); + }, + textEnabled: function() { + return !( $module.is(settings.filter.text) ); + }, + + // definitions for automatic type detection + button: function() { + return $module.is('.button:not(a, .submit)'); + }, + input: function() { + return $module.is('input'); + } + }, + + allow: function(state) { + module.debug('Now allowing state', state); + states[state] = true; + }, + disallow: function(state) { + module.debug('No longer allowing', state); + states[state] = false; + }, + + allows: function(state) { + return states[state] || false; + }, + + enable: { + state: function(state) { + if(module.allows(state)) { + $module.addClass( className[state] ); + } + }, + // convenience + focus: function() { + $module.addClass(className.focus); + }, + hover: function() { + $module.addClass(className.hover); + }, + down: function() { + $module.addClass(className.down); + }, + }, + + disable: { + state: function(state) { + if(module.allows(state)) { + $module.removeClass( className[state] ); + } + }, + // convenience + focus: function() { + $module.removeClass(className.focus); + }, + hover: function() { + $module.removeClass(className.hover); + }, + down: function() { + $module.removeClass(className.down); + }, + }, + + toggle: { + state: function() { + var + apiRequest = $module.data(metadata.promise) + ; + if( module.allows('active') && module.is.enabled() ) { + module.refresh(); + if(apiRequest !== undefined) { + module.listenTo(apiRequest); + } + else { + module.change.state(); + } + } + } + }, + + listenTo: function(apiRequest) { + module.debug('API request detected, waiting for state signal', apiRequest); + if(apiRequest) { + if(text.loading) { + module.update.text(text.loading); + } + $.when(apiRequest) + .then(function() { + if(apiRequest.state() == 'resolved') { + module.debug('API request succeeded'); + settings.activateTest = function(){ return true; }; + settings.deactivateTest = function(){ return true; }; + } + else { + module.debug('API request failed'); + settings.activateTest = function(){ return false; }; + settings.deactivateTest = function(){ return false; }; + } + module.change.state(); + }) + ; + } + // xhr exists but set to false, beforeSend killed the xhr + else { + settings.activateTest = function(){ return false; }; + settings.deactivateTest = function(){ return false; }; + } + }, + + // checks whether active/inactive state can be given + change: { + + state: function() { + module.debug('Determining state change direction'); + // inactive to active change + if( module.is.inactive() ) { + module.activate(); + } + else { + module.deactivate(); + } + if(settings.sync) { + module.sync(); + } + $.proxy(settings.onChange, element)(); + }, + + text: function() { + if( module.is.textEnabled() ) { + if( module.is.active() ) { + if(text.hover) { + module.verbose('Changing text to hover text', text.hover); + module.update.text(text.hover); + } + else if(text.disable) { + module.verbose('Changing text to disable text', text.disable); + module.update.text(text.disable); + } + } + else { + if(text.hover) { + module.verbose('Changing text to hover text', text.disable); + module.update.text(text.hover); + } + else if(text.enable){ + module.verbose('Changing text to enable text', text.enable); + module.update.text(text.enable); + } + } + } + } + + }, + + activate: function() { + if( $.proxy(settings.activateTest, element)() ) { + module.debug('Setting state to active'); + $module + .addClass(className.active) + ; + module.update.text(text.active); + } + $.proxy(settings.onActivate, element)(); + }, + + deactivate: function() { + if($.proxy(settings.deactivateTest, element)() ) { + module.debug('Setting state to inactive'); + $module + .removeClass(className.active) + ; + module.update.text(text.inactive); + } + $.proxy(settings.onDeactivate, element)(); + }, + + sync: function() { + module.verbose('Syncing other buttons to current state'); + if( module.is.active() ) { + $allModules + .not($module) + .state('activate'); + } + else { + $allModules + .not($module) + .state('deactivate') + ; + } + }, + + get: { + text: function() { + return (settings.selector.text) + ? $module.find(settings.selector.text).text() + : $module.html() + ; + }, + textFor: function(state) { + return text[state] || false; + } + }, + + flash: { + text: function(text, duration) { + var + previousText = module.get.text() + ; + module.debug('Flashing text message', text, duration); + text = text || settings.text.flash; + duration = duration || settings.flashDuration; + module.update.text(text); + setTimeout(function(){ + module.update.text(previousText); + }, duration); + } + }, + + reset: { + // on mouseout sets text to previous value + text: function() { + var + activeText = text.active || $module.data(metadata.storedText), + inactiveText = text.inactive || $module.data(metadata.storedText) + ; + if( module.is.textEnabled() ) { + if( module.is.active() && activeText) { + module.verbose('Resetting active text', activeText); + module.update.text(activeText); + } + else if(inactiveText) { + module.verbose('Resetting inactive text', activeText); + module.update.text(inactiveText); + } + } + } + }, + + update: { + text: function(text) { + var + currentText = module.get.text() + ; + if(text && text !== currentText) { + module.debug('Updating text', text); + if(settings.selector.text) { + $module + .data(metadata.storedText, text) + .find(settings.selector.text) + .text(text) + ; + } + else { + $module + .data(metadata.storedText, text) + .html(text) + ; + } + } + else { + module.debug('Text is already sane, ignoring update', text); + } + } + }, + + setting: function(name, value) { + module.debug('Changing setting', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + module.debug('Changing internal', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.state.settings = { + + // module info + name : 'State', + + // debug output + debug : true, + + // verbose debug output + verbose : true, + + // namespace for events + namespace : 'state', + + // debug data includes performance + performance: true, + + // callback occurs on state change + onActivate : function() {}, + onDeactivate : function() {}, + onChange : function() {}, + + // state test functions + activateTest : function() { return true; }, + deactivateTest : function() { return true; }, + + // whether to automatically map default states + automatic : true, + + // activate / deactivate changes all elements instantiated at same time + sync : false, + + // default flash text duration, used for temporarily changing text of an element + flashDuration : 3000, + + // selector filter + filter : { + text : '.loading, .disabled', + active : '.disabled' + }, + + context : false, + + // error + error: { + method : 'The method you called is not defined.' + }, + + // metadata + metadata: { + promise : 'promise', + storedText : 'stored-text' + }, + + // change class on state + className: { + focus : 'focus', + hover : 'hover', + down : 'down', + active : 'active', + loading : 'loading' + }, + + selector: { + // selector for text node + text: false + }, + + defaults : { + input: { + hover : true, + focus : true, + down : true, + loading : false, + active : false + }, + button: { + hover : true, + focus : false, + down : true, + active : true, + loading : true + } + }, + + states : { + hover : true, + focus : true, + down : true, + loading : false, + active : false + }, + + text : { + flash : false, + hover : false, + active : false, + inactive : false, + enable : false, + disable : false + } + +}; + + + +})( jQuery, window , document ); + +/* + * # Semantic - Chatroom + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ($, window, document, undefined) { + +$.fn.chatroom = function(parameters) { + var + settings = $.extend(true, {}, $.fn.chatroom.settings, parameters), + + className = settings.className, + namespace = settings.namespace, + selector = settings.selector, + error = settings.error, + + // hoist arguments + moduleArguments = arguments || false + ; + $(this) + .each(function() { + var + $module = $(this), + + $expandButton = $module.find(selector.expandButton), + $userListButton = $module.find(selector.userListButton), + + $userList = $module.find(selector.userList), + $room = $module.find(selector.room), + $userCount = $module.find(selector.userCount), + + $log = $module.find(selector.log), + $message = $module.find(selector.message), + + $messageInput = $module.find(selector.messageInput), + $messageButton = $module.find(selector.messageButton), + + instance = $module.data('module'), + + html = '', + users = {}, + + channel, + loggedInUser, + + message, + count, + + height, + + pusher, + module + ; + + module = { + + width: { + log : $log.width(), + userList : $userList.outerWidth() + }, + + initialize: function() { + + // check error conditions + if(Pusher === undefined) { + module.error(error.pusher); + } + if(settings.key === undefined || settings.channelName === undefined) { + module.error(error.key); + return false; + } + else if( !(settings.endpoint.message || settings.endpoint.authentication) ) { + module.error(error.endpoint); + return false; + } + + // define pusher + pusher = new Pusher(settings.key); + Pusher.channel_auth_endpoint = settings.endpoint.authentication; + + channel = pusher.subscribe(settings.channelName); + + channel.bind('pusher:subscription_succeeded', module.user.list.create); + channel.bind('pusher:subscription_error', module.error); + channel.bind('pusher:member_added', module.user.joined); + channel.bind('pusher:member_removed', module.user.left); + channel.bind('update_messages', module.message.receive); + + $.each(settings.customEvents, function(label, value) { + channel.bind(label, value); + }); + + // bind module events + $userListButton + .on('click.' + namespace, module.event.toggleUserList) + ; + $expandButton + .on('click.' + namespace, module.event.toggleExpand) + ; + $messageInput + .on('keydown.' + namespace, module.event.input.keydown) + .on('keyup.' + namespace, module.event.input.keyup) + ; + $messageButton + .on('mouseenter.' + namespace, module.event.hover) + .on('mouseleave.' + namespace, module.event.hover) + .on('click.' + namespace, module.event.submit) + ; + // scroll to bottom of chat log + $log + .animate({ + scrollTop: $log.prop('scrollHeight') + }, 400) + ; + $module + .data('module', module) + .addClass(className.loading) + ; + + }, + + // refresh module + refresh: function() { + // reset width calculations + $userListButton + .removeClass(className.active) + ; + module.width = { + log : $log.width(), + userList : $userList.outerWidth() + }; + if( $userListButton.hasClass(className.active) ) { + module.user.list.hide(); + } + $module.data('module', module); + }, + + user: { + + updateCount: function() { + if(settings.userCount) { + users = $module.data('users'); + count = 0; + $.each(users, function() { + count++; + }); + $userCount + .html( settings.templates.userCount(count) ) + ; + } + }, + + // add user to user list + joined: function(member) { + users = $module.data('users'); + if(member.id != 'anonymous' && users[ member.id ] === undefined ) { + users[ member.id ] = member.info; + if(settings.randomColor && member.info.color === undefined) { + member.info.color = settings.templates.color(member.id); + } + html = settings.templates.userList(member.info); + if(member.info.isAdmin) { + $(html) + .prependTo($userList) + ; + } + else { + $(html) + .appendTo($userList) + ; + } + if(settings.partingMessages) { + $log + .append( settings.templates.joined(member.info) ) + ; + module.message.scroll.test(); + } + module.user.updateCount(); + } + }, + + // remove user from user list + left: function(member) { + users = $module.data('users'); + if(member !== undefined && member.id !== 'anonymous') { + delete users[ member.id ]; + $module + .data('users', users) + ; + $userList + .find('[data-id='+ member.id + ']') + .remove() + ; + if(settings.partingMessages) { + $log + .append( settings.templates.left(member.info) ) + ; + module.message.scroll.test(); + } + module.user.updateCount(); + } + }, + + list: { + + // receives list of members and generates user list + create: function(members) { + users = {}; + members.each(function(member) { + if(member.id !== 'anonymous' && member.id !== 'undefined') { + if(settings.randomColor && member.info.color === undefined) { + member.info.color = settings.templates.color(member.id); + } + // sort list with admin first + html = (member.info.isAdmin) + ? settings.templates.userList(member.info) + html + : html + settings.templates.userList(member.info) + ; + users[ member.id ] = member.info; + } + }); + $module + .data('users', users) + .data('user', users[members.me.id] ) + .removeClass(className.loading) + ; + $userList + .html(html) + ; + module.user.updateCount(); + $.proxy(settings.onJoin, $userList.children())(); + }, + + // shows user list + show: function() { + $log + .animate({ + width: (module.width.log - module.width.userList) + }, { + duration : settings.speed, + easing : settings.easing, + complete : module.message.scroll.move + }) + ; + }, + + // hides user list + hide: function() { + $log + .stop() + .animate({ + width: (module.width.log) + }, { + duration : settings.speed, + easing : settings.easing, + complete : module.message.scroll.move + }) + ; + } + + } + + }, + + message: { + + // handles scrolling of chat log + scroll: { + test: function() { + height = $log.prop('scrollHeight') - $log.height(); + if( Math.abs($log.scrollTop() - height) < settings.scrollArea) { + module.message.scroll.move(); + } + }, + + move: function() { + height = $log.prop('scrollHeight') - $log.height(); + $log + .scrollTop(height) + ; + } + }, + + // sends chat message + send: function(message) { + if( !module.utils.emptyString(message) ) { + $.api({ + url : settings.endpoint.message, + method : 'POST', + data : { + 'message': { + content : message, + timestamp : new Date().getTime() + } + } + }); + } + }, + + // receives chat response and processes + receive: function(response) { + message = response.data; + users = $module.data('users'); + loggedInUser = $module.data('user'); + if(users[ message.userID] !== undefined) { + // logged in user's messages already pushed instantly + if(loggedInUser === undefined || loggedInUser.id != message.userID) { + message.user = users[ message.userID ]; + module.message.display(message); + } + } + }, + + // displays message in chat log + display: function(message) { + $log + .append( settings.templates.message(message) ) + ; + module.message.scroll.test(); + $.proxy(settings.onMessage, $log.children().last() )(); + } + + }, + + expand: function() { + $module + .addClass(className.expand) + ; + $.proxy(settings.onExpand, $module )(); + module.refresh(); + }, + + contract: function() { + $module + .removeClass(className.expand) + ; + $.proxy(settings.onContract, $module )(); + module.refresh(); + }, + + event: { + + input: { + + keydown: function(event) { + if(event.which == 13) { + $messageButton + .addClass(className.down) + ; + } + }, + + keyup: function(event) { + if(event.which == 13) { + $messageButton + .removeClass(className.down) + ; + module.event.submit(); + } + } + + }, + + // handles message form submit + submit: function() { + var + message = $messageInput.val(), + loggedInUser = $module.data('user') + ; + if(loggedInUser !== undefined && !module.utils.emptyString(message)) { + module.message.send(message); + // display immediately + module.message.display({ + user: loggedInUser, + text: message + }); + module.message.scroll.move(); + $messageInput + .val('') + ; + + } + }, + + // handles button click on expand button + toggleExpand: function() { + if( !$module.hasClass(className.expand) ) { + $expandButton + .addClass(className.active) + ; + module.expand(); + } + else { + $expandButton + .removeClass(className.active) + ; + module.contract(); + } + }, + + // handles button click on user list button + toggleUserList: function() { + if( !$log.is(':animated') ) { + if( !$userListButton.hasClass(className.active) ) { + $userListButton + .addClass(className.active) + ; + module.user.list.show(); + } + else { + $userListButton + .removeClass('active') + ; + module.user.list.hide(); + } + } + + } + }, + + utils: { + + emptyString: function(string) { + if(typeof string == 'string') { + return (string.search(/\S/) == -1); + } + return false; + } + + }, + + + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + title += ' ' + '(' + $allDropdowns.size() + ')'; + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + } + else { + module.error(error.method); + } + }); + } + if ( $.isFunction( found ) ) { + return found.apply(context, passedArguments); + } + return found || false; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + invokedResponse = module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) +; + + return (invokedResponse) + ? invokedResponse + : this + ; +}; + + $.fn.chatroom.settings = { + + name : 'Chat', + debug : false, + namespace : 'chat', + + channel : 'present-chat', + + onJoin : function(){}, + onMessage : function(){}, + onExpand : function(){}, + onContract : function(){}, + + customEvents : {}, + + partingMessages : false, + userCount : true, + randomColor : true, + + speed : 300, + easing : 'easeOutQuint', + + // pixels from bottom of chat log that should trigger auto scroll to bottom + scrollArea : 9999, + + endpoint : { + message : false, + authentication : false + }, + + error: { + method : 'The method you called is not defined', + endpoint : 'Please define a message and authentication endpoint.', + key : 'You must specify a pusher key and channel.', + pusher : 'You must include the Pusher library.' + }, + + className : { + expand : 'expand', + active : 'active', + hover : 'hover', + down : 'down', + loading : 'loading' + }, + + selector : { + userCount : '.actions .message', + userListButton : '.actions .list.button', + expandButton : '.actions .expand.button', + room : '.room', + userList : '.room .list', + log : '.room .log', + message : '.room .log .message', + author : '.room log .message .author', + messageInput : '.talk input', + messageButton : '.talk .send.button' + }, + + templates: { + + userCount: function(number) { + return number + ' users in chat'; + }, + + color: function(userID) { + var + colors = [ + '#000000', + '#333333', + '#666666', + '#999999', + '#CC9999', + '#CC6666', + '#CC3333', + '#993333', + '#663333', + '#CC6633', + '#CC9966', + '#CC9933', + '#999966', + '#CCCC66', + '#99CC66', + '#669933', + '#669966', + '#33A3CC', + '#336633', + '#33CCCC', + '#339999', + '#336666', + '#336699', + '#6666CC', + '#9966CC', + '#333399', + '#663366', + '#996699', + '#993366', + '#CC6699' + ] + ; + return colors[ Math.floor( Math.random() * colors.length) ]; + }, + + message: function(message) { + var + html = '' + ; + if(message.user.isAdmin) { + message.user.color = '#55356A'; + html += '
'; + html += ''; + } + /* + else if(message.user.isPro) { + html += '
'; + html += ''; + } + */ + else { + html += '
'; + } + html += '

'; + if(message.user.color !== undefined) { + html += '' + message.user.name + ': '; + } + else { + html += '' + message.user.name + ': '; + } + html += '' + + message.text + + '

' + + '
' + ; + return html; + }, + + joined: function(member) { + return (typeof member.name !== undefined) + ? '
' + member.name + ' has joined the chat.
' + : false + ; + }, + left: function(member) { + return (typeof member.name !== undefined) + ? '
' + member.name + ' has left the chat.
' + : false + ; + }, + + userList: function(member) { + var + html = '' + ; + if(member.isAdmin) { + member.color = '#55356A'; + } + html += '' + + '
' + + '
' + + ' ' + + '
' + ; + if(member.color !== undefined) { + html += '

' + member.name + '

'; + } + else { + html += '

' + member.name + '

'; + } + html += '
'; + return html; + } + + } + + }; + +})( jQuery, window , document ); + +/* + * # Semantic - Checkbox + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.checkbox = function(parameters) { + var + $allModules = $(this), + + settings = $.extend(true, {}, $.fn.checkbox.settings, parameters), + + className = settings.className, + namespace = settings.namespace, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + + $allModules + .each(function() { + var + $module = $(this), + $label = $(this).next(settings.selector.label).first(), + $input = $(this).find(settings.selector.input), + + selector = $module.selector || '', + instance = $module.data(moduleNamespace), + + element = this, + module + ; + + module = { + + initialize: function() { + module.verbose('Initializing checkbox', settings); + if(settings.context && selector !== '') { + module.verbose('Adding delegated events'); + $(element, settings.context) + .on(selector, 'click' + eventNamespace, module.toggle) + .on(selector + ' + ' + settings.selector.label, 'click' + eventNamespace, module.toggle) + ; + } + else { + $module + .on('click' + eventNamespace, module.toggle) + .data(moduleNamespace, module) + ; + $label + .on('click' + eventNamespace, module.toggle) + ; + } + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module'); + $module + .off(eventNamespace) + .removeData(moduleNamespace) + ; + }, + + is: { + radio: function() { + return $module.hasClass(className.radio); + } + }, + + can: { + disable: function() { + return (typeof settings.required === 'boolean') + ? settings.required + : !module.is.radio() + ; + } + }, + + enable: function() { + module.debug('Enabling checkbox'); + $input + .prop('checked', true) + ; + $.proxy(settings.onChange, $input.get())(); + $.proxy(settings.onEnable, $input.get())(); + }, + + disable: function() { + module.debug('Disabling checkbox'); + $input + .prop('checked', false) + ; + $.proxy(settings.onChange, $input.get())(); + $.proxy(settings.onDisable, $input.get())(); + }, + + toggle: function(event) { + module.verbose('Determining new checkbox state'); + if($input.prop('checked') === undefined || !$input.prop('checked')) { + module.enable(); + } + else if( module.can.disable() ) { + module.disable(); + } + }, + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.checkbox.settings = { + + name : 'Checkbox', + namespace : 'checkbox', + + verbose : true, + debug : true, + performance : true, + + // delegated event context + context : false, + required : 'auto', + + onChange : function(){}, + onEnable : function(){}, + onDisable : function(){}, + + error : { + method : 'The method you called is not defined.' + }, + + selector : { + input : 'input', + label : 'label' + }, + + className : { + radio : 'radio' + } + +}; + +})( jQuery, window , document ); + +/* + * # Semantic - Dimmer + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.dimmer = function(parameters) { + var + $allModules = $(this), + + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.dimmer.settings, parameters) + : $.fn.dimmer.settings, + + selector = settings.selector, + namespace = settings.namespace, + className = settings.className, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + clickEvent = ('ontouchstart' in document.documentElement) + ? 'touchstart' + : 'click', + + invokedResponse + ; + + $allModules + .each(function() { + var + $module = $(this), + $dimmer = $module.children(selector.dimmer).first(), + + element = this, + instance = $dimmer.data(moduleNamespace), + module + ; + + module = { + + initialize: function() { + if( module.is.dimmer() ) { + $dimmer = $module; + $module = $dimmer.parent(); + module.debug('Module initialized as dimmer', settings); + } + else { + if( module.has.dimmer() ) { + $dimmer = $module.children(selector.dimmer).first(); + module.debug('Module initialized with found dimmer', settings); + } + else { + module.create(); + module.debug('Module initialized with created dimmer', settings); + } + if(settings.on == 'hover') { + $module + .on('mouseenter' + eventNamespace, module.show) + .on('mouseleave' + eventNamespace, module.hide) + ; + } + else if(settings.on == 'click') { + $module + .on(clickEvent + eventNamespace, module.toggle) + ; + } + } + if(settings.closable) { + $dimmer + .on(clickEvent, module.event.click) + ; + } + module.set.dimmable(); + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module'); + instance = module; + $dimmer + .data(moduleNamespace, instance) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module'); + $module + .off(eventNamespace) + ; + }, + + event: { + + click: function(event) { + module.verbose('Determining if event occured on dimmer', event); + if( $dimmer.find(event.target).size() === 0 || $(event.target).is(selector.content) ) { + module.hide(); + event.stopImmediatePropagation(); + } + } + + }, + + create: function() { + $dimmer = settings.template.dimmer(); + $dimmer + .appendTo($module) + ; + if(module.is.page()) { + module.set.pageDimmer(); + } + }, + + animate: { + show: function(callback) { + callback = callback || function(){}; + module.set.dimmed(); + if($.fn.transition !== undefined) { + $dimmer + .transition(settings.transition + ' in', settings.duration, function() { + module.set.active(); + callback(); + }) + ; + } + else { + module.verbose('Showing dimmer animation with javascript'); + $dimmer + .stop() + .css({ + opacity : 0, + width : '100%', + height : '100%' + }) + .fadeTo(settings.duration, 1, function() { + $dimmer.removeAttr('style'); + module.set.active(); + callback(); + }) + ; + } + }, + hide: function(callback) { + callback = callback || function(){}; + module.remove.dimmed(); + if($.fn.transition !== undefined) { + module.verbose('Hiding dimmer with css'); + $dimmer + .transition(settings.transition + ' out', settings.duration, function() { + module.remove.active(); + callback(); + }) + ; + } + else { + module.verbose('Hiding dimmer with javascript'); + $dimmer + .stop() + .fadeOut(settings.duration, function() { + $dimmer.removeAttr('style'); + module.remove.active(); + callback(); + }) + ; + } + } + }, + + has: { + dimmer: function() { + return ( $module.children(selector.dimmer).size() > 0 ); + } + }, + + is: { + active: function() { + return $dimmer.hasClass(className.active); + }, + animating: function() { + return ( $dimmer.is(':animated') || $dimmer.hasClass(className.transition) ); + }, + dimmer: function() { + return $module.is(selector.dimmer); + }, + page: function () { + return $module.is('body'); + }, + dimmable: function() { + return $module.is(selector.dimmable); + }, + enabled: function() { + return !$module.hasClass(className.disabled); + }, + disabled: function() { + return $module.hasClass(className.disabled); + }, + pageDimmer: function() { + return $dimmer.hasClass(className.pageDimmer); + } + }, + + can: { + show: function() { + return !$dimmer.hasClass(className.disabled); + } + }, + + set: { + active: function() { + $dimmer + .removeClass(className.transition) + .addClass(className.active) + ; + }, + dimmable: function() { + $module + .addClass(className.dimmable) + ; + }, + dimmed: function() { + $module.addClass(className.dimmed); + }, + pageDimmer: function() { + $dimmer.addClass(className.pageDimmer); + }, + disabled: function() { + $dimmer.addClass(className.disabled); + } + }, + + remove: { + active: function() { + $dimmer + .removeClass(className.transition) + .removeClass(className.active) + ; + }, + dimmed: function() { + $module.removeClass(className.dimmed); + }, + disabled: function() { + $dimmer.removeClass(className.disabled); + } + }, + + show: function(callback) { + module.debug('Showing dimmer', $dimmer); + if( !(module.is.active() || module.is.animating() ) && module.is.enabled() ) { + module.animate.show(callback); + $.proxy(settings.onShow, element)(); + $.proxy(settings.onChange, element)(); + } + else { + module.debug('Dimmer is already shown or disabled'); + } + }, + + hide: function(callback) { + if( module.is.active() && !module.is.animating() ) { + module.debug('Hiding dimmer', $dimmer); + module.animate.hide(callback); + $.proxy(settings.onHide, element)(); + $.proxy(settings.onChange, element)(); + } + else { + module.debug('Dimmer is not visible'); + } + }, + + toggle: function() { + module.verbose('Toggling dimmer visibility', $dimmer); + if( !module.is.active() ) { + module.show(); + } + else { + module.hide(); + } + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.dimmer.settings = { + + name : 'Dimmer', + namespace : 'dimmer', + + verbose : true, + debug : true, + performance : true, + + transition : 'fade', + + on : false, + closable : true, + duration : 500, + + onChange : function(){}, + onShow : function(){}, + onHide : function(){}, + + error : { + method : 'The method you called is not defined.' + }, + + selector: { + dimmable : '.ui.dimmable', + dimmer : '.ui.dimmer', + content : '.ui.dimmer > .content, .ui.dimmer > .content > .center' + }, + + template: { + dimmer: function() { + return $('
').attr('class', 'ui dimmer'); + } + }, + + className : { + active : 'active', + dimmable : 'ui dimmable', + dimmed : 'dimmed', + disabled : 'disabled', + pageDimmer : 'page', + hide : 'hide', + show : 'show', + transition : 'transition' + } + +}; + +})( jQuery, window , document ); +/* + * # Semantic - Dropdown + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.dropdown = function(parameters) { + var + $allDropdowns = $(this), + $document = $(document), + + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.dropdown.settings, parameters) + : $.fn.dropdown.settings, + + className = settings.className, + metadata = settings.metadata, + namespace = settings.namespace, + selector = settings.selector, + error = settings.error, + + eventNamespace = '.' + namespace, + dropdownNamespace = 'module-' + namespace, + dropdownSelector = $allDropdowns.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + + $allDropdowns + .each(function() { + var + $dropdown = $(this), + $item = $dropdown.find(selector.item), + $text = $dropdown.find(selector.text), + $input = $dropdown.find(selector.input), + + $menu = $dropdown.children(selector.menu), + + isTouchDevice = ('ontouchstart' in document.documentElement), + + element = this, + instance = $dropdown.data(dropdownNamespace), + dropdown + ; + + dropdown = { + + initialize: function() { + dropdown.debug('Initializing dropdown', settings); + if(isTouchDevice) { + $dropdown + .on('touchstart' + eventNamespace, dropdown.event.test.toggle) + ; + } + else if(settings.on == 'click') { + $dropdown + .on('click' + eventNamespace, dropdown.event.test.toggle) + ; + } + else if(settings.on == 'hover') { + $dropdown + .on('mouseenter' + eventNamespace, dropdown.delay.show) + .on('mouseleave' + eventNamespace, dropdown.delay.hide) + ; + } + else { + $dropdown + .on(settings.on + eventNamespace, dropdown.toggle) + ; + } + if(settings.action == 'form') { + dropdown.set.selected(); + } + $item + .on('mouseenter' + eventNamespace, dropdown.event.item.mouseenter) + .on('mouseleave' + eventNamespace, dropdown.event.item.mouseleave) + .on(dropdown.get.selectEvent() + eventNamespace, dropdown.event.item.click) + ; + dropdown.instantiate(); + }, + + instantiate: function() { + dropdown.verbose('Storing instance of dropdown', dropdown); + $dropdown + .data(dropdownNamespace, dropdown) + ; + }, + + destroy: function() { + dropdown.verbose('Destroying previous dropdown for', $dropdown); + $item + .off(eventNamespace) + ; + $dropdown + .off(eventNamespace) + .removeData(dropdownNamespace) + ; + }, + + event: { + + stopPropagation: function(event) { + event.stopPropagation(); + }, + + test: { + toggle: function(event) { + dropdown.determine.intent(event, dropdown.toggle); + event.stopImmediatePropagation(); + }, + hide: function(event) { + dropdown.determine.intent(event, dropdown.hide); + event.stopPropagation(); + } + }, + + item: { + + mouseenter: function(event) { + var + $currentMenu = $(this).find(selector.menu), + $otherMenus = $(this).siblings(selector.item).children(selector.menu) + ; + if( $currentMenu.size() > 0 ) { + clearTimeout(dropdown.itemTimer); + dropdown.itemTimer = setTimeout(function() { + dropdown.animate.hide(false, $otherMenus); + dropdown.verbose('Showing sub-menu', $currentMenu); + dropdown.animate.show(false, $currentMenu); + }, settings.delay.show * 2); + } + }, + + mouseleave: function(event) { + var + $currentMenu = $(this).find(selector.menu) + ; + if($currentMenu.size() > 0) { + clearTimeout(dropdown.itemTimer); + dropdown.itemTimer = setTimeout(function() { + dropdown.verbose('Hiding sub-menu', $currentMenu); + dropdown.animate.hide(false, $currentMenu); + }, settings.delay.hide); + } + }, + + click: function (event) { + var + $choice = $(this), + text = $choice.data(metadata.text) || $choice.text(), + value = $choice.data(metadata.value) || text + ; + if( $choice.find(selector.menu).size() === 0 ) { + dropdown.verbose('Adding active state to selected item'); + $item + .removeClass(className.active) + ; + $choice + .addClass(className.active) + ; + dropdown.determine.selectAction(text, value); + $.proxy(settings.onChange, element)(value, text); + event.stopPropagation(); + } + } + + }, + + resetStyle: function() { + $(this).removeAttr('style'); + } + + }, + + determine: { + selectAction: function(text, value) { + dropdown.verbose('Determining action', settings.action); + if( $.isFunction( dropdown[settings.action] ) ) { + dropdown.verbose('Triggering preset action', settings.action); + dropdown[ settings.action ](text, value); + } + else if( $.isFunction(settings.action) ) { + dropdown.verbose('Triggering user action', settings.action); + settings.action(text, value); + } + else { + dropdown.error(error.action); + } + }, + intent: function(event, callback) { + dropdown.debug('Determining whether event occurred in dropdown', event.target); + callback = callback || function(){}; + if( $(event.target).closest($menu).size() === 0 ) { + dropdown.verbose('Triggering event', callback); + callback(); + } + else { + dropdown.verbose('Event occurred in dropdown, canceling callback'); + } + } + }, + + bind: { + intent: function() { + dropdown.verbose('Binding hide intent event to document'); + $document + .on(dropdown.get.selectEvent(), dropdown.event.test.hide) + ; + } + }, + + unbind: { + intent: function() { + dropdown.verbose('Removing hide intent event from document'); + $document + .off(dropdown.get.selectEvent()) + ; + } + }, + + nothing: function() {}, + + changeText: function(text, value) { + dropdown.set.text(text); + dropdown.hide(); + }, + + updateForm: function(text, value) { + dropdown.set.text(text); + dropdown.set.value(value); + dropdown.hide(); + }, + + get: { + selectEvent: function() { + return (isTouchDevice) + ? 'touchstart' + : 'click' + ; + }, + text: function() { + return $text.text(); + }, + value: function() { + return $input.val(); + }, + item: function(value) { + var + $selectedItem + ; + value = value || $input.val(); + $item + .each(function() { + if( $(this).data(metadata.value) == value ) { + $selectedItem = $(this); + } + }) + ; + return $selectedItem || false; + } + }, + + set: { + text: function(text) { + dropdown.debug('Changing text', text, $text); + $text.removeClass(className.placeholder); + $text.text(text); + }, + value: function(value) { + dropdown.debug('Adding selected value to hidden input', value, $input); + $input.val(value); + }, + active: function() { + $dropdown.addClass(className.active); + }, + visible: function() { + $dropdown.addClass(className.visible); + }, + selected: function(value) { + var + $selectedItem = dropdown.get.item(value), + selectedText + ; + if($selectedItem) { + dropdown.debug('Setting selected menu item to', $selectedItem); + selectedText = $selectedItem.data(metadata.text) || $selectedItem.text(); + $item + .removeClass(className.active) + ; + $selectedItem + .addClass(className.active) + ; + dropdown.set.text(selectedText); + } + } + }, + + remove: { + active: function() { + $dropdown.removeClass(className.active); + }, + visible: function() { + $dropdown.removeClass(className.visible); + } + }, + + is: { + visible: function($subMenu) { + return ($subMenu) + ? $subMenu.is(':animated, :visible') + : $menu.is(':animated, :visible') + ; + }, + hidden: function($subMenu) { + return ($subMenu) + ? $subMenu.is(':not(:animated, :visible)') + : $menu.is(':not(:animated, :visible)') + ; + } + }, + + can: { + click: function() { + return (isTouchDevice || settings.on == 'click'); + }, + show: function() { + return !$dropdown.hasClass(className.disabled); + } + }, + + animate: { + show: function(callback, $subMenu) { + var + $currentMenu = $subMenu || $menu + ; + callback = callback || function(){}; + if( dropdown.is.hidden($currentMenu) ) { + dropdown.verbose('Doing menu show animation', $currentMenu); + if(settings.transition == 'none') { + callback(); + } + else if($.fn.transition !== undefined) { + $currentMenu.transition({ + animation : settings.transition + ' in', + duration : settings.duration, + complete : callback, + queue : false + }) + } + else if(settings.transition == 'slide down') { + $currentMenu + .hide() + .clearQueue() + .children() + .clearQueue() + .css('opacity', 0) + .delay(50) + .animate({ + opacity : 1 + }, settings.duration, 'easeOutQuad', dropdown.event.resetStyle) + .end() + .slideDown(100, 'easeOutQuad', function() { + $.proxy(dropdown.event.resetStyle, this)(); + callback(); + }) + ; + } + else if(settings.transition == 'fade') { + $currentMenu + .hide() + .clearQueue() + .fadeIn(settings.duration, function() { + $.proxy(dropdown.event.resetStyle, this)(); + callback(); + }) + ; + } + else { + dropdown.error(error.transition); + } + } + }, + hide: function(callback, $subMenu) { + var + $currentMenu = $subMenu || $menu + ; + callback = callback || function(){}; + if(dropdown.is.visible($currentMenu) ) { + dropdown.verbose('Doing menu hide animation', $currentMenu); + if($.fn.transition !== undefined) { + $currentMenu.transition({ + animation : settings.transition + ' out', + duration : settings.duration, + complete : callback, + queue : false + }) + } + else if(settings.transition == 'none') { + callback(); + } + else if(settings.transition == 'slide down') { + $currentMenu + .show() + .clearQueue() + .children() + .clearQueue() + .css('opacity', 1) + .animate({ + opacity : 0 + }, 100, 'easeOutQuad', dropdown.event.resetStyle) + .end() + .delay(50) + .slideUp(100, 'easeOutQuad', function() { + $.proxy(dropdown.event.resetStyle, this)(); + callback(); + }) + ; + } + else if(settings.transition == 'fade') { + $currentMenu + .show() + .clearQueue() + .fadeOut(150, function() { + $.proxy(dropdown.event.resetStyle, this)(); + callback(); + }) + ; + } + else { + dropdown.error(error.transition); + } + } + } + }, + + show: function() { + dropdown.debug('Checking if dropdown can show'); + if( dropdown.is.hidden() ) { + dropdown.hideOthers(); + dropdown.set.active(); + dropdown.animate.show(dropdown.set.visible); + if( dropdown.can.click() ) { + dropdown.bind.intent(); + } + $.proxy(settings.onShow, element)(); + } + }, + + hide: function() { + if( dropdown.is.visible() ) { + dropdown.debug('Hiding dropdown'); + if( dropdown.can.click() ) { + dropdown.unbind.intent(); + } + dropdown.remove.active(); + dropdown.animate.hide(dropdown.remove.visible); + $.proxy(settings.onHide, element)(); + } + }, + + delay: { + show: function() { + dropdown.verbose('Delaying show event to ensure user intent'); + clearTimeout(dropdown.timer); + dropdown.timer = setTimeout(dropdown.show, settings.delay.show); + }, + hide: function() { + dropdown.verbose('Delaying hide event to ensure user intent'); + clearTimeout(dropdown.timer); + dropdown.timer = setTimeout(dropdown.hide, settings.delay.hide); + } + }, + + hideOthers: function() { + dropdown.verbose('Finding other dropdowns to hide'); + $allDropdowns + .not($dropdown) + .has(selector.menu + ':visible') + .dropdown('hide') + ; + }, + + toggle: function() { + dropdown.verbose('Toggling menu visibility'); + if( dropdown.is.hidden() ) { + dropdown.show(); + } + else { + dropdown.hide(); + } + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, dropdown, name); + } + else { + dropdown[name] = value; + } + } + else { + return dropdown[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + dropdown.performance.log(arguments); + } + else { + dropdown.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + dropdown.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + dropdown.performance.log(arguments); + } + else { + dropdown.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + dropdown.verbose.apply(console, arguments); + } + } + }, + error: function() { + dropdown.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + dropdown.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(dropdown.performance.timer); + dropdown.performance.timer = setTimeout(dropdown.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(dropdown.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(dropdownSelector) { + title += ' \'' + dropdownSelector + '\''; + } + title += ' ' + '(' + $allDropdowns.size() + ')'; + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + } + else { + dropdown.error(error.method); + } + }); + } + if ( $.isFunction( found ) ) { + return found.apply(context, passedArguments); + } + return found || false; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + dropdown.initialize(); + } + invokedResponse = dropdown.invoke(query); + } + else { + if(instance !== undefined) { + dropdown.destroy(); + } + dropdown.initialize(); + } + }) + ; + + return (invokedResponse) + ? invokedResponse + : this + ; +}; + +$.fn.dropdown.settings = { + + name : 'Dropdown', + namespace : 'dropdown', + + verbose : true, + debug : true, + performance : true, + + on : 'click', + action : 'hide', + + delay: { + show: 200, + hide: 300 + }, + + transition : 'slide down', + duration : 250, + + onChange : function(){}, + onShow : function(){}, + onHide : function(){}, + + error : { + action : 'You called a dropdown action that was not defined', + method : 'The method you called is not defined.', + transition : 'The requested transition was not found' + }, + + metadata: { + text : 'text', + value : 'value' + }, + + selector : { + menu : '.menu', + item : '.menu > .item', + text : '> .text', + input : '> input[type="hidden"]' + }, + + className : { + active : 'active', + placeholder : 'default', + disabled : 'disabled', + visible : 'visible' + } + +}; + +})( jQuery, window , document ); +/* + * # Semantic - Modal + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.modal = function(parameters) { + var + $allModals = $(this), + $document = $(document), + + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.modal.settings, parameters) + : $.fn.modal.settings, + + selector = settings.selector, + className = settings.className, + namespace = settings.namespace, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + moduleSelector = $allModals.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + + invokedResponse + ; + + $allModals + .each(function() { + var + $modal = $(this), + $context = $(settings.context), + $otherModals = $allModals.not($modal), + $closeButton = $modal.find(selector.closeButton), + + $dimmer, + + element = this, + instance = $modal.data(moduleNamespace), + modal + ; + + modal = { + + initialize: function() { + modal.verbose('Attaching events'); + $closeButton + .on('click', modal.event.close) + ; + modal.cache.sizes(); + + modal.verbose('Creating dimmer'); + $context + .dimmer({ + closable: settings.closable, + duration: settings.duration, + onShow: function() { + modal.add.keyboardShortcuts(); + $.proxy(settings.onShow, this)(); + }, + onHide: function() { + if($modal.is(':visible')) { + $context.off('.dimmer'); + modal.hide(); + $.proxy(settings.onHide, this)(); + } + modal.remove.keyboardShortcuts(); + } + }) + ; + $dimmer = $context.children(selector.dimmer); + if( $modal.parent()[0] !== $dimmer[0] ) { + modal.debug('Moving element inside dimmer', $context); + $modal = $modal + .detach() + .appendTo($dimmer) + ; + } + modal.instantiate(); + }, + + instantiate: function() { + modal.verbose('Storing instance of modal'); + instance = modal; + $modal + .data(moduleNamespace, instance) + ; + }, + + destroy: function() { + modal.verbose('Destroying previous modal'); + $modal + .off(eventNamespace) + ; + }, + + event: { + close: function() { + modal.verbose('Close button pressed'); + $context.dimmer('hide'); + }, + keyboard: function(event) { + var + keyCode = event.which, + escapeKey = 27 + ; + if(keyCode == escapeKey) { + modal.debug('Escape key pressed hiding modal'); + $context.dimmer('hide'); + event.preventDefault(); + } + }, + resize: function() { + modal.cache.sizes(); + if( $modal.is(':visible') ) { + modal.set.type(); + modal.set.position(); + } + } + }, + + toggle: function() { + if( modal.is.active() ) { + modal.hide(); + } + else { + modal.show(); + } + }, + + show: function() { + modal.debug('Showing modal'); + modal.set.type(); + modal.set.position(); + modal.hideAll(); + if(settings.transition && $.fn.transition !== undefined) { + $modal + .transition(settings.transition + ' in', settings.duration, modal.set.active) + ; + } + else { + $modal + .fadeIn(settings.duration, settings.easing, modal.set.active) + ; + } + modal.debug('Triggering dimmer'); + $context.dimmer('show'); + }, + + hide: function() { + modal.debug('Hiding modal'); + // remove keyboard detection + $document + .off('keyup.' + namespace) + ; + if(settings.transition && $.fn.transition !== undefined) { + $modal + .transition(settings.transition + ' out', settings.duration, modal.remove.active) + ; + } + else { + $modal + .fadeOut(settings.duration, settings.easing, modal.remove.active) + ; + } + }, + + hideAll: function() { + $otherModals + .filter(':visible') + .modal('hide') + ; + }, + + add: { + keyboardShortcuts: function() { + modal.verbose('Adding keyboard shortcuts'); + $document + .on('keyup' + eventNamespace, modal.event.keyboard) + ; + } + }, + + remove: { + active: function() { + $modal.removeClass(className.active); + }, + keyboardShortcuts: function() { + modal.verbose('Removing keyboard shortcuts'); + $document + .off('keyup' + eventNamespace) + ; + } + }, + + cache: { + sizes: function() { + modal.cache = { + height : $modal.outerHeight() + settings.offset, + contextHeight : (settings.context == 'body') + ? $(window).height() + : $context.height() + }; + console.log($modal); + modal.debug('Caching modal and container sizes', modal.cache); + } + }, + + can: { + fit: function() { + return (modal.cache.height < modal.cache.contextHeight); + } + }, + + is: { + active: function() { + return $modal.hasClass(className.active); + } + }, + + set: { + active: function() { + $modal.addClass('active'); + }, + type: function() { + if(modal.can.fit()) { + modal.verbose('Modal fits on screen'); + $modal.removeClass(className.scrolling); + } + else { + modal.verbose('Modal cannot fit on screen setting to scrolling'); + $modal.addClass(className.scrolling); + } + }, + position: function() { + modal.verbose('Centering modal on page', modal.cache.height / 2); + if(modal.can.fit()) { + $modal + .css({ + marginTop: -(modal.cache.height / 2) + }) + ; + } + else { + $modal + .css({ + top: $context.prop('scrollTop') + }) + ; + } + } + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, modal, name); + } + else { + modal[name] = value; + } + } + else { + return modal[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + modal.performance.log(arguments); + } + else { + modal.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + modal.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + modal.performance.log(arguments); + } + else { + modal.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + modal.verbose.apply(console, arguments); + } + } + }, + error: function() { + modal.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + modal.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(modal.performance.timer); + modal.performance.timer = setTimeout(modal.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(modal.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + modal.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + modal.initialize(); + } + invokedResponse = modal.invoke(query); + } + else { + if(instance !== undefined) { + modal.destroy(); + } + modal.initialize(); + } + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.modal.settings = { + + name : 'Modal', + namespace : 'modal', + verbose : true, + debug : true, + performance : true, + + offset : 0, + transition : 'scale', + duration : 500, + easing : 'easeOutExpo', + + closable : true, + context : 'body', + + onShow : function(){}, + onHide : function(){}, + + selector : { + closeButton : '.close, .actions .button', + dimmer: '.ui.dimmer' + }, + error : { + method : 'The method you called is not defined.' + }, + className : { + scrolling : 'scrolling' + }, +}; + + +})( jQuery, window , document ); +/* + * # Semantic - Nag + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ($, window, document, undefined) { + +$.fn.nag = function(parameters) { + var + $allModules = $(this), + settings = $.extend(true, {}, $.fn.nag.settings, parameters), + + className = settings.className, + selector = settings.selector, + error = settings.error, + namespace = settings.namespace, + + eventNamespace = '.' + namespace, + moduleNamespace = namespace + '-module', + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + $(this) + .each(function() { + var + $module = $(this), + + $close = $module.find(selector.close), + $context = $(settings.context), + + + element = this, + instance = $module.data(moduleNamespace), + + moduleOffset, + moduleHeight, + + contextWidth, + contextHeight, + contextOffset, + + yOffset, + yPosition, + + timer, + module, + + requestAnimationFrame = window.requestAnimationFrame + || window.mozRequestAnimationFrame + || window.webkitRequestAnimationFrame + || window.msRequestAnimationFrame + || function(callback) { setTimeout(callback, 0); } + ; + module = { + + initialize: function() { + module.verbose('Initializing element'); + // calculate module offset once + moduleOffset = $module.offset(); + moduleHeight = $module.outerHeight(); + contextWidth = $context.outerWidth(); + contextHeight = $context.outerHeight(); + contextOffset = $context.offset(); + + $module + .data(moduleNamespace, module) + ; + $close + .on('click' + eventNamespace, module.dismiss) + ; + // lets avoid javascript if we dont need to reposition + if(settings.context == window && settings.position == 'fixed') { + $module + .addClass(className.fixed) + ; + } + if(settings.sticky) { + module.verbose('Adding scroll events'); + // retrigger on scroll for absolute + if(settings.position == 'absolute') { + $context + .on('scroll' + eventNamespace, module.event.scroll) + .on('resize' + eventNamespace, module.event.scroll) + ; + } + // fixed is always relative to window + else { + $(window) + .on('scroll' + eventNamespace, module.event.scroll) + .on('resize' + eventNamespace, module.event.scroll) + ; + } + // fire once to position on init + $.proxy(module.event.scroll, this)(); + } + + if(settings.displayTime > 0) { + setTimeout(module.hide, settings.displayTime); + } + if(module.should.show()) { + if( !$module.is(':visible') ) { + module.show(); + } + } + else { + module.hide(); + } + }, + + destroy: function() { + module.verbose('Destroying instance'); + $module + .removeData(moduleNamespace) + .off(eventNamespace) + ; + if(settings.sticky) { + $context + .off(eventNamespace) + ; + } + }, + + refresh: function() { + module.debug('Refreshing cached calculations'); + moduleOffset = $module.offset(); + moduleHeight = $module.outerHeight(); + contextWidth = $context.outerWidth(); + contextHeight = $context.outerHeight(); + contextOffset = $context.offset(); + }, + + show: function() { + module.debug('Showing nag', settings.animation.show); + if(settings.animation.show == 'fade') { + $module + .fadeIn(settings.duration, settings.easing) + ; + } + else { + $module + .slideDown(settings.duration, settings.easing) + ; + } + }, + + hide: function() { + module.debug('Showing nag', settings.animation.hide); + if(settings.animation.show == 'fade') { + $module + .fadeIn(settings.duration, settings.easing) + ; + } + else { + $module + .slideUp(settings.duration, settings.easing) + ; + } + }, + + onHide: function() { + module.debug('Removing nag', settings.animation.hide); + $module.remove(); + if (settings.onHide) { + settings.onHide(); + } + }, + + stick: function() { + module.refresh(); + + if(settings.position == 'fixed') { + var + windowScroll = $(window).prop('pageYOffset') || $(window).scrollTop(), + fixedOffset = ( $module.hasClass(className.bottom) ) + ? contextOffset.top + (contextHeight - moduleHeight) - windowScroll + : contextOffset.top - windowScroll + ; + $module + .css({ + position : 'fixed', + top : fixedOffset, + left : contextOffset.left, + width : contextWidth - settings.scrollBarWidth + }) + ; + } + else { + $module + .css({ + top : yPosition + }) + ; + } + }, + unStick: function() { + $module + .css({ + top : '' + }) + ; + }, + dismiss: function(event) { + if(settings.storageMethod) { + module.storage.set(settings.storedKey, settings.storedValue); + } + module.hide(); + event.stopImmediatePropagation(); + event.preventDefault(); + }, + + should: { + show: function() { + if(settings.persist) { + module.debug('Persistent nag is set, can show nag'); + return true; + } + if(module.storage.get(settings.storedKey) != settings.storedValue) { + module.debug('Stored value is not set, can show nag', module.storage.get(settings.storedKey)); + return true; + } + module.debug('Stored value is set, cannot show nag', module.storage.get(settings.storedKey)); + return false; + }, + stick: function() { + yOffset = $context.prop('pageYOffset') || $context.scrollTop(); + yPosition = ( $module.hasClass(className.bottom) ) + ? (contextHeight - $module.outerHeight() ) + yOffset + : yOffset + ; + // absolute position calculated when y offset met + if(yPosition > moduleOffset.top) { + return true; + } + else if(settings.position == 'fixed') { + return true; + } + return false; + } + }, + + storage: { + + set: function(key, value) { + module.debug('Setting stored value', key, value, settings.storageMethod); + if(settings.storageMethod == 'local' && window.store !== undefined) { + window.store.set(key, value); + } + // store by cookie + else if($.cookie !== undefined) { + $.cookie(key, value); + } + else { + module.error(error.noStorage); + } + }, + get: function(key) { + module.debug('Getting stored value', key, settings.storageMethod); + if(settings.storageMethod == 'local' && window.store !== undefined) { + return window.store.get(key); + } + // get by cookie + else if($.cookie !== undefined) { + return $.cookie(key); + } + else { + module.error(error.noStorage); + } + } + + }, + + event: { + scroll: function() { + if(timer !== undefined) { + clearTimeout(timer); + } + timer = setTimeout(function() { + if(module.should.stick() ) { + requestAnimationFrame(module.stick); + } + else { + module.unStick(); + } + }, settings.lag); + } + }, + setting: function(name, value) { + module.debug('Changing setting', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + module.debug('Changing internal', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + + }) + ; + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.nag.settings = { + + name : 'Nag', + + verbose : true, + debug : true, + performance : true, + + namespace : 'Nag', + + // allows cookie to be overriden + persist : false, + + // set to zero to manually dismiss, otherwise hides on its own + displayTime : 0, + + animation : { + show: 'slide', + hide: 'slide' + }, + + // method of stickyness + position : 'fixed', + scrollBarWidth : 18, + + // type of storage to use + storageMethod : 'cookie', + + // value to store in dismissed localstorage/cookie + storedKey : 'nag', + storedValue : 'dismiss', + + // need to calculate stickyness on scroll + sticky : false, + + // how often to check scroll event + lag : 0, + + // context for scroll event + context : window, + + error: { + noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state', + method : 'The method you called is not defined.' + }, + + className : { + bottom : 'bottom', + fixed : 'fixed' + }, + + selector : { + close: '.icon.close' + }, + + speed : 500, + easing : 'easeOutQuad', + + onHide: function() {} + +}; + +})( jQuery, window , document ); + +/* + * # Semantic - Popup + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ($, window, document, undefined) { + +$.fn.popup = function(parameters) { + var + $allModules = $(this), + + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.popup.settings, parameters) + : $.fn.popup.settings, + + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + + invokedResponse + ; + $allModules + .each(function() { + var + $module = $(this), + + $window = $(window), + $offsetParent = $module.offsetParent(), + $popup = (settings.inline) + ? $module.next(settings.selector.popup) + : $window.children(settings.selector.popup).last(), + + searchDepth = 0, + + eventNamespace = '.' + settings.namespace, + moduleNamespace = settings.namespace + '-module', + + selector = settings.selector, + className = settings.className, + error = settings.error, + metadata = settings.metadata, + namespace = settings.namespace, + + element = this, + instance = $module.data(moduleNamespace), + module + ; + + module = { + + // binds events + initialize: function() { + module.debug('Initializing module', $module); + if(settings.on == 'hover') { + $module + .on('mouseenter' + eventNamespace, module.event.mouseenter) + .on('mouseleave' + eventNamespace, module.event.mouseleave) + ; + } + else { + $module + .on(settings.on + '' + eventNamespace, module.event[settings.on]) + ; + } + $window + .on('resize' + eventNamespace, module.event.resize) + ; + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, instance) + ; + }, + + refresh: function() { + $popup = (settings.inline) + ? $module.next(selector.popup) + : $window.children(selector.popup).last() + ; + $offsetParent = $module.offsetParent(); + }, + + destroy: function() { + module.debug('Destroying previous module'); + $module + .off(eventNamespace) + .removeData(moduleNamespace) + ; + }, + + event: { + mouseenter: function(event) { + var element = this; + module.timer = setTimeout(function() { + $.proxy(module.toggle, element)(); + if( $(element).hasClass(className.visible) ) { + event.stopPropagation(); + } + }, settings.delay); + }, + mouseleave: function() { + clearTimeout(module.timer); + if( $module.is(':visible') ) { + module.hide(); + } + }, + click: function(event) { + $.proxy(module.toggle, this)(); + if( $(this).hasClass(className.visible) ) { + event.stopPropagation(); + } + }, + resize: function() { + if( $popup.is(':visible') ) { + module.position(); + } + } + }, + + // generates popup html from metadata + create: function() { + module.debug('Creating pop-up html'); + var + html = $module.data(metadata.html) || settings.html, + variation = $module.data(metadata.variation) || settings.variation, + title = $module.data(metadata.title) || settings.title, + content = $module.data(metadata.content) || $module.attr('title') || settings.content + ; + if(html || content || title) { + if(!html) { + html = settings.template({ + title : title, + content : content + }); + } + $popup = $('
') + .addClass(className.popup) + .addClass(variation) + .html(html) + ; + if(settings.inline) { + module.verbose('Inserting popup element inline'); + $popup + .insertAfter($module) + ; + } + else { + module.verbose('Appending popup element to body'); + $popup + .appendTo( $('body') ) + ; + } + $.proxy(settings.onInit, $popup)(); + } + else { + module.error(error.content); + } + }, + + remove: function() { + module.debug('Removing popup'); + $popup + .remove() + ; + }, + + get: { + offstagePosition: function() { + var + boundary = { + top : $(window).scrollTop(), + bottom : $(window).scrollTop() + $(window).height(), + left : 0, + right : $(window).width() + }, + popup = { + width : $popup.width(), + height : $popup.outerHeight(), + position : $popup.offset() + }, + offstage = {}, + offstagePositions = [] + ; + if(popup.position) { + offstage = { + top : (popup.position.top < boundary.top), + bottom : (popup.position.top + popup.height > boundary.bottom), + right : (popup.position.left + popup.width > boundary.right), + left : (popup.position.left < boundary.left) + }; + } + // return only boundaries that have been surpassed + $.each(offstage, function(direction, isOffstage) { + if(isOffstage) { + offstagePositions.push(direction); + } + }); + return (offstagePositions.length > 0) + ? offstagePositions.join(' ') + : false + ; + }, + nextPosition: function(position) { + switch(position) { + case 'top left': + position = 'bottom left'; + break; + case 'bottom left': + position = 'top right'; + break; + case 'top right': + position = 'bottom right'; + break; + case 'bottom right': + position = 'top center'; + break; + case 'top center': + position = 'bottom center'; + break; + case 'bottom center': + position = 'right center'; + break; + case 'right center': + position = 'left center'; + break; + case 'left center': + position = 'top center'; + break; + } + return position; + } + }, + + // determines popup state + toggle: function() { + $module = $(this); + module.debug('Toggling pop-up'); + // refresh state of module + module.refresh(); + if( !$module.hasClass(className.visible) ) { + module.hideAll(); + module.show(); + } + else { + module.hide(); + } + }, + + position: function(position, arrowOffset) { + var + windowWidth = $(window).width(), + windowHeight = $(window).height(), + width = $module.outerWidth(), + height = $module.outerHeight(), + popupWidth = $popup.width(), + popupHeight = $popup.outerHeight(), + + offset = (settings.inline) + ? $module.position() + : $module.offset(), + parentWidth = (settings.inline) + ? $offsetParent.outerWidth() + : $window.outerWidth(), + parentHeight = (settings.inline) + ? $offsetParent.outerHeight() + : $window.outerHeight(), + + positioning, + offstagePosition + ; + position = position || $module.data(metadata.position) || settings.position; + arrowOffset = arrowOffset || $module.data(metadata.arrowOffset) || settings.arrowOffset; + module.debug('Calculating offset for position', position); + switch(position) { + case 'top left': + positioning = { + top : 'auto', + bottom : parentHeight - offset.top + settings.distanceAway, + left : offset.left + arrowOffset + }; + break; + case 'top center': + positioning = { + bottom : parentHeight - offset.top + settings.distanceAway, + left : offset.left + (width / 2) - (popupWidth / 2) + arrowOffset, + top : 'auto', + right : 'auto' + }; + break; + case 'top right': + positioning = { + bottom : parentHeight - offset.top + settings.distanceAway, + right : parentWidth - offset.left - width - arrowOffset, + top : 'auto', + left : 'auto' + }; + break; + case 'left center': + positioning = { + top : offset.top + (height / 2) - (popupHeight / 2), + right : parentWidth - offset.left + settings.distanceAway - arrowOffset, + left : 'auto', + bottom : 'auto' + }; + break; + case 'right center': + positioning = { + top : offset.top + (height / 2) - (popupHeight / 2), + left : offset.left + width + settings.distanceAway + arrowOffset, + bottom : 'auto', + right : 'auto' + }; + break; + case 'bottom left': + positioning = { + top : offset.top + height + settings.distanceAway, + left : offset.left + arrowOffset, + bottom : 'auto', + right : 'auto' + }; + break; + case 'bottom center': + positioning = { + top : offset.top + height + settings.distanceAway, + left : offset.left + (width / 2) - (popupWidth / 2) + arrowOffset, + bottom : 'auto', + right : 'auto' + }; + break; + case 'bottom right': + positioning = { + top : offset.top + height + settings.distanceAway, + right : parentWidth - offset.left - width - arrowOffset, + left : 'auto', + bottom : 'auto' + }; + break; + } + // true width on popup, avoid rounding error + $.extend(positioning, { + width: $popup.width() + 1 + }); + // tentatively place on stage + $popup + .removeAttr('style') + .removeClass('top right bottom left center') + .css(positioning) + .addClass(position) + .addClass(className.loading) + ; + // check if is offstage + offstagePosition = module.get.offstagePosition(); + // recursively find new positioning + if(offstagePosition) { + module.debug('Element is outside boundaries ', offstagePosition); + if(searchDepth < settings.maxSearchDepth) { + position = module.get.nextPosition(position); + searchDepth++; + module.debug('Trying new position: ', position); + return module.position(position); + } + else { + module.error(error.recursion); + searchDepth = 0; + return false; + } + } + else { + module.debug('Position is on stage', position); + searchDepth = 0; + return true; + } + }, + + show: function() { + module.debug('Showing pop-up', settings.transition); + if($popup.size() === 0) { + module.create(); + } + module.position(); + $module + .addClass(className.visible) + ; + $popup + .removeClass(className.loading) + ; + if(settings.transition && $.fn.transition !== undefined) { + $popup + .transition(settings.transition + ' in', settings.duration) + ; + } + else { + $popup + .stop() + .fadeIn(settings.duration, settings.easing) + ; + } + if(settings.on == 'click' && settings.clicktoClose) { + module.debug('Binding popup close event'); + $(document) + .on('click.' + namespace, module.gracefully.hide) + ; + } + $.proxy(settings.onShow, $popup)(); + }, + + hideAll: function() { + $(selector.popup) + .filter(':visible') + .popup('hide') + ; + }, + + hide: function() { + $module + .removeClass(className.visible) + ; + if($popup.is(':visible') ) { + module.debug('Hiding pop-up'); + if(settings.transition && $.fn.transition !== undefined) { + $popup + .transition(settings.transition + ' out', settings.duration) + ; + } + else { + $popup + .stop() + .fadeOut(settings.duration, settings.easing) + ; + } + } + if(settings.on == 'click' && settings.clicktoClose) { + $(document) + .off('click.' + namespace) + ; + } + $.proxy(settings.onHide, $popup)(); + if(!settings.inline) { + module.remove(); + } + }, + + gracefully: { + hide: function(event) { + // don't close on clicks inside popup + if( $(event.target).closest(selector.popup).size() === 0) { + module.hide(); + } + } + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.popup.settings = { + + name : 'Popup', + debug : true, + verbose : true, + performance : true, + namespace : 'popup', + + onInit : function(){}, + onShow : function(){}, + onHide : function(){}, + + variation : '', + content : false, + html : false, + title : false, + + on : 'hover', + clicktoClose : true, + + position : 'top center', + delay : 150, + inline : true, + + duration : 150, + easing : 'easeOutQuint', + transition : 'scale', + + distanceAway : 0, + arrowOffset : 0, + maxSearchDepth : 10, + + error: { + content : 'Your popup has no content specified', + method : 'The method you called is not defined.', + recursion : 'Popup attempted to reposition element to fit, but could not find an adequate position.' + }, + + metadata: { + arrowOffset : 'arrowOffset', + content : 'content', + html : 'html', + position : 'position', + title : 'title', + variation : 'variation' + }, + + className : { + popup : 'ui popup', + visible : 'visible', + loading : 'loading' + }, + + selector : { + popup : '.ui.popup' + }, + + template: function(text) { + var html = ''; + if(typeof text !== undefined) { + if(typeof text.title !== undefined && text.title) { + html += '
' + text.title + '
'; + } + if(typeof text.content !== undefined && text.content) { + html += '
' + text.content + '
'; + } + } + return html; + } + +}; + +})( jQuery, window , document ); + +/* + * # Semantic - Rating + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ($, window, document, undefined) { + +$.fn.rating = function(parameters) { + var + $allModules = $(this), + moduleSelector = $allModules.selector || '', + + settings = $.extend(true, {}, $.fn.rating.settings, parameters), + + namespace = settings.namespace, + className = settings.className, + metadata = settings.metadata, + selector = settings.selector, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + $allModules + .each(function() { + var + $module = $(this), + $icon = $module.find(selector.icon), + + element = this, + instance = $module.data(moduleNamespace), + module + ; + + module = { + + initialize: function() { + module.verbose('Initializing rating module'); + if(settings.interactive) { + $icon + .bind('mouseenter' + eventNamespace, module.event.mouseenter) + .bind('mouseleave' + eventNamespace, module.event.mouseleave) + .bind('click' + eventNamespace, module.event.click) + ; + } + if(settings.initialRating) { + module.debug('Setting initial rating'); + module.setRating(settings.initialRating); + } + if( $module.data(metadata.rating) ) { + module.debug('Rating found in metadata'); + module.setRating( $module.data(metadata.rating) ); + } + $module + .addClass(className.active) + ; + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Instantiating module', settings); + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + $module + .removeData(moduleNamespace) + ; + $icon + .off(eventNamespace) + ; + }, + + setRating: function(rating) { + var + $activeIcon = $icon.eq(rating - 1) + ; + module.verbose('Setting current rating to', rating); + $module + .removeClass(className.hover) + ; + $icon + .removeClass(className.hover) + ; + $activeIcon + .nextAll() + .removeClass(className.active) + ; + $activeIcon + .addClass(className.active) + .prevAll() + .addClass(className.active) + ; + $.proxy(settings.onRate, element)(); + }, + + event: { + mouseenter: function() { + var + $activeIcon = $(this) + ; + $activeIcon + .nextAll() + .removeClass(className.hover) + ; + $module + .addClass(className.hover) + ; + $activeIcon + .addClass(className.hover) + .prevAll() + .addClass(className.hover) + ; + }, + mouseleave: function() { + $module + .removeClass(className.hover) + ; + $icon + .removeClass(className.hover) + ; + }, + click: function() { + var + $activeIcon = $(this) + ; + module.setRating( $icon.index($activeIcon) + 1); + } + }, + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.rating.settings = { + + name : 'Rating', + namespace : 'rating', + + verbose : true, + debug : true, + performance : true, + + initialRating : 0, + interactive : true, + onRate : function(){}, + + error : { + method : 'The method you called is not defined' + }, + + metadata: { + rating: 'rating' + }, + + className : { + active : 'active', + hover : 'hover', + loading : 'loading' + }, + + selector : { + icon : '.icon' + } + +}; + +})( jQuery, window , document ); + +/* + * # Semantic - Search + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ($, window, document, undefined) { + +$.fn.search = function(source, parameters) { + var + $allModules = $(this), + settings = $.extend(true, {}, $.fn.search.settings, parameters), + + + className = settings.className, + selector = settings.selector, + error = settings.error, + namespace = settings.namespace, + + eventNamespace = '.' + namespace, + moduleNamespace = namespace + '-module', + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + $(this) + .each(function() { + var + $module = $(this), + $prompt = $module.find(selector.prompt), + $searchButton = $module.find(selector.searchButton), + $results = $module.find(selector.results), + $result = $module.find(selector.result), + $category = $module.find(selector.category), + + element = this, + instance = $module.data(moduleNamespace), + + module + ; + module = { + + initialize: function() { + module.verbose('Initializing module'); + var + prompt = $prompt[0], + inputEvent = (prompt.oninput !== undefined) + ? 'input' + : (prompt.onpropertychange !== undefined) + ? 'propertychange' + : 'keyup' + ; + // attach events + $prompt + .on('focus' + eventNamespace, module.event.focus) + .on('blur' + eventNamespace, module.event.blur) + .on('keydown' + eventNamespace, module.handleKeyboard) + ; + if(settings.automatic) { + $prompt + .on(inputEvent + eventNamespace, module.search.throttle) + ; + } + $searchButton + .on('click' + eventNamespace, module.search.query) + ; + $results + .on('click' + eventNamespace, selector.result, module.results.select) + ; + module.instantiate(); + }, + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, module) + ; + }, + destroy: function() { + module.verbose('Destroying instance'); + $module + .removeData(moduleNamespace) + ; + }, + event: { + focus: function() { + $module + .addClass(className.focus) + ; + module.results.show(); + }, + blur: function() { + module.search.cancel(); + $module + .removeClass(className.focus) + ; + module.results.hide(); + } + }, + handleKeyboard: function(event) { + var + // force latest jq dom + $result = $module.find(selector.result), + $category = $module.find(selector.category), + keyCode = event.which, + keys = { + backspace : 8, + enter : 13, + escape : 27, + upArrow : 38, + downArrow : 40 + }, + activeClass = className.active, + currentIndex = $result.index( $result.filter('.' + activeClass) ), + resultSize = $result.size(), + newIndex + ; + // search shortcuts + if(keyCode == keys.escape) { + module.verbose('Escape key pressed, blurring search field'); + $prompt + .trigger('blur') + ; + } + // result shortcuts + if($results.filter(':visible').size() > 0) { + if(keyCode == keys.enter) { + module.verbose('Enter key pressed, selecting active result'); + if( $result.filter('.' + activeClass).exists() ) { + $.proxy(module.results.select, $result.filter('.' + activeClass) )(); + event.preventDefault(); + return false; + } + } + else if(keyCode == keys.upArrow) { + module.verbose('Up key pressed, changing active result'); + newIndex = (currentIndex - 1 < 0) + ? currentIndex + : currentIndex - 1 + ; + $category + .removeClass(activeClass) + ; + $result + .removeClass(activeClass) + .eq(newIndex) + .addClass(activeClass) + .closest($category) + .addClass(activeClass) + ; + event.preventDefault(); + } + else if(keyCode == keys.downArrow) { + module.verbose('Down key pressed, changing active result'); + newIndex = (currentIndex + 1 >= resultSize) + ? currentIndex + : currentIndex + 1 + ; + $category + .removeClass(activeClass) + ; + $result + .removeClass(activeClass) + .eq(newIndex) + .addClass(activeClass) + .closest($category) + .addClass(activeClass) + ; + event.preventDefault(); + } + } + else { + // query shortcuts + if(keyCode == keys.enter) { + module.verbose('Enter key pressed, executing query'); + module.search.query(); + $searchButton + .addClass(className.down) + ; + $prompt + .one('keyup', function(){ + $searchButton + .removeClass(className.down) + ; + }) + ; + } + } + }, + search: { + cancel: function() { + var + xhr = $module.data('xhr') || false + ; + if( xhr && xhr.state() != 'resolved') { + module.debug('Cancelling last search'); + xhr.abort(); + } + }, + throttle: function() { + var + searchTerm = $prompt.val(), + numCharacters = searchTerm.length + ; + clearTimeout(module.timer); + if(numCharacters >= settings.minCharacters) { + module.timer = setTimeout(module.search.query, settings.searchThrottle); + } + else { + module.results.hide(); + } + }, + query: function() { + var + searchTerm = $prompt.val(), + cachedHTML = module.search.cache.read(searchTerm) + ; + if(cachedHTML) { + module.debug("Reading result for '" + searchTerm + "' from cache"); + module.results.add(cachedHTML); + } + else { + module.debug("Querying for '" + searchTerm + "'"); + if(typeof source == 'object') { + module.search.local(searchTerm); + } + else { + module.search.remote(searchTerm); + } + $.proxy(settings.onSearchQuery, $module)(searchTerm); + } + }, + local: function(searchTerm) { + var + results = [], + fullTextResults = [], + searchFields = $.isArray(settings.searchFields) + ? settings.searchFields + : [settings.searchFields], + + searchRegExp = new RegExp('(?:\s|^)' + searchTerm, 'i'), + fullTextRegExp = new RegExp(searchTerm, 'i'), + searchHTML + ; + $module + .addClass(className.loading) + ; + // iterate through search fields in array order + $.each(searchFields, function(index, field) { + $.each(source, function(label, thing) { + if(typeof thing[field] == 'string' && ($.inArray(thing, results) == -1) && ($.inArray(thing, fullTextResults) == -1) ) { + if( searchRegExp.test( thing[field] ) ) { + results.push(thing); + } + else if( fullTextRegExp.test( thing[field] ) ) { + fullTextResults.push(thing); + } + } + }); + }); + searchHTML = module.results.generate({ + results: $.merge(results, fullTextResults) + }); + $module + .removeClass(className.loading) + ; + module.search.cache.write(searchTerm, searchHTML); + module.results.add(searchHTML); + }, + remote: function(searchTerm) { + var + apiSettings = { + stateContext : $module, + url : source, + urlData: { query: searchTerm }, + success : function(response) { + searchHTML = module.results.generate(response); + module.search.cache.write(searchTerm, searchHTML); + module.results.add(searchHTML); + }, + failure : module.error + }, + searchHTML + ; + module.search.cancel(); + module.debug('Executing search'); + $.extend(true, apiSettings, settings.apiSettings); + $.api(apiSettings); + }, + + cache: { + read: function(name) { + var + cache = $module.data('cache') + ; + return (settings.cache && (typeof cache == 'object') && (cache[name] !== undefined) ) + ? cache[name] + : false + ; + }, + write: function(name, value) { + var + cache = ($module.data('cache') !== undefined) + ? $module.data('cache') + : {} + ; + cache[name] = value; + $module + .data('cache', cache) + ; + } + } + }, + + results: { + generate: function(response) { + module.debug('Generating html from response', response); + var + template = settings.templates[settings.type], + html = '' + ; + if(($.isPlainObject(response.results) && !$.isEmptyObject(response.results)) || ($.isArray(response.results) && response.results.length > 0) ) { + if(settings.maxResults > 0) { + response.results = $.makeArray(response.results).slice(0, settings.maxResults); + } + if(response.results.length > 0) { + if($.isFunction(template)) { + html = template(response); + } + else { + module.error(error.noTemplate, false); + } + } + } + else { + html = module.message(error.noResults, 'empty'); + } + $.proxy(settings.onResults, $module)(response); + return html; + }, + add: function(html) { + if(settings.onResultsAdd == 'default' || $.proxy(settings.onResultsAdd, $results)(html) == 'default') { + $results + .html(html) + ; + } + module.results.show(); + }, + show: function() { + if( ($results.filter(':visible').size() === 0) && ($prompt.filter(':focus').size() > 0) && $results.html() !== '') { + $results + .stop() + .fadeIn(200) + ; + $.proxy(settings.onResultsOpen, $results)(); + } + }, + hide: function() { + if($results.filter(':visible').size() > 0) { + $results + .stop() + .fadeOut(200) + ; + $.proxy(settings.onResultsClose, $results)(); + } + }, + select: function(event) { + module.debug('Search result selected'); + var + $result = $(this), + $title = $result.find('.title'), + title = $title.html() + ; + if(settings.onSelect == 'default' || $.proxy(settings.onSelect, this)(event) == 'default') { + var + $link = $result.find('a[href]').eq(0), + href = $link.attr('href') || false, + target = $link.attr('target') || false + ; + module.results.hide(); + $prompt + .val(title) + ; + if(href) { + if(target == '_blank' || event.ctrlKey) { + window.open(href); + } + else { + window.location.href = (href); + } + } + } + } + }, + + setting: function(name, value) { + module.debug('Changing setting', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + module.debug('Changing internal', name, value); + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.search.settings = { + + name : 'Search Module', + namespace : 'search', + + debug : true, + verbose : true, + performance : true, + + // onSelect default action is defined in module + onSelect : 'default', + onResultsAdd : 'default', + + onSearchQuery : function(){}, + onResults : function(response){}, + + onResultsOpen : function(){}, + onResultsClose : function(){}, + + automatic : 'true', + type : 'simple', + minCharacters : 3, + searchThrottle : 300, + maxResults : 7, + cache : true, + + searchFields : [ + 'title', + 'description' + ], + + // api config + apiSettings: { + + }, + + className: { + active : 'active', + down : 'down', + focus : 'focus', + empty : 'empty', + loading : 'loading' + }, + + error : { + noResults : 'Your search returned no results', + logging : 'Error in debug logging, exiting.', + noTemplate : 'A valid template name was not specified.', + serverError : 'There was an issue with querying the server.', + method : 'The method you called is not defined.' + }, + + selector : { + prompt : '.prompt', + searchButton : '.search.button', + results : '.results', + category : '.category', + result : '.result' + }, + + templates: { + message: function(message, type) { + var + html = '' + ; + if(message !== undefined && type !== undefined) { + html += '' + + '
' + ; + // message type + if(type == 'empty') { + html += '' + + '
No Results
' + + '
' + message + '
' + ; + } + else { + html += '
' + message + '
'; + } + html += '
'; + } + return html; + }, + categories: function(response) { + var + html = '' + ; + if(response.results !== undefined) { + // each category + $.each(response.results, function(index, category) { + if(category.results !== undefined && category.results.length > 0) { + html += '' + + '
' + + '
' + category.name + '
' + ; + // each item inside category + $.each(category.results, function(index, result) { + html += '
'; + html += ''; + if(result.image !== undefined) { + html+= '' + + '
' + + ' ' + + '
' + ; + } + html += '
'; + if(result.price !== undefined) { + html+= '
' + result.price + '
'; + } + if(result.title !== undefined) { + html+= '
' + result.title + '
'; + } + if(result.description !== undefined) { + html+= '
' + result.description + '
'; + } + html += '' + + '
' + + '
' + ; + }); + html += '' + + '
' + ; + } + }); + if(response.resultPage) { + html += '' + + '' + + response.resultPage.text + + ''; + } + return html; + } + return false; + }, + simple: function(response) { + var + html = '' + ; + if(response.results !== undefined) { + + // each result + $.each(response.results, function(index, result) { + html += ''; + if(result.image !== undefined) { + html+= '' + + '
' + + ' ' + + '
' + ; + } + html += '
'; + if(result.price !== undefined) { + html+= '
' + result.price + '
'; + } + if(result.title !== undefined) { + html+= '
' + result.title + '
'; + } + if(result.description !== undefined) { + html+= '
' + result.description + '
'; + } + html += '' + + '
' + + '
' + ; + }); + + if(response.resultPage) { + html += '' + + '' + + response.resultPage.text + + ''; + } + return html; + } + return false; + } + } +}; + +})( jQuery, window , document ); +/* + * # Semantic - Shape + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.shape = function(parameters) { + var + $allModules = $(this), + + moduleSelector = $allModules.selector || '', + settings = $.extend(true, {}, $.fn.shape.settings, parameters), + + // internal aliases + namespace = settings.namespace, + selector = settings.selector, + error = settings.error, + className = settings.className, + + // define namespaces for modules + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + + $allModules + .each(function() { + var + // selector cache + $module = $(this), + $sides = $module.find(selector.sides), + $side = $module.find(selector.side), + + // private variables + $activeSide, + $nextSide, + + // standard module + element = this, + instance = $module.data(moduleNamespace), + module + ; + + module = { + + initialize: function() { + module.verbose('Initializing module for', element); + module.set.defaultSide(); + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, instance) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module for', element); + $module + .removeData(moduleNamespace) + .off(eventNamespace) + ; + }, + + refresh: function() { + module.verbose('Refreshing selector cache for', element); + $module = $(element); + $sides = $(this).find(selector.shape); + $side = $(this).find(selector.side); + }, + + repaint: function() { + module.verbose('Forcing repaint event'); + var + shape = $sides.get(0) || document.createElement('div'), + fakeAssignment = shape.offsetWidth + ; + }, + + animate: function(propertyObject, callback) { + module.verbose('Animating box with properties', propertyObject); + callback = callback || function(event) { + module.verbose('Executing animation callback'); + if(event !== undefined) { + event.stopPropagation(); + } + module.reset(); + module.set.active(); + }; + if(settings.useCSS) { + if(module.get.transitionEvent()) { + module.verbose('Starting CSS animation'); + $module + .addClass(className.animating) + ; + module.set.stageSize(); + module.repaint(); + $module + .addClass(className.css) + ; + $activeSide + .addClass(className.hidden) + ; + $sides + .css(propertyObject) + .one(module.get.transitionEvent(), callback) + ; + } + else { + callback(); + } + } + else { + // not yet supported until .animate() is extended to allow RotateX/Y + module.verbose('Starting javascript animation'); + $module + .addClass(className.animating) + .removeClass(className.css) + ; + module.set.stageSize(); + module.repaint(); + $activeSide + .animate({ + opacity: 0 + }, settings.duration, settings.easing) + ; + $sides + .animate(propertyObject, settings.duration, settings.easing, callback) + ; + } + }, + + queue: function(method) { + module.debug('Queueing animation of', method); + $sides + .one(module.get.transitionEvent(), function() { + module.debug('Executing queued animation'); + setTimeout(function(){ + $module.shape(method); + }, 0); + }) + ; + }, + + reset: function() { + module.verbose('Animating states reset'); + $module + .removeClass(className.css) + .removeClass(className.animating) + .attr('style', '') + .removeAttr('style') + ; + // removeAttr style does not consistently work in safari + $sides + .attr('style', '') + .removeAttr('style') + ; + $side + .attr('style', '') + .removeAttr('style') + .removeClass(className.hidden) + ; + $nextSide + .removeClass(className.animating) + .attr('style', '') + .removeAttr('style') + ; + }, + + is: { + animating: function() { + return $module.hasClass(className.animating); + } + }, + + get: { + + transform: { + up: function() { + var + translate = { + y: -(($activeSide.outerHeight() - $nextSide.outerHeight()) / 2), + z: -($activeSide.outerHeight() / 2) + } + ; + return { + transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(-90deg)' + }; + }, + + down: function() { + var + translate = { + y: -(($activeSide.outerHeight() - $nextSide.outerHeight()) / 2), + z: -($activeSide.outerHeight() / 2) + } + ; + return { + transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(90deg)' + }; + }, + + left: function() { + var + translate = { + x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2), + z : -($activeSide.outerWidth() / 2) + } + ; + return { + transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(90deg)' + }; + }, + + right: function() { + var + translate = { + x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2), + z : -($activeSide.outerWidth() / 2) + } + ; + return { + transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(-90deg)' + }; + }, + + over: function() { + var + translate = { + x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2) + } + ; + return { + transform: 'translateX(' + translate.x + 'px) rotateY(180deg)' + }; + }, + + back: function() { + var + translate = { + x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2) + } + ; + return { + transform: 'translateX(' + translate.x + 'px) rotateY(-180deg)' + }; + } + }, + + transitionEvent: function() { + var + element = document.createElement('element'), + transitions = { + 'transition' :'transitionend', + 'OTransition' :'oTransitionEnd', + 'MozTransition' :'transitionend', + 'WebkitTransition' :'webkitTransitionEnd' + }, + transition + ; + for(transition in transitions){ + if( element.style[transition] !== undefined ){ + return transitions[transition]; + } + } + }, + + nextSide: function() { + return ( $activeSide.next(selector.side).size() > 0 ) + ? $activeSide.next(selector.side) + : $module.find(selector.side).first() + ; + } + + }, + + set: { + + defaultSide: function() { + $activeSide = $module.find('.' + settings.className.active); + $nextSide = ( $activeSide.next(selector.side).size() > 0 ) + ? $activeSide.next(selector.side) + : $module.find(selector.side).first() + ; + module.verbose('Active side set to', $activeSide); + module.verbose('Next side set to', $nextSide); + }, + + stageSize: function() { + var + stage = { + width : $nextSide.outerWidth(), + height : $nextSide.outerHeight() + } + ; + module.verbose('Resizing stage to fit new content', stage); + $module + .css({ + width : stage.width, + height : stage.height + }) + ; + }, + + nextSide: function(selector) { + $nextSide = $module.find(selector); + if($nextSide.size() === 0) { + module.error(error.side); + } + module.verbose('Next side manually set to', $nextSide); + }, + + active: function() { + module.verbose('Setting new side to active', $nextSide); + $side + .removeClass(className.active) + ; + $nextSide + .addClass(className.active) + ; + $.proxy(settings.onChange, $nextSide)(); + module.set.defaultSide(); + } + }, + + flip: { + + up: function() { + module.debug('Flipping up', $nextSide); + if( !module.is.animating() ) { + module.stage.above(); + module.animate( module.get.transform.up() ); + } + else { + module.queue('flip up'); + } + }, + + down: function() { + module.debug('Flipping down', $nextSide); + if( !module.is.animating() ) { + module.stage.below(); + module.animate( module.get.transform.down() ); + } + else { + module.queue('flip down'); + } + }, + + left: function() { + module.debug('Flipping left', $nextSide); + if( !module.is.animating() ) { + module.stage.left(); + module.animate(module.get.transform.left() ); + } + else { + module.queue('flip left'); + } + }, + + right: function() { + module.debug('Flipping right', $nextSide); + if( !module.is.animating() ) { + module.stage.right(); + module.animate(module.get.transform.right() ); + } + else { + module.queue('flip right'); + } + }, + + over: function() { + module.debug('Flipping over', $nextSide); + if( !module.is.animating() ) { + module.stage.behind(); + module.animate(module.get.transform.over() ); + } + else { + module.queue('flip over'); + } + }, + + back: function() { + module.debug('Flipping back', $nextSide); + if( !module.is.animating() ) { + module.stage.behind(); + module.animate(module.get.transform.back() ); + } + else { + module.queue('flip back'); + } + } + + }, + + stage: { + + above: function() { + var + box = { + origin : (($activeSide.outerHeight() - $nextSide.outerHeight()) / 2), + depth : { + active : ($nextSide.outerHeight() / 2), + next : ($activeSide.outerHeight() / 2) + } + } + ; + module.verbose('Setting the initial animation position as above', $nextSide, box); + $activeSide + .css({ + 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)' + }) + ; + $nextSide + .addClass(className.animating) + .css({ + 'display' : 'block', + 'top' : box.origin + 'px', + 'transform' : 'rotateX(90deg) translateZ(' + box.depth.next + 'px)' + }) + ; + }, + + below: function() { + var + box = { + origin : (($activeSide.outerHeight() - $nextSide.outerHeight()) / 2), + depth : { + active : ($nextSide.outerHeight() / 2), + next : ($activeSide.outerHeight() / 2) + } + } + ; + module.verbose('Setting the initial animation position as below', $nextSide, box); + $activeSide + .css({ + 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)' + }) + ; + $nextSide + .addClass(className.animating) + .css({ + 'display' : 'block', + 'top' : box.origin + 'px', + 'transform' : 'rotateX(-90deg) translateZ(' + box.depth.next + 'px)' + }) + ; + }, + + left: function() { + var + box = { + origin : ( ( $activeSide.outerWidth() - $nextSide.outerWidth() ) / 2), + depth : { + active : ($nextSide.outerWidth() / 2), + next : ($activeSide.outerWidth() / 2) + } + } + ; + module.verbose('Setting the initial animation position as left', $nextSide, box); + $activeSide + .css({ + 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)' + }) + ; + $nextSide + .addClass(className.animating) + .css({ + 'display' : 'block', + 'left' : box.origin + 'px', + 'transform' : 'rotateY(-90deg) translateZ(' + box.depth.next + 'px)' + }) + ; + }, + + right: function() { + var + box = { + origin : ( ( $activeSide.outerWidth() - $nextSide.outerWidth() ) / 2), + depth : { + active : ($nextSide.outerWidth() / 2), + next : ($activeSide.outerWidth() / 2) + } + } + ; + module.verbose('Setting the initial animation position as left', $nextSide, box); + $activeSide + .css({ + 'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)' + }) + ; + $nextSide + .addClass(className.animating) + .css({ + 'display' : 'block', + 'left' : box.origin + 'px', + 'transform' : 'rotateY(90deg) translateZ(' + box.depth.next + 'px)' + }) + ; + }, + + behind: function() { + var + box = { + origin : ( ( $activeSide.outerWidth() - $nextSide.outerWidth() ) / 2), + depth : { + active : ($nextSide.outerWidth() / 2), + next : ($activeSide.outerWidth() / 2) + } + } + ; + module.verbose('Setting the initial animation position as behind', $nextSide, box); + $activeSide + .css({ + 'transform' : 'rotateY(0deg)' + }) + ; + $nextSide + .addClass(className.animating) + .css({ + 'display' : 'block', + 'left' : box.origin + 'px', + 'transform' : 'rotateY(-180deg)' + }) + ; + } + }, + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.shape.settings = { + + // module info + name : 'Shape', + + // debug content outputted to console + debug : true, + + // verbose debug output + verbose : true, + + // performance data output + performance: true, + + // event namespace + namespace : 'shape', + + // callback occurs on side change + beforeChange : function() {}, + onChange : function() {}, + + // use css animation (currently only true is supported) + useCSS : true, + + // animation duration (useful only with future js animations) + duration : 1000, + easing : 'easeInOutQuad', + + // possible errors + error: { + side : 'You tried to switch to a side that does not exist.', + method : 'The method you called is not defined' + }, + + // classnames used + className : { + css : 'css', + animating : 'animating', + hidden : 'hidden', + active : 'active' + }, + + // selectors used + selector : { + sides : '.sides', + side : '.side' + } + +}; + + +})( jQuery, window , document ); +/* + * # Semantic - Dropdown + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.sidebar = function(parameters) { + var + $allModules = $(this), + + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.sidebar.settings, parameters) + : $.fn.sidebar.settings, + + selector = settings.selector, + className = settings.className, + namespace = settings.namespace, + error = settings.error, + + eventNamespace = '.' + namespace, + moduleNamespace = 'module-' + namespace, + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + invokedResponse + ; + + $allModules + .each(function() { + var + $module = $(this), + + $body = $('body'), + $head = $('head'), + $style = $('style[title=' + namespace + ']'), + + element = this, + instance = $module.data(moduleNamespace), + module + ; + + module = { + + initialize: function() { + module.debug('Initializing sidebar', $module); + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module for', $module); + $module + .off(eventNamespace) + .removeData(moduleNamespace) + ; + }, + + refresh: function() { + module.verbose('Refreshing selector cache'); + $style = $('style[title=' + namespace + ']'); + }, + + attach: { + + events: function(selector, event) { + var + $toggle = $(selector) + ; + event = $.isFunction(module[event]) + ? module[event] + : module.toggle + ; + if($toggle.size() > 0) { + module.debug('Attaching sidebar events to element', selector, event); + $toggle + .off(eventNamespace) + .on('click' + eventNamespace, event) + ; + } + else { + module.error(error.notFound); + } + } + + }, + + show: function() { + module.debug('Showing sidebar'); + if(module.is.closed()) { + if(!settings.overlay) { + module.pushPage(); + } + module.set.active(); + } + else { + module.debug('Sidebar is already visible'); + } + }, + + hide: function() { + if(module.is.open()) { + if(!settings.overlay) { + module.pullPage(); + module.remove.pushed(); + } + module.remove.active(); + } + }, + + toggle: function() { + if(module.is.closed()) { + module.show(); + } + else { + module.hide(); + } + }, + + pushPage: function() { + var + direction = module.get.direction(), + distance = (module.is.vertical()) + ? $module.outerHeight() + : $module.outerWidth() + ; + if(settings.useCSS) { + module.debug('Using CSS to animate body'); + module.add.bodyCSS(direction, distance); + module.set.pushed(); + } + else { + module.animatePage(direction, distance, module.set.pushed); + } + }, + + pullPage: function() { + var + direction = module.get.direction() + ; + if(settings.useCSS) { + module.debug('Resetting body position css'); + module.remove.bodyCSS(); + } + else { + module.debug('Resetting body position using javascript'); + module.animatePage(direction, 0); + } + module.remove.pushed(); + }, + + animatePage: function(direction, distance) { + var + animateSettings = {} + ; + animateSettings['padding-' + direction] = distance; + module.debug('Using javascript to animate body', animateSettings); + $body + .animate(animateSettings, settings.duration, module.set.pushed) + ; + }, + + add: { + bodyCSS: function(direction, distance) { + var + style + ; + if(direction !== className.bottom) { + style = '' + + '' + ; + } + $head.append(style); + module.debug('Adding body css to head', $style); + } + }, + + remove: { + bodyCSS: function() { + module.debug('Removing body css styles', $style); + module.refresh(); + $style.remove(); + }, + active: function() { + $module.removeClass(className.active); + }, + pushed: function() { + module.verbose('Removing body push state', module.get.direction()); + $body + .removeClass(className[ module.get.direction() ]) + .removeClass(className.pushed) + ; + } + }, + + set: { + active: function() { + $module.addClass(className.active); + }, + pushed: function() { + module.verbose('Adding body push state', module.get.direction()); + $body + .addClass(className[ module.get.direction() ]) + .addClass(className.pushed) + ; + } + }, + + get: { + direction: function() { + if($module.hasClass(className.top)) { + return className.top; + } + else if($module.hasClass(className.right)) { + return className.right; + } + else if($module.hasClass(className.bottom)) { + return className.bottom; + } + else { + return className.left; + } + }, + transitionEvent: function() { + var + element = document.createElement('element'), + transitions = { + 'transition' :'transitionend', + 'OTransition' :'oTransitionEnd', + 'MozTransition' :'transitionend', + 'WebkitTransition' :'webkitTransitionEnd' + }, + transition + ; + for(transition in transitions){ + if( element.style[transition] !== undefined ){ + return transitions[transition]; + } + } + } + }, + + is: { + open: function() { + return $module.is(':animated') || $module.hasClass(className.active); + }, + closed: function() { + return !module.is.open(); + }, + vertical: function() { + return $module.hasClass(className.top); + } + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.sidebar.settings = { + + name : 'Sidebar', + namespace : 'sidebar', + + verbose : true, + debug : true, + performance : true, + + useCSS : true, + overlay : false, + duration : 300, + + side : 'left', + + onChange : function(){}, + onShow : function(){}, + onHide : function(){}, + + className: { + active : 'active', + pushed : 'pushed', + top : 'top', + left : 'left', + right : 'right', + bottom : 'bottom' + }, + + error : { + method : 'The method you called is not defined.', + notFound : 'There were no elements that matched the specified selector' + } + +}; + +})( jQuery, window , document ); +/* + * # Semantic - Tab + * http://github.com/jlukic/semantic-ui/ + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + + +;(function ($, window, document, undefined) { + + $.fn.tab = function(parameters) { + + var + settings = $.extend(true, {}, $.fn.tab.settings, parameters), + + $module = $(this), + $tabs = $(settings.context).find(settings.selector.tabs), + + moduleSelector = $module.selector || '', + + cache = {}, + firstLoad = true, + recursionDepth = 0, + + activeTabPath, + parameterArray, + historyEvent, + + element = this, + time = new Date().getTime(), + performance = [], + + className = settings.className, + metadata = settings.metadata, + error = settings.error, + + eventNamespace = '.' + settings.namespace, + moduleNamespace = settings.namespace + '-module', + + instance = $module.data(moduleNamespace), + + query = arguments[0], + methodInvoked = (instance !== undefined && typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + + module, + invokedResponse + ; + + module = { + + initialize: function() { + module.debug('Initializing Tabs', $module); + // attach history events + if(settings.history) { + if( $.address === undefined ) { + module.error(error.state); + return false; + } + else if(settings.path === false) { + module.error(error.path); + return false; + } + else { + if(settings.auto) { + settings.apiSettings = { + url: settings.path + '/{$tab}' + }; + } + module.verbose('Address library found adding state change event'); + $.address + .state(settings.path) + .unbind('change') + .bind('change', module.event.history.change) + ; + } + } + // attach events if navigation wasn't set to window + if( !$.isWindow( element ) ) { + $module + .on('click' + eventNamespace, module.event.click) + ; + } + module.instantiate(); + }, + + instantiate: function () { + module.verbose('Storing instance of module', module); + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.debug('Destroying tabs', $module); + $module + .off(eventNamespace) + ; + }, + + event: { + click: function() { + module.debug('Navigation clicked'); + var + tabPath = $(this).data(metadata.tab) + ; + if(tabPath !== undefined) { + if(settings.history) { + $.address.value(tabPath); + } + else { + module.changeTab(tabPath); + } + } + else { + module.debug('No tab specified'); + } + }, + history: { + change: function(event) { + var + tabPath = event.pathNames.join('/') || module.get.initialPath(), + pageTitle = settings.templates.determineTitle(tabPath) || false + ; + module.debug('History change event', tabPath, event); + historyEvent = event; + if(tabPath !== undefined) { + module.changeTab(tabPath); + } + if(pageTitle) { + $.address.title(pageTitle); + } + } + } + }, + + refresh: function() { + if(activeTabPath) { + module.debug('Refreshing tab', activeTabPath); + module.changeTab(activeTabPath); + } + }, + + cache: { + + read: function(cacheKey) { + return (cacheKey !== undefined) + ? cache[cacheKey] + : false + ; + }, + add: function(cacheKey, content) { + cacheKey = cacheKey || activeTabPath; + module.debug('Adding cached content for', cacheKey); + cache[cacheKey] = content; + }, + remove: function(cacheKey) { + cacheKey = cacheKey || activeTabPath; + module.debug('Removing cached content for', cacheKey); + delete cache[cacheKey]; + } + }, + + changeTab: function(tabPath) { + var + pushStateAvailable = (window.history && window.history.pushState), + shouldIgnoreLoad = (pushStateAvailable && settings.ignoreFirstLoad && firstLoad), + remoteContent = (settings.auto || $.isPlainObject(settings.apiSettings) ), + // only get default path if not remote content + pathArray = (remoteContent && !shouldIgnoreLoad) + ? module.utilities.pathToArray(tabPath) + : module.get.defaultPathArray(tabPath), + tabPath = module.utilities.arrayToPath(pathArray) + ; + module.deactivate.all(); + $.each(pathArray, function(index, tab) { + var + currentPathArray = pathArray.slice(0, index + 1), + currentPath = module.utilities.arrayToPath(currentPathArray), + + isTab = module.is.tab(currentPath), + isLastIndex = (index + 1 == pathArray.length), + + $tab = module.get.tabElement(currentPath), + nextPathArray, + nextPath, + isLastTab + ; + module.verbose('Looking for tab', tab); + if(isTab) { + module.verbose('Tab was found', tab); + + // scope up + activeTabPath = currentPath; + parameterArray = module.utilities.filterArray(pathArray, currentPathArray); + + if(isLastIndex) { + isLastTab = true; + } + else { + nextPathArray = pathArray.slice(0, index + 2); + nextPath = module.utilities.arrayToPath(nextPathArray); + isLastTab = ( !module.is.tab(nextPath) ); + if(isLastTab) { + module.verbose('Tab parameters found', nextPathArray); + } + } + if(isLastTab && remoteContent) { + if(!shouldIgnoreLoad) { + module.activate.navigation(currentPath); + module.content.fetch(currentPath, tabPath); + } + else { + module.debug('Ignoring remote content on first tab load', currentPath); + firstLoad = false; + module.cache.add(tabPath, $tab.html()); + module.activate.all(currentPath); + $.proxy(settings.onTabInit, $tab)(currentPath, parameterArray, historyEvent); + $.proxy(settings.onTabLoad, $tab)(currentPath, parameterArray, historyEvent); + } + return false; + } + else { + module.debug('Opened local tab', currentPath); + module.activate.all(currentPath); + $.proxy(settings.onTabLoad, $tab)(currentPath, parameterArray, historyEvent); + } + } + else { + module.error(error.missingTab, tab); + return false; + } + }); + }, + + content: { + + fetch: function(tabPath, fullTabPath) { + var + $tab = module.get.tabElement(tabPath), + fullTabPath = fullTabPath || tabPath, + cachedContent = module.cache.read(fullTabPath), + apiSettings = { + dataType : 'html', + stateContext : $tab, + success : function(response) { + module.cache.add(fullTabPath, response); + module.content.update(tabPath, response); + if(tabPath == activeTabPath) { + module.debug('Content loaded', tabPath); + module.activate.tab(tabPath); + } + else { + module.debug('Content loaded in background', tabPath); + } + $.proxy(settings.onTabInit, $tab)(tabPath, parameterArray, historyEvent); + $.proxy(settings.onTabLoad, $tab)(tabPath, parameterArray, historyEvent); + }, + urlData: { tab: fullTabPath } + }, + request = $tab.data(metadata.promise) || false, + existingRequest = ( request && request.state() === 'pending' ) + ; + if(settings.cache && cachedContent) { + module.debug('Showing existing content', fullTabPath); + module.content.update(tabPath, cachedContent); + module.activate.tab(tabPath); + $.proxy(settings.onTabLoad, $tab)(tabPath, parameterArray, historyEvent); + } + else if(existingRequest) { + module.debug('Content is already loading', fullTabPath); + $tab + .addClass(className.loading) + ; + } + else if($.api !== undefined) { + module.debug('Retrieving remote content', fullTabPath); + $.api( $.extend(true, { headers: { 'X-Remote': true } }, settings.apiSettings, apiSettings) ); + } + else { + module.error(error.api); + } + }, + + update: function(tabPath, html) { + module.debug('Updating html for', tabPath); + var + $tab = module.get.tabElement(tabPath) + ; + $tab + .html(html) + ; + } + }, + + activate: { + all: function(tabPath) { + module.activate.tab(tabPath); + module.activate.navigation(tabPath); + }, + tab: function(tabPath) { + var + $tab = module.get.tabElement(tabPath) + ; + module.verbose('Showing tab content for', $tab); + $tab.addClass(className.active); + }, + navigation: function(tabPath) { + var + $navigation = module.get.navElement(tabPath) + ; + module.verbose('Activating tab navigation for', $navigation, tabPath); + $navigation.addClass(className.active); + } + }, + + deactivate: { + all: function() { + module.deactivate.navigation(); + module.deactivate.tabs(); + }, + navigation: function() { + $module + .removeClass(className.active) + ; + }, + tabs: function() { + $tabs + .removeClass(className.active + ' ' + className.loading) + ; + } + }, + + is: { + tab: function(tabName) { + return (tabName !== undefined) + ? ( module.get.tabElement(tabName).size() > 0 ) + : false + ; + } + }, + + get: { + initialPath: function() { + return $module.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab); + }, + path: function() { + return $.address.value(); + }, + // adds default tabs to tab path + defaultPathArray: function(tabPath) { + return module.utilities.pathToArray( module.get.defaultPath(tabPath) ); + }, + defaultPath: function(tabPath) { + var + $defaultNav = $module.filter('[data-' + metadata.tab + '^="' + tabPath + '/"]').eq(0), + defaultTab = $defaultNav.data(metadata.tab) || false + ; + if( defaultTab ) { + module.debug('Found default tab', defaultTab); + if(recursionDepth < settings.maxDepth) { + recursionDepth++; + return module.get.defaultPath(defaultTab); + } + module.error(error.recursion); + } + else { + module.debug('No default tabs found for', tabPath); + } + recursionDepth = 0; + return tabPath; + }, + navElement: function(tabPath) { + tabPath = tabPath || activeTabPath; + return $module.filter('[data-' + metadata.tab + '="' + tabPath + '"]'); + }, + tabElement: function(tabPath) { + var + $fullPathTab, + $simplePathTab, + tabPathArray, + lastTab + ; + tabPath = tabPath || activeTabPath; + tabPathArray = module.utilities.pathToArray(tabPath); + lastTab = module.utilities.last(tabPathArray); + $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + lastTab + '"]'); + $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + tabPath + '"]'); + return ($fullPathTab.size() > 0) + ? $fullPathTab + : $simplePathTab + ; + }, + tab: function() { + return activeTabPath; + } + }, + + utilities: { + filterArray: function(keepArray, removeArray) { + return $.grep(keepArray, function(keepValue) { + return ( $.inArray(keepValue, removeArray) == -1); + }); + }, + last: function(array) { + return $.isArray(array) + ? array[ array.length - 1] + : false + ; + }, + pathToArray: function(pathName) { + if(pathName === undefined) { + pathName = activeTabPath; + } + return typeof pathName == 'string' + ? pathName.split('/') + : [pathName] + ; + }, + arrayToPath: function(pathArray) { + return $.isArray(pathArray) + ? pathArray.join('/') + : false + ; + } + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; + + }; + + // shortcut for tabbed content with no defined navigation + $.tab = function(settings) { + $(window).tab(settings); + }; + + $.fn.tab.settings = { + + name : 'Tab', + verbose : true, + debug : true, + performance : true, + namespace : 'tab', + + // only called first time a tab's content is loaded (when remote source) + onTabInit : function(tabPath, parameterArray, historyEvent) {}, + // called on every load + onTabLoad : function(tabPath, parameterArray, historyEvent) {}, + + templates : { + determineTitle: function(tabArray) {} + }, + + // uses pjax style endpoints fetching content from same url with remote-content headers + auto : false, + + history : false, + path : false, + + context : 'body', + + // max depth a tab can be nested + maxDepth : 25, + // dont load content on first load + ignoreFirstLoad : true, + // load tab content new every tab click + alwaysRefresh : false, + // cache the content requests to pull locally + cache : true, + // settings for api call + apiSettings : false, + + error: { + api : 'You attempted to load content without API module', + noContent : 'The tab you specified is missing a content url.', + method : 'The method you called is not defined', + state : 'The state library has not been initialized', + missingTab : 'Tab cannot be found', + path : 'History enabled, but no path was specified', + recursion : 'Max recursive depth reached' + }, + + metadata : { + tab : 'tab', + loaded : 'loaded', + promise: 'promise' + }, + + className : { + loading : 'loading', + active : 'active' + }, + + selector : { + tabs : '.tab' + } + + }; + +})( jQuery, window , document ); + +/* + * # Semantic - Transition + * http://github.com/jlukic/semantic-ui/ + * + * + * Copyright 2013 Contributors + * Released under the MIT license + * http://opensource.org/licenses/MIT + * + */ + +;(function ( $, window, document, undefined ) { + +$.fn.transition = function() { + var + $allModules = $(this), + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + moduleArguments = arguments, + query = moduleArguments[0], + queryArguments = [].slice.call(arguments, 1), + methodInvoked = (typeof query === 'string'), + + requestAnimationFrame = window.requestAnimationFrame + || window.mozRequestAnimationFrame + || window.webkitRequestAnimationFrame + || window.msRequestAnimationFrame + || function(callback) { setTimeout(callback, 0); }, + + invokedResponse + ; + $allModules + .each(function() { + var + $module = $(this), + element = this, + + // set at run time + settings, + instance, + + error, + className, + metadata, + animationEnd, + animationName, + + namespace, + moduleNamespace, + module + ; + + module = { + + initialize: function() { + // get settings + settings = module.get.settings.apply(element, moduleArguments); + module.verbose('Converted arguments into settings object', settings); + + // set shortcuts + error = settings.error; + className = settings.className; + namespace = settings.namespace; + metadata = settings.metadata; + moduleNamespace = 'module-' + namespace; + + animationEnd = module.get.animationEvent(); + animationName = module.get.animationName(); + + instance = $module.data(moduleNamespace); + + if(instance === undefined) { + module.instantiate(); + } + if(methodInvoked) { + methodInvoked = module.invoke(query); + } + // no internal method was found matching query or query not made + if(methodInvoked === false) { + module.animate(); + } + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, instance) + ; + }, + + destroy: function() { + module.verbose('Destroying previous module for', element); + $module + .removeData(moduleNamespace) + ; + }, + + animate: function(overrideSettings) { + settings = overrideSettings || settings; + module.debug('Preparing animation', settings.animation); + if(module.is.animating()) { + if(settings.queue) { + module.queue(settings.animation); + } + return false; + } + module.save.conditions(); + module.set.duration(settings.duration); + module.set.animating(); + module.repaint(); + $module + .addClass(className.transition) + .addClass(settings.animation) + .one(animationEnd, module.complete) + ; + if(!module.has.direction() && module.can.transition()) { + module.set.direction(); + } + if(!module.can.animate()) { + module.restore.conditions(); + module.error(error.noAnimation); + return false; + } + module.show(); + module.debug('Starting tween', settings.animation, $module.attr('class')); + }, + + queue: function(animation) { + module.debug('Queueing animation of', animation); + instance.queuing = true; + $module + .one(animationEnd, function() { + instance.queuing = false; + module.animate.apply(this, settings); + }) + ; + }, + + complete: function () { + module.verbose('CSS animation complete', settings.animation); + if(!module.is.looping()) { + if($module.hasClass(className.outward)) { + module.restore.conditions(); + module.hide(); + } + else if($module.hasClass(className.inward)) { + module.restore.conditions(); + module.show(); + } + else { + module.restore.conditions(); + } + module.remove.animating(); + } + $.proxy(settings.complete, this)(); + }, + + repaint: function(fakeAssignment) { + module.verbose('Forcing repaint event'); + fakeAssignment = element.offsetWidth; + }, + + has: { + direction: function(animation) { + animation = animation || settings.animation; + if( $module.hasClass(className.inward) || $module.hasClass(className.outward) ) { + return true; + } + } + }, + + set: { + + animating: function() { + $module.addClass(className.animating); + }, + + direction: function() { + if($module.is(':visible')) { + module.debug('Automatically determining the direction of animation', 'Outward'); + $module + .addClass(className.outward) + .removeClass(className.inward) + ; + } + else { + module.debug('Automatically determining the direction of animation', 'Inward'); + $module + .addClass(className.inward) + .removeClass(className.outward) + ; + } + }, + + looping: function() { + module.debug('Transition set to loop'); + $module + .addClass(className.looping) + ; + }, + + duration: function(duration) { + duration = duration || settings.duration; + duration = (typeof duration == 'number') + ? duration + 'ms' + : duration + ; + module.verbose('Setting animation duration', duration); + $module + .css({ + '-webkit-animation-duration': duration, + '-moz-animation-duration': duration, + '-ms-animation-duration': duration, + '-o-animation-duration': duration, + 'animation-duration': duration + }) + ; + } + }, + + save: { + conditions: function() { + module.cache = { + className : $module.attr('class'), + style : $module.attr('style') + }; + module.verbose('Saving original attributes', module.cache); + } + }, + + restore: { + conditions: function() { + if(typeof module.cache === undefined) { + module.error(error.cache); + return false; + } + if(module.cache.className) { + $module.attr('class', module.cache.className); + } + else { + $module.removeAttr('class'); + } + if(module.cache.style) { + $module.attr('style', module.cache.style); + } + else { + $module.removeAttr('style'); + } + if(module.is.looping()) { + module.remove.looping(); + } + module.verbose('Restoring original attributes', module.cache); + } + }, + + remove: { + + animating: function() { + $module.removeClass(className.animating); + }, + + looping: function() { + module.debug('Transitions are no longer looping'); + $module + .removeClass(className.looping) + ; + module.repaint(); + } + + }, + + get: { + + settings: function(animation, duration, complete) { + // single settings object + if($.isPlainObject(animation)) { + return $.extend(true, {}, $.fn.transition.settings, animation); + } + // all arguments provided + else if(typeof complete == 'function') { + return $.extend(true, {}, $.fn.transition.settings, { + animation : animation, + complete : complete, + duration : duration + }); + } + // only duration provided + else if(typeof duration == 'string' || typeof duration == 'number') { + return $.extend(true, {}, $.fn.transition.settings, { + animation : animation, + duration : duration + }); + } + // duration is actually settings object + else if(typeof duration == 'object') { + return $.extend(true, {}, $.fn.transition.settings, duration, { + animation : animation + }); + } + // duration is actually callback + else if(typeof duration == 'function') { + return $.extend(true, {}, $.fn.transition.settings, { + animation : animation, + complete : duration + }); + } + // only animation provided + else { + return $.extend(true, {}, $.fn.transition.settings, { + animation : animation + }); + } + return $.fn.transition.settings; + }, + + animationName: function() { + var + element = document.createElement('div'), + animations = { + 'animation' :'animationName', + 'OAnimation' :'oAnimationName', + 'MozAnimation' :'mozAnimationName', + 'WebkitAnimation' :'webkitAnimationName' + }, + animation + ; + for(animation in animations){ + if( element.style[animation] !== undefined ){ + module.verbose('Determining animation vendor name property', animations[animation]); + return animations[animation]; + } + } + return false; + }, + + animationEvent: function() { + var + element = document.createElement('div'), + animations = { + 'animation' :'animationend', + 'OAnimation' :'oAnimationEnd', + 'MozAnimation' :'mozAnimationEnd', + 'WebkitAnimation' :'webkitAnimationEnd' + }, + animation + ; + for(animation in animations){ + if( element.style[animation] !== undefined ){ + module.verbose('Determining animation vendor end event', animations[animation]); + return animations[animation]; + } + } + return false; + } + + }, + + can: { + animate: function() { + if($module.css(animationName) !== 'none') { + module.debug('CSS definition found'); + return true; + } + else { + module.debug('Unable to find css definition'); + return false; + } + }, + transition: function() { + var + $clone = $('
').addClass( $module.attr('class') ).appendTo($('body')), + currentAnimation = $clone.css(animationName), + inAnimation = $clone.addClass(className.inward).css(animationName) + ; + if(currentAnimation != inAnimation) { + module.debug('In/out transitions exist'); + $clone.remove(); + return true; + } + else { + module.debug('Static animation found'); + $clone.remove(); + return false; + } + } + }, + + is: { + animating: function() { + return $module.hasClass(className.animating); + }, + looping: function() { + return $module.hasClass(className.looping); + }, + visible: function() { + return $module.is(':visible'); + } + }, + + hide: function() { + module.verbose('Hiding element'); + $module + .removeClass(className.visible) + .addClass(className.transition) + .addClass(className.hidden) + ; + }, + show: function() { + module.verbose('Showing element'); + $module + .removeClass(className.hidden) + .addClass(className.transition) + .addClass(className.visible) + ; + }, + + start: function() { + module.verbose('Starting animation'); + $module.removeClass(className.disabled); + }, + + stop: function() { + module.debug('Stopping animation'); + $module.addClass(className.disabled); + }, + + toggle: function() { + module.debug('Toggling play status'); + $module.toggleClass(className.disabled); + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found || false; + } + }; + module.initialize(); + }) + ; + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.transition.settings = { + + // module info + name : 'Transition', + + // debug content outputted to console + debug : true, + + // verbose debug output + verbose : true, + + // performance data output + performance : true, + + // event namespace + namespace : 'transition', + + // animation complete event + complete : function() {}, + + // animation duration + animation : 'fade', + duration : '700ms', + + // queue up animations + queue : true, + + className : { + transition : 'ui transition', + animating : 'animating', + looping : 'looping', + loading : 'loading', + disabled : 'disabled', + hidden : 'hidden', + visible : 'visible', + inward : 'in', + outward : 'out' + }, + + // possible errors + error: { + noAnimation : 'There is no css animation matching the one you specified.', + method : 'The method you called is not defined' + } + +}; + + +})( jQuery, window , document ); + +/* ****************************** + Module - Video + Author: Jack Lukic + + This is a video playlist and video embed plugin which helps + provide helpers for adding embed code for vimeo and youtube and + abstracting event handlers for each library + +****************************** */ + +;(function ($, window, document, undefined) { + +$.fn.video = function(parameters) { + + var + $allModules = $(this), + + settings = ( $.isPlainObject(parameters) ) + ? $.extend(true, {}, $.fn.video.settings, parameters) + : $.fn.video.settings, + + moduleSelector = $allModules.selector || '', + + time = new Date().getTime(), + performance = [], + + query = arguments[0], + methodInvoked = (typeof query == 'string'), + queryArguments = [].slice.call(arguments, 1), + + selector = settings.selector, + className = settings.className, + error = settings.error, + metadata = settings.metadata, + namespace = settings.namespace, + + eventNamespace = '.' + namespace, + moduleNamespace = namespace + '-module', + + invokedResponse + ; + + $allModules + .each(function() { + var + $module = $(this), + $placeholder = $module.find(selector.placeholder), + $playButton = $module.find(selector.playButton), + $embed = $module.find(selector.embed), + + element = this, + instance = $module.data(moduleNamespace), + module + ; + + module = { + + initialize: function() { + module.debug('Initializing video'); + $placeholder + .on('click' + eventNamespace, module.play) + ; + $playButton + .on('click' + eventNamespace, module.play) + ; + module.instantiate(); + }, + + instantiate: function() { + module.verbose('Storing instance of module', module); + instance = module; + $module + .data(moduleNamespace, module) + ; + }, + + destroy: function() { + module.verbose('Destroying previous instance of video'); + $module + .removeData(moduleNamespace) + .off(eventNamespace) + ; + }, + + // sets new video + change: function(source, id, url) { + module.debug('Changing video to ', source, id, url); + $module + .data(metadata.source, source) + .data(metadata.id, id) + .data(metadata.url, url) + ; + settings.onChange(); + }, + + // clears video embed + reset: function() { + module.debug('Clearing video embed and showing placeholder'); + $module + .removeClass(className.active) + ; + $embed + .html(' ') + ; + $placeholder + .show() + ; + settings.onReset(); + }, + + // plays current video + play: function() { + module.debug('Playing video'); + var + source = $module.data(metadata.source) || false, + url = $module.data(metadata.url) || false, + id = $module.data(metadata.id) || false + ; + $embed + .html( module.generate.html(source, id, url) ) + ; + $module + .addClass(className.active) + ; + settings.onPlay(); + }, + + generate: { + // generates iframe html + html: function(source, id, url) { + module.debug('Generating embed html'); + var + width = (settings.width == 'auto') + ? $module.width() + : settings.width, + height = (settings.height == 'auto') + ? $module.height() + : settings.height, + html + ; + if(source && id) { + if(source == 'vimeo') { + html = '' + + '' + ; + } + else if(source == 'youtube') { + html = '' + + '' + ; + } + } + else if(url) { + html = '' + + '' + ; + } + else { + module.error(error.noVideo); + } + return html; + }, + + // generate url parameters + url: function(source) { + var + api = (settings.api) + ? 1 + : 0, + autoplay = (settings.autoplay) + ? 1 + : 0, + hd = (settings.hd) + ? 1 + : 0, + showUI = (settings.showUI) + ? 1 + : 0, + // opposite used for some params + hideUI = !(settings.showUI) + ? 1 + : 0, + url = '' + ; + if(source == 'vimeo') { + url = '' + + 'api=' + api + + '&title=' + showUI + + '&byline=' + showUI + + '&portrait=' + showUI + + '&autoplay=' + autoplay + ; + if(settings.color) { + url += '&color=' + settings.color; + } + } + if(source == 'ustream') { + url = '' + + 'autoplay=' + autoplay + ; + if(settings.color) { + url += '&color=' + settings.color; + } + } + else if(source == 'youtube') { + url = '' + + 'enablejsapi=' + api + + '&autoplay=' + autoplay + + '&autohide=' + hideUI + + '&hq=' + hd + + '&modestbranding=1' + ; + if(settings.color) { + url += '&color=' + settings.color; + } + } + return url; + } + }, + + setting: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, settings, name); + } + else { + settings[name] = value; + } + } + else { + return settings[name]; + } + }, + internal: function(name, value) { + if(value !== undefined) { + if( $.isPlainObject(name) ) { + $.extend(true, module, name); + } + else { + module[name] = value; + } + } + else { + return module[name]; + } + }, + debug: function() { + if(settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.debug.apply(console, arguments); + } + } + }, + verbose: function() { + if(settings.verbose && settings.debug) { + if(settings.performance) { + module.performance.log(arguments); + } + else { + module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); + module.verbose.apply(console, arguments); + } + } + }, + error: function() { + module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); + module.error.apply(console, arguments); + }, + performance: { + log: function(message) { + var + currentTime, + executionTime, + previousTime + ; + if(settings.performance) { + currentTime = new Date().getTime(); + previousTime = time || currentTime; + executionTime = currentTime - previousTime; + time = currentTime; + performance.push({ + 'Element' : element, + 'Name' : message[0], + 'Arguments' : [].slice.call(message, 1) || '', + 'Execution Time' : executionTime + }); + } + clearTimeout(module.performance.timer); + module.performance.timer = setTimeout(module.performance.display, 100); + }, + display: function() { + var + title = settings.name + ':', + totalTime = 0 + ; + time = false; + clearTimeout(module.performance.timer); + $.each(performance, function(index, data) { + totalTime += data['Execution Time']; + }); + title += ' ' + totalTime + 'ms'; + if(moduleSelector) { + title += ' \'' + moduleSelector + '\''; + } + if($allModules.size() > 1) { + title += ' ' + '(' + $allModules.size() + ')'; + } + if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { + console.groupCollapsed(title); + if(console.table) { + console.table(performance); + } + else { + $.each(performance, function(index, data) { + console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); + }); + } + console.groupEnd(); + } + performance = []; + } + }, + invoke: function(query, passedArguments, context) { + var + maxDepth, + found, + response + ; + passedArguments = passedArguments || queryArguments; + context = element || context; + if(typeof query == 'string' && instance !== undefined) { + query = query.split(/[\. ]/); + maxDepth = query.length - 1; + $.each(query, function(depth, value) { + var camelCaseValue = (depth != maxDepth) + ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) + : query + ; + if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) { + instance = instance[value]; + } + else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) { + instance = instance[camelCaseValue]; + } + else if( instance[value] !== undefined ) { + found = instance[value]; + return false; + } + else if( instance[camelCaseValue] !== undefined ) { + found = instance[camelCaseValue]; + return false; + } + else { + module.error(error.method); + return false; + } + }); + } + if ( $.isFunction( found ) ) { + response = found.apply(context, passedArguments); + } + else if(found !== undefined) { + response = found; + } + if($.isArray(invokedResponse)) { + invokedResponse.push(response); + } + else if(typeof invokedResponse == 'string') { + invokedResponse = [invokedResponse, response]; + } + else if(response !== undefined) { + invokedResponse = response; + } + return found; + } + }; + + if(methodInvoked) { + if(instance === undefined) { + module.initialize(); + } + module.invoke(query); + } + else { + if(instance !== undefined) { + module.destroy(); + } + module.initialize(); + } + }) + ; + return (invokedResponse !== undefined) + ? invokedResponse + : this + ; +}; + +$.fn.video.settings = { + + name : 'Video', + namespace : 'video', + + debug : true, + verbose : true, + performance : true, + + metadata : { + source : 'source', + id : 'id', + url : 'url' + }, + + onPlay : function(){}, + onReset : function(){}, + onChange : function(){}, + + // callbacks not coded yet (needs to use jsapi) + onPause : function() {}, + onStop : function() {}, + + width : 'auto', + height : 'auto', + + autoplay : false, + color : '#442359', + hd : true, + showUI : false, + api : true, + + error : { + noVideo : 'No video specified', + method : 'The method you called is not defined' + }, + + className : { + active : 'active' + }, + + selector : { + embed : '.embed', + placeholder : '.placeholder', + playButton : '.play' + } +}; + + +})( jQuery, window , document ); diff --git a/node/src/files/build/semantic.zip b/node/src/files/build/semantic.zip index 7d0857778..89844b35b 100644 Binary files a/node/src/files/build/semantic.zip and b/node/src/files/build/semantic.zip differ