From b646e2302ddc9400c17cf30064bd97f1a0904c90 Mon Sep 17 00:00:00 2001 From: Emad Ibrahim Date: Sat, 28 Sep 2013 00:00:31 -0400 Subject: [PATCH] added semantic.js to build using concat in grunt --- build/packaged/javascript/semantic.js | 11048 ++++++++++++++++ node/Gruntfile.js | 6 +- .../build/packaged/javascript/semantic.js | 11048 ++++++++++++++++ node/src/files/build/semantic.zip | Bin 2179171 -> 2245586 bytes 4 files changed, 22101 insertions(+), 1 deletion(-) create mode 100644 build/packaged/javascript/semantic.js create mode 100644 node/src/files/build/packaged/javascript/semantic.js 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 7d0857778e0b16a10e63aa198dcc3268cc516ec0..89844b35b3f49026fe0c3336b93ff18c253d59d0 100644 GIT binary patch delta 75067 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 agKwVz1wSQFVo5Wk89F`$L4Sb{g#QDC?7~9; delta 8001 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