Browse Source

adds inline form validation, default validation types, validation on input change

Former-commit-id: b5162eb7a2295e79510529ce81dc5bfb48b01275
Former-commit-id: 55525c13de1bd1e7a781a71dc75d70ba74b302a6
beta
Jack Lukic 12 years ago
parent
commit
b41d6d96f4
  1. 2
      build/minified/collections/form.min.css
  2. 2
      build/minified/collections/menu.min.css
  3. 2
      build/minified/elements/label.min.css
  4. 458
      build/minified/modules/behavior/form.js
  5. 2
      build/minified/modules/behavior/form.min.js
  6. 2
      build/minified/modules/behavior/state.min.js
  7. 2
      build/minified/modules/chat.min.js
  8. 2
      build/minified/modules/dropdown.js
  9. 2
      build/minified/modules/dropdown.min.js
  10. 2
      build/minified/modules/modal.min.js
  11. 2
      build/minified/modules/nag.min.js
  12. 2
      build/minified/modules/popup.min.js
  13. 2
      build/minified/modules/search.min.js
  14. 2
      build/minified/modules/shape.min.js
  15. 2
      build/minified/modules/star.min.js
  16. 2
      build/minified/modules/tab.min.js
  17. 2
      build/minified/modules/video.min.js
  18. 458
      build/packaged/modules/behavior/form.js
  19. 2
      build/packaged/modules/dropdown.js
  20. 2
      build/packaged/semantic.min.css.REMOVED.git-id
  21. 2
      build/packaged/semantic.min.js.REMOVED.git-id
  22. 17
      build/uncompressed/collections/form.css
  23. 9
      build/uncompressed/collections/menu.css
  24. 10
      build/uncompressed/elements/label.css
  25. 458
      build/uncompressed/modules/behavior/form.js
  26. 2
      build/uncompressed/modules/dropdown.js
  27. 85
      node/npm-debug.log
  28. 6
      node/src/documents/collections/form.html
  29. 1
      node/src/documents/collections/menu.html
  30. 17
      node/src/files/components/semantic/collections/form.css
  31. 9
      node/src/files/components/semantic/collections/menu.css
  32. 10
      node/src/files/components/semantic/elements/label.css
  33. 458
      node/src/files/components/semantic/modules/behavior/form.js
  34. 2
      node/src/files/components/semantic/modules/dropdown.js
  35. 3
      node/src/files/javascript/dropdown.js
  36. 19
      src/collections/form.less
  37. 9
      src/collections/menu.less
  38. 10
      src/elements/label.less
  39. 104
      src/modules/behavior/default-text.js
  40. 458
      src/modules/behavior/form.js
  41. 2
      src/modules/dropdown.js

2
build/minified/collections/form.min.css

File diff suppressed because one or more lines are too long

2
build/minified/collections/menu.min.css

File diff suppressed because one or more lines are too long

2
build/minified/elements/label.min.css

File diff suppressed because one or more lines are too long

458
build/minified/modules/behavior/form.js

@ -3,7 +3,7 @@
Author: Jack Lukic Author: Jack Lukic
Notes: First Commit April 08, 2012 Notes: First Commit April 08, 2012
Refactored Feb 22, 2012 Refactored May 28, 2013
Allows you to validate forms based on a form validation object Allows you to validate forms based on a form validation object
Form validation objects are bound by either data-validate="" metadata, or form id or name tags Form validation objects are bound by either data-validate="" metadata, or form id or name tags
@ -12,32 +12,42 @@
;(function ( $, window, document, undefined ) { ;(function ( $, window, document, undefined ) {
$.fn.validateForm = function(fields, parameters) { $.fn.form = function(fields, parameters) {
var var
$allModules = $(this), $allModules = $(this),
settings = $.extend(true, {}, $.fn.validateForm.settings, parameters), settings = $.extend(true, {}, $.fn.form.settings, parameters),
// make arguments available validation = $.extend({}, $.fn.form.settings.defaults, fields),
eventNamespace = '.' + settings.namespace,
moduleNamespace = 'module-' + settings.namespace,
selector = $allModules.selector || '',
time = new Date().getTime(),
performance = [],
query = arguments[0], query = arguments[0],
passedArguments = [].slice.call(arguments, 1), methodInvoked = (typeof query == 'string'),
queryArguments = [].slice.call(arguments, 1),
invokedResponse invokedResponse
; ;
$allModules $allModules
.each(function() { .each(function() {
var var
$module = $(this), $module = $(this),
$group = $(this).find(settings.selector.group),
$field = $(this).find(settings.selector.field), $field = $(this).find(settings.selector.field),
$errorPrompt = $(this).find(settings.selector.prompt), $group = $(this).find(settings.selector.group),
$message = $(this).find(settings.selector.message),
$prompt = $(this).find(settings.selector.prompt),
$submit = $(this).find(settings.selector.submit),
formErrors = [], formErrors = [],
selector = $module.selector || '',
element = this, element = this,
instance = $module.data('module-' + settings.namespace), instance = $module.data('module-' + settings.namespace),
methodInvoked = (typeof query == 'string'),
namespace = settings.namespace, namespace = settings.namespace,
selector = settings.selector,
metadata = settings.metadata, metadata = settings.metadata,
className = settings.className, className = settings.className,
errors = settings.errors, errors = settings.errors,
@ -48,21 +58,20 @@ $.fn.validateForm = function(fields, parameters) {
initialize: function() { initialize: function() {
module.verbose('Initializing form validation'); module.verbose('Initializing form validation');
if(fields !== undefined || !$.isEmptyObject(fields) ) { if(settings.keyboardShortcuts) {
// add default text if set $field
if($.fn.defaultText !== undefined) { .on('keydown' + eventNamespace, module.event.field.keydown)
$.each(fields, function(fieldName, field) { ;
module.field.add.defaultText(field);
});
} }
// attach event handler
$module $module
.on('submit.' + namespace, module.validate.form) .on('submit' + eventNamespace, module.validate.form)
;
$field
.on('change' + eventNamespace, module.event.field.change)
;
$submit
.on('click' + eventNamespace, module.submit)
; ;
}
else {
module.error(errors.noFields, $module);
}
}, },
destroy: function() { destroy: function() {
@ -71,11 +80,66 @@ $.fn.validateForm = function(fields, parameters) {
; ;
}, },
refresh: function() {
$field = $module.find(selector.field);
},
submit: function() {
module.verbose('Submitting form', $module);
$module.submit();
},
event: {
field: { field: {
find: function(identifier) { keydown: function(event) {
var var
$field = $module.find(settings.selector.field) $field = $(this),
key = event.which,
keyCode = {
enter : 13,
escape : 27
}
; ;
if( key == keyCode.escape) {
module.verbose('Escape key pressed blurring field');
$field.blur();
}
if( 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();
},
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: {
field: function(identifier) {
if( $field.filter('#' + identifier).size() > 0 ) { if( $field.filter('#' + identifier).size() > 0 ) {
return $field.filter('#' + identifier); return $field.filter('#' + identifier);
} }
@ -87,54 +151,67 @@ $.fn.validateForm = function(fields, parameters) {
} }
return $('<input/>'); return $('<input/>');
}, },
add: { validation: function($field) {
defaultText: function(field) {
var var
$field = module.field.find(field.identifier) rules
; ;
if(field.defaultText !== undefined) { $.each(validation, function(fieldName, field) {
$field.defaultText(field.defaultText); if( module.get.field(field.identifier).get(0) == $field.get(0) ) {
rules = field;
}
});
return rules || false;
} }
}, },
error: function(field, errors) {
add: {
prompt: function(field, errors) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
$errorGroup = $field.closest($group), $fieldGroup = $field.closest($group),
$errorPrompt = $group.find($errorPrompt), $prompt = $fieldGroup.find(selector.prompt),
promptExists = ($errorPrompt.size() !== 0) promptExists = ($prompt.size() !== 0)
; ;
$errorGroup module.verbose('Adding inline validation prompt');
$fieldGroup
.addClass(className.error) .addClass(className.error)
; ;
if(settings.inlineError) { if(settings.inlineError) {
// create message container on first invalid validation attempt
if(!promptExists) { if(!promptExists) {
$errorPrompt = $('<div />') $prompt = settings.templates.prompt(errors);
.addClass(className.prompt) $prompt
.insertBefore($field) .appendTo($fieldGroup)
.hide()
; ;
} }
// add prompt message $prompt
$errorPrompt
.html(errors[0]) .html(errors[0])
.fadeIn(settings.animateSpeed)
; ;
if($prompt.is(':not(:visible)')) {
$prompt.fadeIn(200);
}
} }
},
errors: function(errors) {
module.debug('Adding form error messages', errors);
$message
.html( settings.templates.error(errors) )
;
} }
}, },
remove: { remove: {
error: function(field) { prompt: function(field) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
$errorGroup = $field.closest($group), $fieldGroup = $field.closest($group),
$errorPrompt = $group.find($errorPrompt) $prompt = $group.find($prompt)
; ;
$errorGroup $fieldGroup
.removeClass(className.error) .removeClass(className.error)
; ;
if(settings.inlineError) { if(settings.inlineError) {
$errorPrompt.hide(); $prompt.hide();
}
} }
} }
}, },
@ -147,28 +224,32 @@ $.fn.validateForm = function(fields, parameters) {
; ;
// reset errors // reset errors
formErrors = []; formErrors = [];
$.each(fields, function(fieldName, field){ $.each(validation, function(fieldName, field){
// form is invalid after first bad field, but keep checking
if( !( module.validate.field(field) ) ) { if( !( module.validate.field(field) ) ) {
allValid = false; allValid = false;
} }
}); });
// Evaluate form callbacks if(allValid) {
return (allValid) $module.removeClass(className.error);
? $.proxy(settings.onSuccess, this)(event) $.proxy(settings.onSuccess, this)(event);
: $.proxy(settings.onFailure, this)(formErrors) }
; else {
$module.addClass(className.error);
if(!settings.inlineError) {
module.add.errors(formErrors);
}
$.proxy(settings.onFailure, this)(formErrors);
}
}, },
// takes a validation object and returns whether field passes validation // takes a validation object and returns whether field passes validation
field: function(field) { field: function(field) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
fieldValid = true, fieldValid = true,
fieldErrors = [] fieldErrors = []
; ;
if(field.rules !== undefined) { if(field.rules !== undefined) {
// iterate over all validation types for a certain field
$.each(field.rules, function(index, rule) { $.each(field.rules, function(index, rule) {
if( !( module.validate.rule(field, rule) ) ) { if( !( module.validate.rule(field, rule) ) ) {
module.debug('Field is invalid', field.identifier, rule.type); module.debug('Field is invalid', field.identifier, rule.type);
@ -178,12 +259,12 @@ $.fn.validateForm = function(fields, parameters) {
}); });
} }
if(fieldValid) { if(fieldValid) {
module.field.remove.error(field, fieldErrors); module.remove.prompt(field, fieldErrors);
settings.onValid($field); $.proxy(settings.onValid, $field)();
} }
else { else {
formErrors = formErrors.concat(fieldErrors); formErrors = formErrors.concat(fieldErrors);
module.field.add.error(field, fieldErrors); module.add.prompt(field, fieldErrors);
$.proxy(settings.onInvalid, $field)(fieldErrors); $.proxy(settings.onInvalid, $field)(fieldErrors);
return false; return false;
} }
@ -193,14 +274,9 @@ $.fn.validateForm = function(fields, parameters) {
// takes validation rule and returns whether field passes rule // takes validation rule and returns whether field passes rule
rule: function(field, validation) { rule: function(field, validation) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
type = validation.type, type = validation.type,
defaultText = (field.defaultText !== undefined) value = $field.val(),
? field.defaultText
: false,
value = ($field.val() == defaultText)
? ''
: $field.val(),
bracketRegExp = /\[(.*?)\]/i, bracketRegExp = /\[(.*?)\]/i,
bracket = bracketRegExp.exec(type), bracket = bracketRegExp.exec(type),
@ -225,51 +301,104 @@ $.fn.validateForm = function(fields, parameters) {
} }
}, },
/* standard module */
setting: function(name, value) { setting: function(name, value) {
if(value === undefined) { if(value !== undefined) {
return settings[name]; if( $.isPlainObject(name) ) {
$.extend(true, settings, name);
} }
else {
settings[name] = value; settings[name] = value;
}
}
else {
return settings[name];
}
}, },
verbose: function() { internal: function(name, value) {
if(settings.verbose) { if(value !== undefined) {
module.debug.apply(this, arguments); if( $.isPlainObject(name) ) {
$.extend(true, module, name);
}
else {
module[name] = value;
}
}
else {
return module[name];
} }
}, },
debug: function() { debug: function() {
var
output = [],
message = settings.moduleName + ': ' + arguments[0],
variables = [].slice.call( arguments, 1 ),
log = console.info || console.log || function(){}
;
log = Function.prototype.bind.call(log, console);
if(settings.debug) { if(settings.debug) {
output.push(message); module.performance.log(arguments[0]);
log.apply(console, output.concat(variables) ); module.debug = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
}
},
verbose: function() {
if(settings.verbose && settings.debug) {
module.performance.log(arguments[0]);
module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
} }
}, },
error: function() { error: function() {
module.error = Function.prototype.bind.call(console.log, console, settings.moduleName + ':');
},
performance: {
log: function(message) {
var var
output = [], currentTime,
errorMessage = settings.moduleName + ': ' + arguments[0], executionTime,
variables = [].slice.call( arguments, 1 ), previousTime
log = console.warn || console.log || function(){}
; ;
log = Function.prototype.bind.call(log, console); if(settings.performance) {
if(settings.debug) { currentTime = new Date().getTime();
output.push(errorMessage); previousTime = time || currentTime,
output.concat(variables); executionTime = currentTime - previousTime;
log.apply(console, output.concat(variables) ); time = currentTime;
performance.push({
'Element' : element,
'Name' : message,
'Execution Time' : executionTime
});
clearTimeout(module.performance.timer);
module.performance.timer = setTimeout(module.performance.display, 100);
}
},
display: function() {
var
title = settings.moduleName,
caption = settings.moduleName + ': ' + selector + '(' + $allModules.size() + ' elements)',
totalExecutionTime = 0
;
if(selector) {
title += 'Performance (' + selector + ')';
}
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
console.groupCollapsed(title);
if(console.table) {
$.each(performance, function(index, data) {
totalExecutionTime += data['Execution Time'];
});
console.table(performance);
}
else {
$.each(performance, function(index, data) {
totalExecutionTime += data['Execution Time'];
});
}
console.log('Total Execution Time:', totalExecutionTime +'ms');
console.groupEnd();
performance = [];
time = false;
}
} }
}, },
invoke: function(query, context, passedArguments) { invoke: function(query, passedArguments, context) {
var var
maxDepth, maxDepth,
found found
; ;
passedArguments = passedArguments || [].slice.call( arguments, 2 ); passedArguments = passedArguments || queryArguments;
context = element || context;
if(typeof query == 'string' && instance !== undefined) { if(typeof query == 'string' && instance !== undefined) {
query = query.split('.'); query = query.split('.');
maxDepth = query.length - 1; maxDepth = query.length - 1;
@ -287,42 +416,47 @@ $.fn.validateForm = function(fields, parameters) {
}); });
} }
if ( $.isFunction( found ) ) { if ( $.isFunction( found ) ) {
module.verbose('Executing invoked function', found);
return found.apply(context, passedArguments); return found.apply(context, passedArguments);
} }
// return retrieved variable or chain return found || false;
return found;
} }
}; };
// check for invoking internal method
if(methodInvoked) { if(methodInvoked) {
invokedResponse = module.invoke(query, this, passedArguments); if(instance === undefined) {
module.initialize();
}
invokedResponse = module.invoke(query);
} }
// otherwise initialize
else { else {
if(instance !== undefined) {
module.destroy();
}
module.initialize(); module.initialize();
} }
}) })
; ;
// chain or return queried method return (invokedResponse)
return (invokedResponse !== undefined)
? invokedResponse ? invokedResponse
: this : this
; ;
}; };
$.fn.validateForm.settings = { $.fn.form.settings = {
// module info // module info
moduleName : 'Validate Form Module', moduleName : 'Validate Form Module',
debug : true, debug : true,
verbose : false, verbose : true,
namespace : 'validate', namespace : 'validate',
keyboardShortcuts : true,
on : 'change',
animateSpeed : 150, animateSpeed : 150,
inlineError : false, inlineError : false,
onValid : function() {}, onValid : function() {},
onInvalid : function() {}, onInvalid : function() {},
onSuccess : function() { return true; }, onSuccess : function() { return true; },
@ -332,22 +466,122 @@ $.fn.validateForm.settings = {
validate: 'validate' validate: 'validate'
}, },
// errors
errors: {
method : 'The method you called is not defined.',
noFields : 'No validation object specified.'
},
selector : { selector : {
message : '.error.message',
field : 'input, textarea, select',
group : '.field', group : '.field',
input : 'input',
prompt : '.prompt', prompt : '.prompt',
field : 'input, textarea, select' submit : '.submit'
}, },
className : { className : {
error : 'error', error : 'error',
prompt : 'prompt' down : 'down',
label : 'ui label prompt'
},
// errors
errors: {
method : 'The method you called is not defined.'
},
defaults: {
firstName: {
identifier : 'first-name',
rules: [
{
type : 'empty',
prompt : 'Please enter your first name'
}
]
},
lastName: {
identifier : 'last-name',
rules: [
{
type : 'empty',
prompt : 'Please enter your last name'
}
]
},
username: {
identifier : 'username',
rules: [
{
type : 'empty',
prompt : 'Please enter a username'
}
]
},
email: {
identifier : 'email',
rules: [
{
type : 'empty',
prompt : 'Please enter your email'
},
{
type : 'email',
prompt : 'Please enter a valid email'
}
]
},
password: {
identifier : 'password',
rules: [
{
type : 'empty',
prompt : 'Please enter a password'
},
{
type : 'length[6]',
prompt : 'Your password must be at least 6 characters'
}
]
},
passwordConfirm: {
identifier : 'password-confirm',
rules: [
{
type : 'empty',
prompt : 'Please confirm your password'
},
{
identifier : 'password-confirm',
type : 'match[password]',
prompt : 'Please verify password matches'
}
]
},
terms: {
identifier : 'terms',
rules: [
{
type : 'checked',
prompt : 'You must agree to the terms and conditions'
}
]
}
},
templates: {
error: function(errors) {
var
html = '<ul class="list">'
;
$.each(errors, function(index, value) {
html += '<li>' + value + '</li>';
});
html += '</ul>';
return $(html);
},
prompt: function(errors) {
return $('<div/>')
.addClass('ui red pointing prompt label')
.html(errors[0])
;
}
}, },
rules: { rules: {

2
build/minified/modules/behavior/form.min.js

File diff suppressed because one or more lines are too long

2
build/minified/modules/behavior/state.min.js

File diff suppressed because one or more lines are too long

2
build/minified/modules/chat.min.js

File diff suppressed because one or more lines are too long

2
build/minified/modules/dropdown.js

@ -394,7 +394,7 @@ $.fn.dropdown = function(parameters) {
debug: function() { debug: function() {
if(settings.debug) { if(settings.debug) {
module.performance.log(arguments[0]); module.performance.log(arguments[0]);
module.debug = Function.prototype.bind.call(console.log, console, settings.moduleName + ':'); module.debug = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
} }
}, },
verbose: function() { verbose: function() {

2
build/minified/modules/dropdown.min.js

File diff suppressed because one or more lines are too long

2
build/minified/modules/modal.min.js

@ -1 +1 @@
(function(e,t,n,o){e.dimScreen=function(t){var n="function"==typeof t?e.extend({},e.fn.modal.settings,{dim:t}):e.extend({},e.fn.modal.settings,t),o=e(n.context),i=o.children(n.selector.dimmer),a=i.size()>0,s=i.css("opacity");return a||(i=e("<div/>").attr("id","dimmer").html('<div class="content"></div>'),o.append(i)),s!=n.opacity&&(i.one("click",function(){n.unDim(),e.unDimScreen()}),0===n.duration?i.css({visibility:"visible"}).find(".content").css({opacity:n.opacity,visibility:"visible"}):i.css({visibility:"visible"}).find(".content").css({opacity:0,visibility:"visible"}).fadeTo(n.duration,n.opacity,n.dim)),this},e.unDimScreen=function(t){var n="function"==typeof t?e.extend({},e.fn.modal.settings,{unDim:t}):e.extend({},e.fn.modal.settings,t),o=e(n.context),i=o.children(n.selector.dimmer),a=i.size()>0;return a&&(n.unDim(),0===n.duration?i.css({visibility:"hidden"}).remove():i.find(".content").fadeTo(n.duration,0,function(){i.remove()})),this},e.fn.modal=function(i){var a,s=e.extend(!0,{},e.fn.modal.settings,i),r=arguments[0],c=[].slice.call(arguments,1);return e(this).each(function(){var i,l=e(this),u=l.find(s.selector.closeButton),d=(e(s.context).find(s.selector.dimmer),e(s.context).children(s.selector.modal)),f=d.not(l),m=l.data("module-"+s.namespace),p="string"==typeof r,g=(s.className,s.namespace);i={initialize:function(){l.on("modalShow."+g,i.show).on("modalHide."+g,i.hide).data("module-"+g,i)},show:function(){var i=l.outerHeight(),a=e(t).height(),r=i>a,c=r?"absolute":"fixed",d=r?"0":"50%",m=r?a/8:-((i-s.closeSpacing)/2),p="absolute"==l.css("position")?m+e(t).prop("pageYOffset"):m,h=p+s.animationOffset;e.fn.popIn!==o?l.addClass(c).css({display:"block",opacity:0,top:d,marginTop:p+"px"}).popIn():l.addClass(c).css({display:"block",opacity:0,top:d,marginTop:h+"px"}).animate({opacity:1,marginTop:p+"px"},s.duration+300,s.easing),f.is(":visible")&&f.filter(":visible").hide(),e.dimScreen({context:s.context,duration:0,dim:function(){e(n).on("keyup."+g,function(e){var t=e.which,n=27;switch(t){case n:l.trigger("modalHide"),e.preventDefault()}}),u.one("click",function(){l.trigger("modalHide")}),s.dim()},unDim:function(){l.trigger("modalHide"),u.unbind("click")}})},hide:function(){e(n).off("keyup."+g),e.unDimScreen({duration:0,unDim:function(){l.popOut(200),s.unDim()}})},setting:function(e,t){return t===o?s[e]:(s[e]=t,o)},debug:function(){var e=[],t=s.moduleName+": "+arguments[0],n=[].slice.call(arguments,1),o=console.info||console.log||function(){};s.debug&&(e.push(t),o.apply(console,e.concat(n)))},error:function(){var e=[],t=s.moduleName+": "+arguments[0],n=[].slice.call(arguments,1),o=console.warn||console.log||function(){};s.debug&&(e.push(t),e.concat(n),o.apply(console,e.concat(n)))},invoke:function(t,n,a){var r,c;return a=a||[].slice.call(arguments,2),"string"==typeof t&&m!==o&&(t=t.split("."),r=t.length-1,e.each(t,function(t,n){return e.isPlainObject(m[n])&&t!=r?(m=m[n],!0):m[n]!==o?(c=m[n],!0):(i.error(s.errors.method),!1)})),e.isFunction(c)?c.apply(n,a):c}},p?a=i.invoke(r,this,c):i.initialize()}),a!==o?a:this},e.fn.modal.settings={moduleName:"Modal",debug:!1,namespace:"modal",errors:{method:"The method you called is not defined"},dim:function(){},unDim:function(){},hide:function(){},show:function(){},context:"body",opacity:.8,closeSpacing:25,animationOffset:15,duration:400,easing:"easeOutExpo",selector:{dimmer:"#dimmer",modal:".modal",closeButton:".close"}}})(jQuery,window,document); (function(e,t,n,o){e.dimScreen=function(t){var n="function"==typeof t?e.extend({},e.fn.modal.settings,{dim:t}):e.extend({},e.fn.modal.settings,t),o=e(n.context),i=o.children(n.selector.dimmer),a=i.size()>0,r=i.css("opacity");return a||(i=e("<div/>").attr("id","dimmer").html('<div class="content"></div>'),o.append(i)),r!=n.opacity&&(i.one("click",function(){n.unDim(),e.unDimScreen()}),0===n.duration?i.css({visibility:"visible"}).find(".content").css({opacity:n.opacity,visibility:"visible"}):i.css({visibility:"visible"}).find(".content").css({opacity:0,visibility:"visible"}).fadeTo(n.duration,n.opacity,n.dim)),this},e.unDimScreen=function(t){var n="function"==typeof t?e.extend({},e.fn.modal.settings,{unDim:t}):e.extend({},e.fn.modal.settings,t),o=e(n.context),i=o.children(n.selector.dimmer),a=i.size()>0;return a&&(n.unDim(),0===n.duration?i.css({visibility:"hidden"}).remove():i.find(".content").fadeTo(n.duration,0,function(){i.remove()})),this},e.fn.modal=function(i){var a,r=e.extend(!0,{},e.fn.modal.settings,i),s=arguments[0],c=[].slice.call(arguments,1);return e(this).each(function(){var i,l=e(this),u=l.find(r.selector.closeButton),d=(e(r.context).find(r.selector.dimmer),e(r.context).children(r.selector.modal)),m=d.not(l),f=l.data("module-"+r.namespace),p="string"==typeof s,g=(r.className,r.namespace);i={initialize:function(){l.on("modalShow."+g,i.show).on("modalHide."+g,i.hide).data("module-"+g,i)},show:function(){var i=l.outerHeight(),a=e(t).height(),s=i>a,c=s?"absolute":"fixed",d=s?"0":"50%",f=s?a/8:-((i-r.closeSpacing)/2),p="absolute"==l.css("position")?f+e(t).prop("pageYOffset"):f,h=p+r.animationOffset;e.fn.popIn!==o?l.addClass(c).css({display:"block",opacity:0,top:d,marginTop:p+"px"}).popIn():l.addClass(c).css({display:"block",opacity:0,top:d,marginTop:h+"px"}).animate({opacity:1,marginTop:p+"px"},r.duration+300,r.easing),m.is(":visible")&&m.filter(":visible").hide(),e.dimScreen({context:r.context,duration:0,dim:function(){e(n).on("keyup."+g,function(e){var t=e.which,n=27;switch(t){case n:l.trigger("modalHide"),e.preventDefault()}}),u.one("click",function(){l.trigger("modalHide")}),r.dim()},unDim:function(){l.trigger("modalHide"),u.unbind("click")}})},hide:function(){e(n).off("keyup."+g),e.unDimScreen({duration:0,unDim:function(){l.popOut(200),r.unDim()}})},setting:function(e,t){return t===o?r[e]:(r[e]=t,o)},debug:function(){var e=[],t=r.moduleName+": "+arguments[0],n=[].slice.call(arguments,1),o=console.info||console.log||function(){};r.debug&&(e.push(t),o.apply(console,e.concat(n)))},error:function(){var e=[],t=r.moduleName+": "+arguments[0],n=[].slice.call(arguments,1),o=console.warn||console.log||function(){};r.debug&&(e.push(t),e.concat(n),o.apply(console,e.concat(n)))},invoke:function(t,n,a){var s,c;return a=a||[].slice.call(arguments,2),"string"==typeof t&&f!==o&&(t=t.split("."),s=t.length-1,e.each(t,function(t,n){return e.isPlainObject(f[n])&&t!=s?(f=f[n],!0):f[n]!==o?(c=f[n],!0):(i.error(r.errors.method),!1)})),e.isFunction(c)?c.apply(n,a):c}},p?a=i.invoke(s,this,c):i.initialize()}),a!==o?a:this},e.fn.modal.settings={moduleName:"Modal",debug:!1,namespace:"modal",errors:{method:"The method you called is not defined"},dim:function(){},unDim:function(){},hide:function(){},show:function(){},context:"body",opacity:.8,closeSpacing:25,animationOffset:15,duration:400,easing:"easeOutExpo",selector:{dimmer:"#dimmer",modal:".modal",closeButton:".close"}}})(jQuery,window,document);

2
build/minified/modules/nag.min.js

@ -1 +1 @@
(function(e,t,n,o){e.fn.nag=function(n){var i=e.extend(!0,{},e.fn.nag.settings,n),a=arguments||!1;return e(this).each(function(){var n,s,r,c,l,u,d,f,m,p=e(this),g=p.find(i.selector.close),h=e(i.context),v=p.data("module"),b=i.className,y=t.requestAnimationFrame||t.mozRequestAnimationFrame||t.webkitRequestAnimationFrame||t.msRequestAnimationFrame||function(e){setTimeout(e,0)};return m={initialize:function(){n=p.offset(),s=p.outerHeight(),r=h.outerWidth(),c=h.outerHeight(),l=h.offset(),p.data("module",m),g.on("mouseenter mouseleave",m.event.hover).on("click",m.dismiss),i.context==t&&"fixed"==i.position&&p.addClass(b.fixed),i.sticky&&("absolute"==i.position?h.on("scroll resize",m.event.scroll):e(t).on("scroll resize",m.event.scroll),e.proxy(m.event.scroll,this)()),i.followLink&&p.on("mouseenter mouseleave",m.event.hover).on("click",m.followLink),i.displayTime>0&&setTimeout(m.hide,i.displayTime),m.should.show()?p.is(":visible")||m.show():m.hide()},refresh:function(){n=p.offset(),s=p.outerHeight(),r=h.outerWidth(),c=h.outerHeight(),l=h.offset()},show:function(){e.fn.popIn!==o?p.popIn(i.duration):p.fadeIn(i.duration,i.easing)},hide:function(){p.fadeOut(i.duration,i.easing)},stick:function(){if(m.refresh(),"fixed"==i.position){var n=e(t).prop("pageYOffset")||e(t).scrollTop(),o=p.hasClass(b.bottom)?l.top+(c-s)-n:l.top-n;p.css({position:"fixed",top:o,left:l.left,width:r-i.scrollBarWidth})}else p.css({top:d})},unStick:function(){p.css({top:""})},dismiss:function(){i.storageMethod&&m.storage.set(i.storedKey,i.storedValue),m.hide()},should:{show:function(){return m.storage.get(i.storedKey)==i.storedValue?!1:!0},stick:function(){return u=h.prop("pageYOffset")||h.scrollTop(),d=p.hasClass(b.bottom)?c-p.outerHeight()+u:u,d>n.top?!0:"fixed"==i.position?!0:!1}},followLink:function(){e.fn.followLink!==o&&p.followLink()},storage:{set:function(t,n){"local"==i.storageMethod&&store!==o?store.set(t,n):e.cookie!==o?e.cookie(t,n):m.error(i.errors.noStorage)},get:function(t){return"local"==i.storageMethod&&store!==o?store.get(t):e.cookie!==o?e.cookie(t):(m.error(i.errors.noStorage),o)}},event:{hover:function(){e(this).toggleClass(b.hover)},scroll:function(){f!==o&&clearTimeout(f),f=setTimeout(function(){m.should.stick()?y(m.stick):m.unStick()},i.lag)}},error:function(e){console.log("Nag Module:"+e)},invoke:function(t,n,a){var s;return a=a||Array.prototype.slice.call(arguments,2),"string"==typeof t&&v!==o&&(t=t.split("."),e.each(t,function(t,n){return e.isPlainObject(v[n])?(v=v[n],!0):e.isFunction(v[n])?(s=v[n],!0):(m.error(i.errors.method),!1)})),e.isFunction(s)?s.apply(n,a):s}},v!==o&&a?("invoke"==a[0]&&(a=Array.prototype.slice.call(a,1)),m.invoke(a[0],this,Array.prototype.slice.call(a,1))):(m.initialize(),o)}),this},e.fn.nag.settings={displayTime:0,followLink:!0,position:"fixed",scrollBarWidth:18,storageMethod:"cookie",storedKey:"nag",storedValue:"dismiss",sticky:!0,lag:0,context:t,errors:{noStorage:"Neither $.cookie or store is defined. A storage solution is required for storing state",followLink:"Follow link is set but the plugin is not included"},className:{bottom:"bottom",hover:"hover",fixed:"fixed"},selector:{close:".icon.close"},speed:500,easing:"easeOutQuad"}})(jQuery,window,document); (function(e,t,n,o){e.fn.nag=function(n){var i=e.extend(!0,{},e.fn.nag.settings,n),a=arguments||!1;return e(this).each(function(){var n,s,r,l,c,u,d,m,f,p=e(this),g=p.find(i.selector.close),h=e(i.context),v=p.data("module"),b=i.className,y=t.requestAnimationFrame||t.mozRequestAnimationFrame||t.webkitRequestAnimationFrame||t.msRequestAnimationFrame||function(e){setTimeout(e,0)};return f={initialize:function(){n=p.offset(),s=p.outerHeight(),r=h.outerWidth(),l=h.outerHeight(),c=h.offset(),p.data("module",f),g.on("mouseenter mouseleave",f.event.hover).on("click",f.dismiss),i.context==t&&"fixed"==i.position&&p.addClass(b.fixed),i.sticky&&("absolute"==i.position?h.on("scroll resize",f.event.scroll):e(t).on("scroll resize",f.event.scroll),e.proxy(f.event.scroll,this)()),i.followLink&&p.on("mouseenter mouseleave",f.event.hover).on("click",f.followLink),i.displayTime>0&&setTimeout(f.hide,i.displayTime),f.should.show()?p.is(":visible")||f.show():f.hide()},refresh:function(){n=p.offset(),s=p.outerHeight(),r=h.outerWidth(),l=h.outerHeight(),c=h.offset()},show:function(){e.fn.popIn!==o?p.popIn(i.duration):p.fadeIn(i.duration,i.easing)},hide:function(){p.fadeOut(i.duration,i.easing)},stick:function(){if(f.refresh(),"fixed"==i.position){var n=e(t).prop("pageYOffset")||e(t).scrollTop(),o=p.hasClass(b.bottom)?c.top+(l-s)-n:c.top-n;p.css({position:"fixed",top:o,left:c.left,width:r-i.scrollBarWidth})}else p.css({top:d})},unStick:function(){p.css({top:""})},dismiss:function(){i.storageMethod&&f.storage.set(i.storedKey,i.storedValue),f.hide()},should:{show:function(){return f.storage.get(i.storedKey)==i.storedValue?!1:!0},stick:function(){return u=h.prop("pageYOffset")||h.scrollTop(),d=p.hasClass(b.bottom)?l-p.outerHeight()+u:u,d>n.top?!0:"fixed"==i.position?!0:!1}},followLink:function(){e.fn.followLink!==o&&p.followLink()},storage:{set:function(t,n){"local"==i.storageMethod&&store!==o?store.set(t,n):e.cookie!==o?e.cookie(t,n):f.error(i.errors.noStorage)},get:function(t){return"local"==i.storageMethod&&store!==o?store.get(t):e.cookie!==o?e.cookie(t):(f.error(i.errors.noStorage),o)}},event:{hover:function(){e(this).toggleClass(b.hover)},scroll:function(){m!==o&&clearTimeout(m),m=setTimeout(function(){f.should.stick()?y(f.stick):f.unStick()},i.lag)}},error:function(e){console.log("Nag Module:"+e)},invoke:function(t,n,a){var s;return a=a||Array.prototype.slice.call(arguments,2),"string"==typeof t&&v!==o&&(t=t.split("."),e.each(t,function(t,n){return e.isPlainObject(v[n])?(v=v[n],!0):e.isFunction(v[n])?(s=v[n],!0):(f.error(i.errors.method),!1)})),e.isFunction(s)?s.apply(n,a):s}},v!==o&&a?("invoke"==a[0]&&(a=Array.prototype.slice.call(a,1)),f.invoke(a[0],this,Array.prototype.slice.call(a,1))):(f.initialize(),o)}),this},e.fn.nag.settings={displayTime:0,followLink:!0,position:"fixed",scrollBarWidth:18,storageMethod:"cookie",storedKey:"nag",storedValue:"dismiss",sticky:!0,lag:0,context:t,errors:{noStorage:"Neither $.cookie or store is defined. A storage solution is required for storing state",followLink:"Follow link is set but the plugin is not included"},className:{bottom:"bottom",hover:"hover",fixed:"fixed"},selector:{close:".icon.close"},speed:500,easing:"easeOutQuad"}})(jQuery,window,document);

2
build/minified/modules/popup.min.js

File diff suppressed because one or more lines are too long

2
build/minified/modules/search.min.js

File diff suppressed because one or more lines are too long

2
build/minified/modules/shape.min.js

File diff suppressed because one or more lines are too long

2
build/minified/modules/star.min.js

@ -1 +1 @@
(function(e,t,n,o){e.fn.starReview=function(t){var n=e.extend(!0,{},e.fn.starReview.settings,t),i=arguments||!1;return e(this).each(function(){var t,a=e(this),s=a.find(n.selector.star),r=n.className,c=n.namespace,l=a.data("module");return t={settings:n,initialize:function(){n.rateable&&(e.fn.state!==o&&(a.state(),s.state()),s.bind("mouseenter."+c,t.event.mouseenter).bind("mouseleave."+c,t.event.mouseleave).bind("click."+c,t.event.click)),a.addClass(r.initialize).data("module",t)},setRating:function(t){var o=s.eq(t-1);a.removeClass(r.hover),s.removeClass(r.hover),o.nextAll().removeClass(r.active),o.addClass(r.active).prevAll().addClass(r.active),e.proxy(n.onRate,a)()},event:{mouseenter:function(){var t=e(this);t.nextAll().removeClass(r.hover),a.addClass(r.hover),t.addClass(r.hover).prevAll().addClass(r.hover)},mouseleave:function(){s.removeClass(r.hover)},click:function(){var n=e(this);t.setRating(s.index(n)+1)}},error:function(e){console.warn(n.moduleName+": "+e)},invoke:function(i,a,s){var r;return s=s||Array.prototype.slice.call(arguments,2),"string"==typeof i&&l!==o&&(i=i.split("."),e.each(i,function(o,i){return e.isPlainObject(l[i])?(l=l[i],!0):e.isFunction(l[i])?(r=l[i],!0):(t.error(n.errors.method),!1)})),e.isFunction(r)?r.apply(a,s):!1}},l!==o&&i?("invoke"==i[0]&&(i=Array.prototype.slice.call(i,1)),t.invoke(i[0],this,Array.prototype.slice.call(i,1))):(t.initialize(),o)}),this},e.fn.starReview.settings={moduleName:"Star Module",namespace:"star",rateable:!0,onRate:function(){},className:{initialize:"initialize",loading:"loading",active:"active",hover:"hover",down:"down"},selector:{star:"i"}}})(jQuery,window,document); (function(e,t,n,o){e.fn.starReview=function(t){var n=e.extend(!0,{},e.fn.starReview.settings,t),i=arguments||!1;return e(this).each(function(){var t,a=e(this),s=a.find(n.selector.star),r=n.className,l=n.namespace,c=a.data("module");return t={settings:n,initialize:function(){n.rateable&&(e.fn.state!==o&&(a.state(),s.state()),s.bind("mouseenter."+l,t.event.mouseenter).bind("mouseleave."+l,t.event.mouseleave).bind("click."+l,t.event.click)),a.addClass(r.initialize).data("module",t)},setRating:function(t){var o=s.eq(t-1);a.removeClass(r.hover),s.removeClass(r.hover),o.nextAll().removeClass(r.active),o.addClass(r.active).prevAll().addClass(r.active),e.proxy(n.onRate,a)()},event:{mouseenter:function(){var t=e(this);t.nextAll().removeClass(r.hover),a.addClass(r.hover),t.addClass(r.hover).prevAll().addClass(r.hover)},mouseleave:function(){s.removeClass(r.hover)},click:function(){var n=e(this);t.setRating(s.index(n)+1)}},error:function(e){console.warn(n.moduleName+": "+e)},invoke:function(i,a,s){var r;return s=s||Array.prototype.slice.call(arguments,2),"string"==typeof i&&c!==o&&(i=i.split("."),e.each(i,function(o,i){return e.isPlainObject(c[i])?(c=c[i],!0):e.isFunction(c[i])?(r=c[i],!0):(t.error(n.errors.method),!1)})),e.isFunction(r)?r.apply(a,s):!1}},c!==o&&i?("invoke"==i[0]&&(i=Array.prototype.slice.call(i,1)),t.invoke(i[0],this,Array.prototype.slice.call(i,1))):(t.initialize(),o)}),this},e.fn.starReview.settings={moduleName:"Star Module",namespace:"star",rateable:!0,onRate:function(){},className:{initialize:"initialize",loading:"loading",active:"active",hover:"hover",down:"down"},selector:{star:"i"}}})(jQuery,window,document);

2
build/minified/modules/tab.min.js

File diff suppressed because one or more lines are too long

2
build/minified/modules/video.min.js

@ -1 +1 @@
(function(e,t,n,o){e.fn.video=function(t){var n,i=e.extend(!0,{},e.fn.video.settings,t),a=arguments||!1;return e(this).each(function(){var s,r=e(this),l=r.find(i.selector.placeholder),c=r.find(i.selector.playButton),u=r.find(i.selector.embed),d=r.data("module-"+i.namespace),f="string"==typeof t,p=i.namespace,m=i.metadata,g=i.className;s={initialize:function(){s.debug("Initializing video"),l.off(".video").on("click."+p,s.play),c.off(".video").on("click."+p,s.play),r.data("module-"+p,s)},change:function(e,t){s.debug("Changing video to ",t),r.data(m.source,e).data(m.flv,t),i.onChange()},reset:function(){s.debug("Clearing video embed and showing placeholder"),r.removeClass(g.active),u.html(" "),l.show(),i.onReset()},play:function(){s.debug("Playing video");var e=r.data(m.source),t=r.data(m.flv);u.html(s.generate.html(e,t)),r.addClass(g.active),i.onPlay()},generate:{html:function(e,t){s.debug("Generating embed html");var n,o="auto"==i.width?r.width():i.width,a="auto"==i.height?r.height():i.height;return"vimeo"==e?n='<iframe src="http://player.vimeo.com/video/'+t+"?="+s.generate.url(e)+'"'+' width="'+o+'" height="'+a+'"'+' frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>':"youtube"==e&&(n='<iframe src="http://www.youtube.com/embed/'+t+"?="+s.generate.url(e)+'"'+' width="'+o+'" height="'+a+'"'+' frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'),n},url:function(e){var t=i.api?1:0,n=i.autoplay?1:0,o=i.hd?1:0,a=i.showUI?1:0,s=i.showUI?0:1,r="";return"vimeo"==e?(r="api="+t+"&amp;title="+a+"&amp;byline="+a+"&amp;portrait="+a+"&amp;autoplay="+n,i.color&&(r+="&amp;color="+i.color)):"youtube"==e&&(r="enablejsapi="+t+"&amp;autoplay="+n+"&amp;autohide="+s+"&amp;hq="+o+"&amp;modestbranding=1",i.color&&(r+="&amp;color="+i.color)),r}},debug:function(e,t){i.debug&&(t!==o?console.info(i.moduleName+": "+e,t):console.info(i.moduleName+": "+e))},error:function(e){console.warn(i.moduleName+": "+e)},invoke:function(t,n,a){var r;return a=a||Array.prototype.slice.call(arguments,2),"string"==typeof t&&d!==o&&(t=t.split("."),e.each(t,function(t,n){return e.isPlainObject(d[n])?(d=d[n],!0):e.isFunction(d[n])?(r=d[n],!0):(s.error(i.errors.method),!1)})),e.isFunction(r)?r.apply(n,a):r}},f?n=s.invoke(a[0],this,Array.prototype.slice.call(a,1)):(d&&s.destroy(),s.initialize())}),n!==o?n:this},e.fn.videoPlaylist=function(t,n){var o=e(this),i=e(t),a=i.find(".embed iframe"),s=e.extend({},e.fn.videoPlaylist.settings,n,!0);o.each(function(){var t=e(this),n=s.metadata,a=s.namespace,r=s.className,l={initialize:function(){t.on("click."+a,l.changeVideo)},changeVideo:function(){var a=t.data(n.flv)||!1,l=t.data(n.source)||!1,c=t.data(n.placeholder)||!1;if(a&&l){if(i.data(n.source,l).data(n.flv,a),s.showPlaceholder)i.removeClass(r.active).find(e.fn.video.selector.placeholder).attr("src",c);else try{i.video("play")}catch(u){console.warn("Video Playlist Module: "+s.error.init)}o.removeClass(r.active),t.addClass(r.active)}}};l.initialize()}),s.playFirst&&(o.eq(0).trigger("click"),a.size()>0&&a.attr("src",a.attr("src").replace("autoplay=1","autoplay=0")))},e.fn.video.settings={moduleName:"Video",namespace:"video",debug:!1,metadata:{source:"source",flv:"flv"},onPlay:function(){},onReset:function(){},onChange:function(){},play:function(){},pause:function(){},stop:function(){},width:"auto",height:"auto",autoplay:!1,color:"#442359",hd:!0,showUI:!1,api:!0,errors:{method:"The method you called is not defined"},className:{active:"active"},selector:{embed:".embed",placeholder:".placeholder",playButton:".play"}},e.fn.videoPlaylist.settings={moduleName:"Video Playlist",namespace:"videoPlaylist",source:"vimeo",showPlaceholder:!1,playFirst:!0,metadata:{flv:"flv",source:"source",placeholder:"placeholder"},errors:{init:"The video player you specified was not yet initialized"},className:{active:"active"}}})(jQuery,window,document); (function(e,t,n,o){e.fn.video=function(t){var n,i=e.extend(!0,{},e.fn.video.settings,t),a=arguments||!1;return e(this).each(function(){var s,r=e(this),l=r.find(i.selector.placeholder),c=r.find(i.selector.playButton),u=r.find(i.selector.embed),d=r.data("module-"+i.namespace),f="string"==typeof t,m=i.namespace,p=i.metadata,g=i.className;s={initialize:function(){s.debug("Initializing video"),l.off(".video").on("click."+m,s.play),c.off(".video").on("click."+m,s.play),r.data("module-"+m,s)},change:function(e,t){s.debug("Changing video to ",t),r.data(p.source,e).data(p.flv,t),i.onChange()},reset:function(){s.debug("Clearing video embed and showing placeholder"),r.removeClass(g.active),u.html(" "),l.show(),i.onReset()},play:function(){s.debug("Playing video");var e=r.data(p.source),t=r.data(p.flv);u.html(s.generate.html(e,t)),r.addClass(g.active),i.onPlay()},generate:{html:function(e,t){s.debug("Generating embed html");var n,o="auto"==i.width?r.width():i.width,a="auto"==i.height?r.height():i.height;return"vimeo"==e?n='<iframe src="http://player.vimeo.com/video/'+t+"?="+s.generate.url(e)+'"'+' width="'+o+'" height="'+a+'"'+' frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>':"youtube"==e&&(n='<iframe src="http://www.youtube.com/embed/'+t+"?="+s.generate.url(e)+'"'+' width="'+o+'" height="'+a+'"'+' frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>'),n},url:function(e){var t=i.api?1:0,n=i.autoplay?1:0,o=i.hd?1:0,a=i.showUI?1:0,s=i.showUI?0:1,r="";return"vimeo"==e?(r="api="+t+"&amp;title="+a+"&amp;byline="+a+"&amp;portrait="+a+"&amp;autoplay="+n,i.color&&(r+="&amp;color="+i.color)):"youtube"==e&&(r="enablejsapi="+t+"&amp;autoplay="+n+"&amp;autohide="+s+"&amp;hq="+o+"&amp;modestbranding=1",i.color&&(r+="&amp;color="+i.color)),r}},debug:function(e,t){i.debug&&(t!==o?console.info(i.moduleName+": "+e,t):console.info(i.moduleName+": "+e))},error:function(e){console.warn(i.moduleName+": "+e)},invoke:function(t,n,a){var r;return a=a||Array.prototype.slice.call(arguments,2),"string"==typeof t&&d!==o&&(t=t.split("."),e.each(t,function(t,n){return e.isPlainObject(d[n])?(d=d[n],!0):e.isFunction(d[n])?(r=d[n],!0):(s.error(i.errors.method),!1)})),e.isFunction(r)?r.apply(n,a):r}},f?n=s.invoke(a[0],this,Array.prototype.slice.call(a,1)):(d&&s.destroy(),s.initialize())}),n!==o?n:this},e.fn.videoPlaylist=function(t,n){var o=e(this),i=e(t),a=i.find(".embed iframe"),s=e.extend({},e.fn.videoPlaylist.settings,n,!0);o.each(function(){var t=e(this),n=s.metadata,a=s.namespace,r=s.className,l={initialize:function(){t.on("click."+a,l.changeVideo)},changeVideo:function(){var a=t.data(n.flv)||!1,l=t.data(n.source)||!1,c=t.data(n.placeholder)||!1;if(a&&l){if(i.data(n.source,l).data(n.flv,a),s.showPlaceholder)i.removeClass(r.active).find(e.fn.video.selector.placeholder).attr("src",c);else try{i.video("play")}catch(u){console.warn("Video Playlist Module: "+s.error.init)}o.removeClass(r.active),t.addClass(r.active)}}};l.initialize()}),s.playFirst&&(o.eq(0).trigger("click"),a.size()>0&&a.attr("src",a.attr("src").replace("autoplay=1","autoplay=0")))},e.fn.video.settings={moduleName:"Video",namespace:"video",debug:!1,metadata:{source:"source",flv:"flv"},onPlay:function(){},onReset:function(){},onChange:function(){},play:function(){},pause:function(){},stop:function(){},width:"auto",height:"auto",autoplay:!1,color:"#442359",hd:!0,showUI:!1,api:!0,errors:{method:"The method you called is not defined"},className:{active:"active"},selector:{embed:".embed",placeholder:".placeholder",playButton:".play"}},e.fn.videoPlaylist.settings={moduleName:"Video Playlist",namespace:"videoPlaylist",source:"vimeo",showPlaceholder:!1,playFirst:!0,metadata:{flv:"flv",source:"source",placeholder:"placeholder"},errors:{init:"The video player you specified was not yet initialized"},className:{active:"active"}}})(jQuery,window,document);

458
build/packaged/modules/behavior/form.js

@ -3,7 +3,7 @@
Author: Jack Lukic Author: Jack Lukic
Notes: First Commit April 08, 2012 Notes: First Commit April 08, 2012
Refactored Feb 22, 2012 Refactored May 28, 2013
Allows you to validate forms based on a form validation object Allows you to validate forms based on a form validation object
Form validation objects are bound by either data-validate="" metadata, or form id or name tags Form validation objects are bound by either data-validate="" metadata, or form id or name tags
@ -12,32 +12,42 @@
;(function ( $, window, document, undefined ) { ;(function ( $, window, document, undefined ) {
$.fn.validateForm = function(fields, parameters) { $.fn.form = function(fields, parameters) {
var var
$allModules = $(this), $allModules = $(this),
settings = $.extend(true, {}, $.fn.validateForm.settings, parameters), settings = $.extend(true, {}, $.fn.form.settings, parameters),
// make arguments available validation = $.extend({}, $.fn.form.settings.defaults, fields),
eventNamespace = '.' + settings.namespace,
moduleNamespace = 'module-' + settings.namespace,
selector = $allModules.selector || '',
time = new Date().getTime(),
performance = [],
query = arguments[0], query = arguments[0],
passedArguments = [].slice.call(arguments, 1), methodInvoked = (typeof query == 'string'),
queryArguments = [].slice.call(arguments, 1),
invokedResponse invokedResponse
; ;
$allModules $allModules
.each(function() { .each(function() {
var var
$module = $(this), $module = $(this),
$group = $(this).find(settings.selector.group),
$field = $(this).find(settings.selector.field), $field = $(this).find(settings.selector.field),
$errorPrompt = $(this).find(settings.selector.prompt), $group = $(this).find(settings.selector.group),
$message = $(this).find(settings.selector.message),
$prompt = $(this).find(settings.selector.prompt),
$submit = $(this).find(settings.selector.submit),
formErrors = [], formErrors = [],
selector = $module.selector || '',
element = this, element = this,
instance = $module.data('module-' + settings.namespace), instance = $module.data('module-' + settings.namespace),
methodInvoked = (typeof query == 'string'),
namespace = settings.namespace, namespace = settings.namespace,
selector = settings.selector,
metadata = settings.metadata, metadata = settings.metadata,
className = settings.className, className = settings.className,
errors = settings.errors, errors = settings.errors,
@ -48,21 +58,20 @@ $.fn.validateForm = function(fields, parameters) {
initialize: function() { initialize: function() {
module.verbose('Initializing form validation'); module.verbose('Initializing form validation');
if(fields !== undefined || !$.isEmptyObject(fields) ) { if(settings.keyboardShortcuts) {
// add default text if set $field
if($.fn.defaultText !== undefined) { .on('keydown' + eventNamespace, module.event.field.keydown)
$.each(fields, function(fieldName, field) { ;
module.field.add.defaultText(field);
});
} }
// attach event handler
$module $module
.on('submit.' + namespace, module.validate.form) .on('submit' + eventNamespace, module.validate.form)
;
$field
.on('change' + eventNamespace, module.event.field.change)
;
$submit
.on('click' + eventNamespace, module.submit)
; ;
}
else {
module.error(errors.noFields, $module);
}
}, },
destroy: function() { destroy: function() {
@ -71,11 +80,66 @@ $.fn.validateForm = function(fields, parameters) {
; ;
}, },
refresh: function() {
$field = $module.find(selector.field);
},
submit: function() {
module.verbose('Submitting form', $module);
$module.submit();
},
event: {
field: { field: {
find: function(identifier) { keydown: function(event) {
var var
$field = $module.find(settings.selector.field) $field = $(this),
key = event.which,
keyCode = {
enter : 13,
escape : 27
}
; ;
if( key == keyCode.escape) {
module.verbose('Escape key pressed blurring field');
$field.blur();
}
if( 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();
},
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: {
field: function(identifier) {
if( $field.filter('#' + identifier).size() > 0 ) { if( $field.filter('#' + identifier).size() > 0 ) {
return $field.filter('#' + identifier); return $field.filter('#' + identifier);
} }
@ -87,54 +151,67 @@ $.fn.validateForm = function(fields, parameters) {
} }
return $('<input/>'); return $('<input/>');
}, },
add: { validation: function($field) {
defaultText: function(field) {
var var
$field = module.field.find(field.identifier) rules
; ;
if(field.defaultText !== undefined) { $.each(validation, function(fieldName, field) {
$field.defaultText(field.defaultText); if( module.get.field(field.identifier).get(0) == $field.get(0) ) {
rules = field;
}
});
return rules || false;
} }
}, },
error: function(field, errors) {
add: {
prompt: function(field, errors) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
$errorGroup = $field.closest($group), $fieldGroup = $field.closest($group),
$errorPrompt = $group.find($errorPrompt), $prompt = $fieldGroup.find(selector.prompt),
promptExists = ($errorPrompt.size() !== 0) promptExists = ($prompt.size() !== 0)
; ;
$errorGroup module.verbose('Adding inline validation prompt');
$fieldGroup
.addClass(className.error) .addClass(className.error)
; ;
if(settings.inlineError) { if(settings.inlineError) {
// create message container on first invalid validation attempt
if(!promptExists) { if(!promptExists) {
$errorPrompt = $('<div />') $prompt = settings.templates.prompt(errors);
.addClass(className.prompt) $prompt
.insertBefore($field) .appendTo($fieldGroup)
.hide()
; ;
} }
// add prompt message $prompt
$errorPrompt
.html(errors[0]) .html(errors[0])
.fadeIn(settings.animateSpeed)
; ;
if($prompt.is(':not(:visible)')) {
$prompt.fadeIn(200);
}
} }
},
errors: function(errors) {
module.debug('Adding form error messages', errors);
$message
.html( settings.templates.error(errors) )
;
} }
}, },
remove: { remove: {
error: function(field) { prompt: function(field) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
$errorGroup = $field.closest($group), $fieldGroup = $field.closest($group),
$errorPrompt = $group.find($errorPrompt) $prompt = $group.find($prompt)
; ;
$errorGroup $fieldGroup
.removeClass(className.error) .removeClass(className.error)
; ;
if(settings.inlineError) { if(settings.inlineError) {
$errorPrompt.hide(); $prompt.hide();
}
} }
} }
}, },
@ -147,28 +224,32 @@ $.fn.validateForm = function(fields, parameters) {
; ;
// reset errors // reset errors
formErrors = []; formErrors = [];
$.each(fields, function(fieldName, field){ $.each(validation, function(fieldName, field){
// form is invalid after first bad field, but keep checking
if( !( module.validate.field(field) ) ) { if( !( module.validate.field(field) ) ) {
allValid = false; allValid = false;
} }
}); });
// Evaluate form callbacks if(allValid) {
return (allValid) $module.removeClass(className.error);
? $.proxy(settings.onSuccess, this)(event) $.proxy(settings.onSuccess, this)(event);
: $.proxy(settings.onFailure, this)(formErrors) }
; else {
$module.addClass(className.error);
if(!settings.inlineError) {
module.add.errors(formErrors);
}
$.proxy(settings.onFailure, this)(formErrors);
}
}, },
// takes a validation object and returns whether field passes validation // takes a validation object and returns whether field passes validation
field: function(field) { field: function(field) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
fieldValid = true, fieldValid = true,
fieldErrors = [] fieldErrors = []
; ;
if(field.rules !== undefined) { if(field.rules !== undefined) {
// iterate over all validation types for a certain field
$.each(field.rules, function(index, rule) { $.each(field.rules, function(index, rule) {
if( !( module.validate.rule(field, rule) ) ) { if( !( module.validate.rule(field, rule) ) ) {
module.debug('Field is invalid', field.identifier, rule.type); module.debug('Field is invalid', field.identifier, rule.type);
@ -178,12 +259,12 @@ $.fn.validateForm = function(fields, parameters) {
}); });
} }
if(fieldValid) { if(fieldValid) {
module.field.remove.error(field, fieldErrors); module.remove.prompt(field, fieldErrors);
settings.onValid($field); $.proxy(settings.onValid, $field)();
} }
else { else {
formErrors = formErrors.concat(fieldErrors); formErrors = formErrors.concat(fieldErrors);
module.field.add.error(field, fieldErrors); module.add.prompt(field, fieldErrors);
$.proxy(settings.onInvalid, $field)(fieldErrors); $.proxy(settings.onInvalid, $field)(fieldErrors);
return false; return false;
} }
@ -193,14 +274,9 @@ $.fn.validateForm = function(fields, parameters) {
// takes validation rule and returns whether field passes rule // takes validation rule and returns whether field passes rule
rule: function(field, validation) { rule: function(field, validation) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
type = validation.type, type = validation.type,
defaultText = (field.defaultText !== undefined) value = $field.val(),
? field.defaultText
: false,
value = ($field.val() == defaultText)
? ''
: $field.val(),
bracketRegExp = /\[(.*?)\]/i, bracketRegExp = /\[(.*?)\]/i,
bracket = bracketRegExp.exec(type), bracket = bracketRegExp.exec(type),
@ -225,51 +301,104 @@ $.fn.validateForm = function(fields, parameters) {
} }
}, },
/* standard module */
setting: function(name, value) { setting: function(name, value) {
if(value === undefined) { if(value !== undefined) {
return settings[name]; if( $.isPlainObject(name) ) {
$.extend(true, settings, name);
} }
else {
settings[name] = value; settings[name] = value;
}
}
else {
return settings[name];
}
}, },
verbose: function() { internal: function(name, value) {
if(settings.verbose) { if(value !== undefined) {
module.debug.apply(this, arguments); if( $.isPlainObject(name) ) {
$.extend(true, module, name);
}
else {
module[name] = value;
}
}
else {
return module[name];
} }
}, },
debug: function() { debug: function() {
var
output = [],
message = settings.moduleName + ': ' + arguments[0],
variables = [].slice.call( arguments, 1 ),
log = console.info || console.log || function(){}
;
log = Function.prototype.bind.call(log, console);
if(settings.debug) { if(settings.debug) {
output.push(message); module.performance.log(arguments[0]);
log.apply(console, output.concat(variables) ); module.debug = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
}
},
verbose: function() {
if(settings.verbose && settings.debug) {
module.performance.log(arguments[0]);
module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
} }
}, },
error: function() { error: function() {
module.error = Function.prototype.bind.call(console.log, console, settings.moduleName + ':');
},
performance: {
log: function(message) {
var var
output = [], currentTime,
errorMessage = settings.moduleName + ': ' + arguments[0], executionTime,
variables = [].slice.call( arguments, 1 ), previousTime
log = console.warn || console.log || function(){}
; ;
log = Function.prototype.bind.call(log, console); if(settings.performance) {
if(settings.debug) { currentTime = new Date().getTime();
output.push(errorMessage); previousTime = time || currentTime,
output.concat(variables); executionTime = currentTime - previousTime;
log.apply(console, output.concat(variables) ); time = currentTime;
performance.push({
'Element' : element,
'Name' : message,
'Execution Time' : executionTime
});
clearTimeout(module.performance.timer);
module.performance.timer = setTimeout(module.performance.display, 100);
}
},
display: function() {
var
title = settings.moduleName,
caption = settings.moduleName + ': ' + selector + '(' + $allModules.size() + ' elements)',
totalExecutionTime = 0
;
if(selector) {
title += 'Performance (' + selector + ')';
}
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
console.groupCollapsed(title);
if(console.table) {
$.each(performance, function(index, data) {
totalExecutionTime += data['Execution Time'];
});
console.table(performance);
}
else {
$.each(performance, function(index, data) {
totalExecutionTime += data['Execution Time'];
});
}
console.log('Total Execution Time:', totalExecutionTime +'ms');
console.groupEnd();
performance = [];
time = false;
}
} }
}, },
invoke: function(query, context, passedArguments) { invoke: function(query, passedArguments, context) {
var var
maxDepth, maxDepth,
found found
; ;
passedArguments = passedArguments || [].slice.call( arguments, 2 ); passedArguments = passedArguments || queryArguments;
context = element || context;
if(typeof query == 'string' && instance !== undefined) { if(typeof query == 'string' && instance !== undefined) {
query = query.split('.'); query = query.split('.');
maxDepth = query.length - 1; maxDepth = query.length - 1;
@ -287,42 +416,47 @@ $.fn.validateForm = function(fields, parameters) {
}); });
} }
if ( $.isFunction( found ) ) { if ( $.isFunction( found ) ) {
module.verbose('Executing invoked function', found);
return found.apply(context, passedArguments); return found.apply(context, passedArguments);
} }
// return retrieved variable or chain return found || false;
return found;
} }
}; };
// check for invoking internal method
if(methodInvoked) { if(methodInvoked) {
invokedResponse = module.invoke(query, this, passedArguments); if(instance === undefined) {
module.initialize();
}
invokedResponse = module.invoke(query);
} }
// otherwise initialize
else { else {
if(instance !== undefined) {
module.destroy();
}
module.initialize(); module.initialize();
} }
}) })
; ;
// chain or return queried method return (invokedResponse)
return (invokedResponse !== undefined)
? invokedResponse ? invokedResponse
: this : this
; ;
}; };
$.fn.validateForm.settings = { $.fn.form.settings = {
// module info // module info
moduleName : 'Validate Form Module', moduleName : 'Validate Form Module',
debug : true, debug : true,
verbose : false, verbose : true,
namespace : 'validate', namespace : 'validate',
keyboardShortcuts : true,
on : 'change',
animateSpeed : 150, animateSpeed : 150,
inlineError : false, inlineError : false,
onValid : function() {}, onValid : function() {},
onInvalid : function() {}, onInvalid : function() {},
onSuccess : function() { return true; }, onSuccess : function() { return true; },
@ -332,22 +466,122 @@ $.fn.validateForm.settings = {
validate: 'validate' validate: 'validate'
}, },
// errors
errors: {
method : 'The method you called is not defined.',
noFields : 'No validation object specified.'
},
selector : { selector : {
message : '.error.message',
field : 'input, textarea, select',
group : '.field', group : '.field',
input : 'input',
prompt : '.prompt', prompt : '.prompt',
field : 'input, textarea, select' submit : '.submit'
}, },
className : { className : {
error : 'error', error : 'error',
prompt : 'prompt' down : 'down',
label : 'ui label prompt'
},
// errors
errors: {
method : 'The method you called is not defined.'
},
defaults: {
firstName: {
identifier : 'first-name',
rules: [
{
type : 'empty',
prompt : 'Please enter your first name'
}
]
},
lastName: {
identifier : 'last-name',
rules: [
{
type : 'empty',
prompt : 'Please enter your last name'
}
]
},
username: {
identifier : 'username',
rules: [
{
type : 'empty',
prompt : 'Please enter a username'
}
]
},
email: {
identifier : 'email',
rules: [
{
type : 'empty',
prompt : 'Please enter your email'
},
{
type : 'email',
prompt : 'Please enter a valid email'
}
]
},
password: {
identifier : 'password',
rules: [
{
type : 'empty',
prompt : 'Please enter a password'
},
{
type : 'length[6]',
prompt : 'Your password must be at least 6 characters'
}
]
},
passwordConfirm: {
identifier : 'password-confirm',
rules: [
{
type : 'empty',
prompt : 'Please confirm your password'
},
{
identifier : 'password-confirm',
type : 'match[password]',
prompt : 'Please verify password matches'
}
]
},
terms: {
identifier : 'terms',
rules: [
{
type : 'checked',
prompt : 'You must agree to the terms and conditions'
}
]
}
},
templates: {
error: function(errors) {
var
html = '<ul class="list">'
;
$.each(errors, function(index, value) {
html += '<li>' + value + '</li>';
});
html += '</ul>';
return $(html);
},
prompt: function(errors) {
return $('<div/>')
.addClass('ui red pointing prompt label')
.html(errors[0])
;
}
}, },
rules: { rules: {

2
build/packaged/modules/dropdown.js

@ -394,7 +394,7 @@ $.fn.dropdown = function(parameters) {
debug: function() { debug: function() {
if(settings.debug) { if(settings.debug) {
module.performance.log(arguments[0]); module.performance.log(arguments[0]);
module.debug = Function.prototype.bind.call(console.log, console, settings.moduleName + ':'); module.debug = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
} }
}, },
verbose: function() { verbose: function() {

2
build/packaged/semantic.min.css.REMOVED.git-id

@ -1 +1 @@
c2cc09fda7af25b2ac2972b6d855ae43b108f345 4faca9c8fe96f7f3a21cf890917ad9525a94fa9f

2
build/packaged/semantic.min.js.REMOVED.git-id

@ -1 +1 @@
2c4195be95b12a3b16a540277bbbb730beedecca 9db5cfc27a304899cd1ab4666348c271a8bb92a8

17
build/uncompressed/collections/form.css

@ -112,6 +112,23 @@
.ui.form .message:first-child { .ui.form .message:first-child {
margin-top: 0px; margin-top: 0px;
} }
/*--------------------
Validation Prompt
---------------------*/
.ui.form .field .prompt.label {
white-space: nowrap;
}
.ui.form .inline.field .prompt {
margin-top: 0em;
margin-left: 1em;
}
.ui.form .inline.field .prompt:before {
margin-top: -0.3em;
bottom: auto;
right: auto;
top: 50%;
left: 0em;
}
/******************************* /*******************************
States States
*******************************/ *******************************/

9
build/uncompressed/collections/menu.css

@ -199,10 +199,15 @@
---------------*/ ---------------*/
.ui.menu .item > .label, .ui.menu .item > .label,
.ui.menu .item > a > .label { .ui.menu .item > a > .label {
font-size: 0.9em; font-size: 0.8em;
margin: -0.3em 0em -0.3em 0.3em; margin: -0.3em 0em -0.3em 0.3em;
padding: 0.1em 0.5em; padding: 0.1em 0.8em;
vertical-align: baseline; vertical-align: baseline;
text-transform: none;
}
.ui.menu .item > .floating.label,
.ui.menu .item > a > .floating.label {
padding: 0.3em 0.8em;
} }
/*-------------- /*--------------
Images Images

10
build/uncompressed/elements/label.css

@ -15,7 +15,7 @@
.ui.label { .ui.label {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
background-color: #F5F5F5; background-color: #E8E8E8;
padding: 0.5em 0.8em; padding: 0.5em 0.8em;
color: rgba(0, 0, 0, 0.65); color: rgba(0, 0, 0, 0.65);
text-transform: uppercase; text-transform: uppercase;
@ -42,6 +42,7 @@ a.ui.label {
.ui.label .detail { .ui.label .detail {
display: inline-block; display: inline-block;
margin-left: 1em; margin-left: 1em;
font-weight: bold;
opacity: 0.8; opacity: 0.8;
} }
.ui.label .icon.close { .ui.label .icon.close {
@ -67,12 +68,12 @@ a.ui.label {
--------------------*/ --------------------*/
a.ui.labels .label:hover, a.ui.labels .label:hover,
a.ui.label:hover { a.ui.label:hover {
background-color: #F0F0F0; background-color: #E0E0E0;
color: rgba(0, 0, 0, 0.7); color: rgba(0, 0, 0, 0.7);
} }
.ui.labels a.label:hover:before, .ui.labels a.label:hover:before,
a.ui.label:hover:before { a.ui.label:hover:before {
background-color: #F0F0F0; background-color: #E0E0E0;
color: rgba(0, 0, 0, 0.7); color: rgba(0, 0, 0, 0.7);
} }
.ui.label .icon.close:hover { .ui.label .icon.close:hover {
@ -341,6 +342,9 @@ a.ui.teal.tag.label:hover:before {
; ;
} }
/*--- Above ---*/ /*--- Above ---*/
.ui.pointing.label:before {
background-color: #E8E8E8;
}
.ui.pointing.label, .ui.pointing.label,
.ui.pointing.above.label { .ui.pointing.above.label {
margin-top: 1em; margin-top: 1em;

458
build/uncompressed/modules/behavior/form.js

@ -3,7 +3,7 @@
Author: Jack Lukic Author: Jack Lukic
Notes: First Commit April 08, 2012 Notes: First Commit April 08, 2012
Refactored Feb 22, 2012 Refactored May 28, 2013
Allows you to validate forms based on a form validation object Allows you to validate forms based on a form validation object
Form validation objects are bound by either data-validate="" metadata, or form id or name tags Form validation objects are bound by either data-validate="" metadata, or form id or name tags
@ -12,32 +12,42 @@
;(function ( $, window, document, undefined ) { ;(function ( $, window, document, undefined ) {
$.fn.validateForm = function(fields, parameters) { $.fn.form = function(fields, parameters) {
var var
$allModules = $(this), $allModules = $(this),
settings = $.extend(true, {}, $.fn.validateForm.settings, parameters), settings = $.extend(true, {}, $.fn.form.settings, parameters),
// make arguments available validation = $.extend({}, $.fn.form.settings.defaults, fields),
eventNamespace = '.' + settings.namespace,
moduleNamespace = 'module-' + settings.namespace,
selector = $allModules.selector || '',
time = new Date().getTime(),
performance = [],
query = arguments[0], query = arguments[0],
passedArguments = [].slice.call(arguments, 1), methodInvoked = (typeof query == 'string'),
queryArguments = [].slice.call(arguments, 1),
invokedResponse invokedResponse
; ;
$allModules $allModules
.each(function() { .each(function() {
var var
$module = $(this), $module = $(this),
$group = $(this).find(settings.selector.group),
$field = $(this).find(settings.selector.field), $field = $(this).find(settings.selector.field),
$errorPrompt = $(this).find(settings.selector.prompt), $group = $(this).find(settings.selector.group),
$message = $(this).find(settings.selector.message),
$prompt = $(this).find(settings.selector.prompt),
$submit = $(this).find(settings.selector.submit),
formErrors = [], formErrors = [],
selector = $module.selector || '',
element = this, element = this,
instance = $module.data('module-' + settings.namespace), instance = $module.data('module-' + settings.namespace),
methodInvoked = (typeof query == 'string'),
namespace = settings.namespace, namespace = settings.namespace,
selector = settings.selector,
metadata = settings.metadata, metadata = settings.metadata,
className = settings.className, className = settings.className,
errors = settings.errors, errors = settings.errors,
@ -48,21 +58,20 @@ $.fn.validateForm = function(fields, parameters) {
initialize: function() { initialize: function() {
module.verbose('Initializing form validation'); module.verbose('Initializing form validation');
if(fields !== undefined || !$.isEmptyObject(fields) ) { if(settings.keyboardShortcuts) {
// add default text if set $field
if($.fn.defaultText !== undefined) { .on('keydown' + eventNamespace, module.event.field.keydown)
$.each(fields, function(fieldName, field) { ;
module.field.add.defaultText(field);
});
} }
// attach event handler
$module $module
.on('submit.' + namespace, module.validate.form) .on('submit' + eventNamespace, module.validate.form)
;
$field
.on('change' + eventNamespace, module.event.field.change)
;
$submit
.on('click' + eventNamespace, module.submit)
; ;
}
else {
module.error(errors.noFields, $module);
}
}, },
destroy: function() { destroy: function() {
@ -71,11 +80,66 @@ $.fn.validateForm = function(fields, parameters) {
; ;
}, },
refresh: function() {
$field = $module.find(selector.field);
},
submit: function() {
module.verbose('Submitting form', $module);
$module.submit();
},
event: {
field: { field: {
find: function(identifier) { keydown: function(event) {
var var
$field = $module.find(settings.selector.field) $field = $(this),
key = event.which,
keyCode = {
enter : 13,
escape : 27
}
; ;
if( key == keyCode.escape) {
module.verbose('Escape key pressed blurring field');
$field.blur();
}
if( 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();
},
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: {
field: function(identifier) {
if( $field.filter('#' + identifier).size() > 0 ) { if( $field.filter('#' + identifier).size() > 0 ) {
return $field.filter('#' + identifier); return $field.filter('#' + identifier);
} }
@ -87,54 +151,67 @@ $.fn.validateForm = function(fields, parameters) {
} }
return $('<input/>'); return $('<input/>');
}, },
add: { validation: function($field) {
defaultText: function(field) {
var var
$field = module.field.find(field.identifier) rules
; ;
if(field.defaultText !== undefined) { $.each(validation, function(fieldName, field) {
$field.defaultText(field.defaultText); if( module.get.field(field.identifier).get(0) == $field.get(0) ) {
rules = field;
}
});
return rules || false;
} }
}, },
error: function(field, errors) {
add: {
prompt: function(field, errors) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
$errorGroup = $field.closest($group), $fieldGroup = $field.closest($group),
$errorPrompt = $group.find($errorPrompt), $prompt = $fieldGroup.find(selector.prompt),
promptExists = ($errorPrompt.size() !== 0) promptExists = ($prompt.size() !== 0)
; ;
$errorGroup module.verbose('Adding inline validation prompt');
$fieldGroup
.addClass(className.error) .addClass(className.error)
; ;
if(settings.inlineError) { if(settings.inlineError) {
// create message container on first invalid validation attempt
if(!promptExists) { if(!promptExists) {
$errorPrompt = $('<div />') $prompt = settings.templates.prompt(errors);
.addClass(className.prompt) $prompt
.insertBefore($field) .appendTo($fieldGroup)
.hide()
; ;
} }
// add prompt message $prompt
$errorPrompt
.html(errors[0]) .html(errors[0])
.fadeIn(settings.animateSpeed)
; ;
if($prompt.is(':not(:visible)')) {
$prompt.fadeIn(200);
}
} }
},
errors: function(errors) {
module.debug('Adding form error messages', errors);
$message
.html( settings.templates.error(errors) )
;
} }
}, },
remove: { remove: {
error: function(field) { prompt: function(field) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
$errorGroup = $field.closest($group), $fieldGroup = $field.closest($group),
$errorPrompt = $group.find($errorPrompt) $prompt = $group.find($prompt)
; ;
$errorGroup $fieldGroup
.removeClass(className.error) .removeClass(className.error)
; ;
if(settings.inlineError) { if(settings.inlineError) {
$errorPrompt.hide(); $prompt.hide();
}
} }
} }
}, },
@ -147,28 +224,32 @@ $.fn.validateForm = function(fields, parameters) {
; ;
// reset errors // reset errors
formErrors = []; formErrors = [];
$.each(fields, function(fieldName, field){ $.each(validation, function(fieldName, field){
// form is invalid after first bad field, but keep checking
if( !( module.validate.field(field) ) ) { if( !( module.validate.field(field) ) ) {
allValid = false; allValid = false;
} }
}); });
// Evaluate form callbacks if(allValid) {
return (allValid) $module.removeClass(className.error);
? $.proxy(settings.onSuccess, this)(event) $.proxy(settings.onSuccess, this)(event);
: $.proxy(settings.onFailure, this)(formErrors) }
; else {
$module.addClass(className.error);
if(!settings.inlineError) {
module.add.errors(formErrors);
}
$.proxy(settings.onFailure, this)(formErrors);
}
}, },
// takes a validation object and returns whether field passes validation // takes a validation object and returns whether field passes validation
field: function(field) { field: function(field) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
fieldValid = true, fieldValid = true,
fieldErrors = [] fieldErrors = []
; ;
if(field.rules !== undefined) { if(field.rules !== undefined) {
// iterate over all validation types for a certain field
$.each(field.rules, function(index, rule) { $.each(field.rules, function(index, rule) {
if( !( module.validate.rule(field, rule) ) ) { if( !( module.validate.rule(field, rule) ) ) {
module.debug('Field is invalid', field.identifier, rule.type); module.debug('Field is invalid', field.identifier, rule.type);
@ -178,12 +259,12 @@ $.fn.validateForm = function(fields, parameters) {
}); });
} }
if(fieldValid) { if(fieldValid) {
module.field.remove.error(field, fieldErrors); module.remove.prompt(field, fieldErrors);
settings.onValid($field); $.proxy(settings.onValid, $field)();
} }
else { else {
formErrors = formErrors.concat(fieldErrors); formErrors = formErrors.concat(fieldErrors);
module.field.add.error(field, fieldErrors); module.add.prompt(field, fieldErrors);
$.proxy(settings.onInvalid, $field)(fieldErrors); $.proxy(settings.onInvalid, $field)(fieldErrors);
return false; return false;
} }
@ -193,14 +274,9 @@ $.fn.validateForm = function(fields, parameters) {
// takes validation rule and returns whether field passes rule // takes validation rule and returns whether field passes rule
rule: function(field, validation) { rule: function(field, validation) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
type = validation.type, type = validation.type,
defaultText = (field.defaultText !== undefined) value = $field.val(),
? field.defaultText
: false,
value = ($field.val() == defaultText)
? ''
: $field.val(),
bracketRegExp = /\[(.*?)\]/i, bracketRegExp = /\[(.*?)\]/i,
bracket = bracketRegExp.exec(type), bracket = bracketRegExp.exec(type),
@ -225,51 +301,104 @@ $.fn.validateForm = function(fields, parameters) {
} }
}, },
/* standard module */
setting: function(name, value) { setting: function(name, value) {
if(value === undefined) { if(value !== undefined) {
return settings[name]; if( $.isPlainObject(name) ) {
$.extend(true, settings, name);
} }
else {
settings[name] = value; settings[name] = value;
}
}
else {
return settings[name];
}
}, },
verbose: function() { internal: function(name, value) {
if(settings.verbose) { if(value !== undefined) {
module.debug.apply(this, arguments); if( $.isPlainObject(name) ) {
$.extend(true, module, name);
}
else {
module[name] = value;
}
}
else {
return module[name];
} }
}, },
debug: function() { debug: function() {
var
output = [],
message = settings.moduleName + ': ' + arguments[0],
variables = [].slice.call( arguments, 1 ),
log = console.info || console.log || function(){}
;
log = Function.prototype.bind.call(log, console);
if(settings.debug) { if(settings.debug) {
output.push(message); module.performance.log(arguments[0]);
log.apply(console, output.concat(variables) ); module.debug = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
}
},
verbose: function() {
if(settings.verbose && settings.debug) {
module.performance.log(arguments[0]);
module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
} }
}, },
error: function() { error: function() {
module.error = Function.prototype.bind.call(console.log, console, settings.moduleName + ':');
},
performance: {
log: function(message) {
var var
output = [], currentTime,
errorMessage = settings.moduleName + ': ' + arguments[0], executionTime,
variables = [].slice.call( arguments, 1 ), previousTime
log = console.warn || console.log || function(){}
; ;
log = Function.prototype.bind.call(log, console); if(settings.performance) {
if(settings.debug) { currentTime = new Date().getTime();
output.push(errorMessage); previousTime = time || currentTime,
output.concat(variables); executionTime = currentTime - previousTime;
log.apply(console, output.concat(variables) ); time = currentTime;
performance.push({
'Element' : element,
'Name' : message,
'Execution Time' : executionTime
});
clearTimeout(module.performance.timer);
module.performance.timer = setTimeout(module.performance.display, 100);
}
},
display: function() {
var
title = settings.moduleName,
caption = settings.moduleName + ': ' + selector + '(' + $allModules.size() + ' elements)',
totalExecutionTime = 0
;
if(selector) {
title += 'Performance (' + selector + ')';
}
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
console.groupCollapsed(title);
if(console.table) {
$.each(performance, function(index, data) {
totalExecutionTime += data['Execution Time'];
});
console.table(performance);
}
else {
$.each(performance, function(index, data) {
totalExecutionTime += data['Execution Time'];
});
}
console.log('Total Execution Time:', totalExecutionTime +'ms');
console.groupEnd();
performance = [];
time = false;
}
} }
}, },
invoke: function(query, context, passedArguments) { invoke: function(query, passedArguments, context) {
var var
maxDepth, maxDepth,
found found
; ;
passedArguments = passedArguments || [].slice.call( arguments, 2 ); passedArguments = passedArguments || queryArguments;
context = element || context;
if(typeof query == 'string' && instance !== undefined) { if(typeof query == 'string' && instance !== undefined) {
query = query.split('.'); query = query.split('.');
maxDepth = query.length - 1; maxDepth = query.length - 1;
@ -287,42 +416,47 @@ $.fn.validateForm = function(fields, parameters) {
}); });
} }
if ( $.isFunction( found ) ) { if ( $.isFunction( found ) ) {
module.verbose('Executing invoked function', found);
return found.apply(context, passedArguments); return found.apply(context, passedArguments);
} }
// return retrieved variable or chain return found || false;
return found;
} }
}; };
// check for invoking internal method
if(methodInvoked) { if(methodInvoked) {
invokedResponse = module.invoke(query, this, passedArguments); if(instance === undefined) {
module.initialize();
}
invokedResponse = module.invoke(query);
} }
// otherwise initialize
else { else {
if(instance !== undefined) {
module.destroy();
}
module.initialize(); module.initialize();
} }
}) })
; ;
// chain or return queried method return (invokedResponse)
return (invokedResponse !== undefined)
? invokedResponse ? invokedResponse
: this : this
; ;
}; };
$.fn.validateForm.settings = { $.fn.form.settings = {
// module info // module info
moduleName : 'Validate Form Module', moduleName : 'Validate Form Module',
debug : true, debug : true,
verbose : false, verbose : true,
namespace : 'validate', namespace : 'validate',
keyboardShortcuts : true,
on : 'change',
animateSpeed : 150, animateSpeed : 150,
inlineError : false, inlineError : false,
onValid : function() {}, onValid : function() {},
onInvalid : function() {}, onInvalid : function() {},
onSuccess : function() { return true; }, onSuccess : function() { return true; },
@ -332,22 +466,122 @@ $.fn.validateForm.settings = {
validate: 'validate' validate: 'validate'
}, },
// errors
errors: {
method : 'The method you called is not defined.',
noFields : 'No validation object specified.'
},
selector : { selector : {
message : '.error.message',
field : 'input, textarea, select',
group : '.field', group : '.field',
input : 'input',
prompt : '.prompt', prompt : '.prompt',
field : 'input, textarea, select' submit : '.submit'
}, },
className : { className : {
error : 'error', error : 'error',
prompt : 'prompt' down : 'down',
label : 'ui label prompt'
},
// errors
errors: {
method : 'The method you called is not defined.'
},
defaults: {
firstName: {
identifier : 'first-name',
rules: [
{
type : 'empty',
prompt : 'Please enter your first name'
}
]
},
lastName: {
identifier : 'last-name',
rules: [
{
type : 'empty',
prompt : 'Please enter your last name'
}
]
},
username: {
identifier : 'username',
rules: [
{
type : 'empty',
prompt : 'Please enter a username'
}
]
},
email: {
identifier : 'email',
rules: [
{
type : 'empty',
prompt : 'Please enter your email'
},
{
type : 'email',
prompt : 'Please enter a valid email'
}
]
},
password: {
identifier : 'password',
rules: [
{
type : 'empty',
prompt : 'Please enter a password'
},
{
type : 'length[6]',
prompt : 'Your password must be at least 6 characters'
}
]
},
passwordConfirm: {
identifier : 'password-confirm',
rules: [
{
type : 'empty',
prompt : 'Please confirm your password'
},
{
identifier : 'password-confirm',
type : 'match[password]',
prompt : 'Please verify password matches'
}
]
},
terms: {
identifier : 'terms',
rules: [
{
type : 'checked',
prompt : 'You must agree to the terms and conditions'
}
]
}
},
templates: {
error: function(errors) {
var
html = '<ul class="list">'
;
$.each(errors, function(index, value) {
html += '<li>' + value + '</li>';
});
html += '</ul>';
return $(html);
},
prompt: function(errors) {
return $('<div/>')
.addClass('ui red pointing prompt label')
.html(errors[0])
;
}
}, },
rules: { rules: {

2
build/uncompressed/modules/dropdown.js

@ -394,7 +394,7 @@ $.fn.dropdown = function(parameters) {
debug: function() { debug: function() {
if(settings.debug) { if(settings.debug) {
module.performance.log(arguments[0]); module.performance.log(arguments[0]);
module.debug = Function.prototype.bind.call(console.log, console, settings.moduleName + ':'); module.debug = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
} }
}, },
verbose: function() { verbose: function() {

85
node/npm-debug.log

@ -1,85 +0,0 @@
0 info it worked if it ends with ok
1 verbose cli [ 'node',
1 verbose cli '/usr/bin/npm',
1 verbose cli 'install',
1 verbose cli 'grunt-bower-installer',
1 verbose cli '--save-dev' ]
2 info using npm@1.2.21
3 info using node@v0.10.5
4 verbose node symlink /usr/bin/node
5 verbose read json /home/jack/quirky/semantic/node/package.json
6 verbose read json /home/jack/quirky/semantic/node/node_modules/bal-util/package.json
7 verbose read json /home/jack/quirky/semantic/node/node_modules/docpad/package.json
8 verbose read json /home/jack/quirky/semantic/node/node_modules/docpad-plugin-coffeescript/package.json
9 verbose read json /home/jack/quirky/semantic/node/node_modules/docpad-plugin-eco/package.json
10 verbose read json /home/jack/quirky/semantic/node/node_modules/docpad-plugin-ghpages/package.json
11 verbose read json /home/jack/quirky/semantic/node/node_modules/docpad-plugin-handlebars/package.json
12 verbose read json /home/jack/quirky/semantic/node/node_modules/docpad-plugin-html2coffee/package.json
13 verbose read json /home/jack/quirky/semantic/node/node_modules/docpad-plugin-jade/package.json
14 verbose read json /home/jack/quirky/semantic/node/node_modules/docpad-plugin-livereload/package.json
15 verbose read json /home/jack/quirky/semantic/node/node_modules/docpad-plugin-marked/package.json
16 verbose read json /home/jack/quirky/semantic/node/node_modules/docpad-plugin-paged/package.json
17 verbose read json /home/jack/quirky/semantic/node/node_modules/docpad-plugin-partials/package.json
18 verbose read json /home/jack/quirky/semantic/node/node_modules/docpad-plugin-stylus/package.json
19 verbose read json /home/jack/quirky/semantic/node/node_modules/docpad-plugin-text/package.json
20 verbose read json /home/jack/quirky/semantic/node/node_modules/grunt/package.json
21 verbose read json /home/jack/quirky/semantic/node/node_modules/grunt-bower-task/package.json
22 verbose read json /home/jack/quirky/semantic/node/node_modules/grunt-contrib-clean/package.json
23 verbose read json /home/jack/quirky/semantic/node/node_modules/grunt-contrib-copy/package.json
24 verbose read json /home/jack/quirky/semantic/node/node_modules/grunt-contrib-cssmin/package.json
25 verbose read json /home/jack/quirky/semantic/node/node_modules/grunt-contrib-less/package.json
26 verbose read json /home/jack/quirky/semantic/node/node_modules/grunt-contrib-uglify/package.json
27 verbose read json /home/jack/quirky/semantic/node/node_modules/grunt-contrib-watch/package.json
28 verbose read json /home/jack/quirky/semantic/node/node_modules/grunt-css/package.json
29 verbose read json /home/jack/quirky/semantic/node/node_modules/underscore/package.json
30 verbose from cache /home/jack/quirky/semantic/node/package.json
31 verbose readDependencies using package.json deps
32 verbose cache add [ 'grunt-bower-installer', null ]
33 verbose cache add name=undefined spec="grunt-bower-installer" args=["grunt-bower-installer",null]
34 verbose parsed url { protocol: null,
34 verbose parsed url slashes: null,
34 verbose parsed url auth: null,
34 verbose parsed url host: null,
34 verbose parsed url port: null,
34 verbose parsed url hostname: null,
34 verbose parsed url hash: null,
34 verbose parsed url search: null,
34 verbose parsed url query: null,
34 verbose parsed url pathname: 'grunt-bower-installer',
34 verbose parsed url path: 'grunt-bower-installer',
34 verbose parsed url href: 'grunt-bower-installer' }
35 silly lockFile 8289328e-grunt-bower-installer grunt-bower-installer
36 verbose lock grunt-bower-installer /home/jack/.npm/8289328e-grunt-bower-installer.lock
37 silly lockFile 8289328e-grunt-bower-installer grunt-bower-installer
38 silly lockFile 8289328e-grunt-bower-installer grunt-bower-installer
39 verbose addNamed [ 'grunt-bower-installer', '' ]
40 verbose addNamed [ null, '' ]
41 silly lockFile 550a3685-grunt-bower-installer grunt-bower-installer@
42 verbose lock grunt-bower-installer@ /home/jack/.npm/550a3685-grunt-bower-installer.lock
43 silly addNameRange { name: 'grunt-bower-installer', range: '', hasData: false }
44 verbose url raw grunt-bower-installer
45 verbose url resolving [ 'https://registry.npmjs.org/', './grunt-bower-installer' ]
46 verbose url resolved https://registry.npmjs.org/grunt-bower-installer
47 info trying registry request attempt 1 at 12:22:55
48 http GET https://registry.npmjs.org/grunt-bower-installer
49 http 404 https://registry.npmjs.org/grunt-bower-installer
50 silly registry.get cb [ 404,
50 silly registry.get { server: 'CouchDB/1.3.0 (Erlang OTP/R15B03)',
50 silly registry.get date: 'Thu, 23 May 2013 16:22:40 GMT',
50 silly registry.get 'content-type': 'application/json',
50 silly registry.get 'content-length': '52',
50 silly registry.get 'cache-control': 'must-revalidate' } ]
51 silly lockFile 550a3685-grunt-bower-installer grunt-bower-installer@
52 silly lockFile 550a3685-grunt-bower-installer grunt-bower-installer@
53 error 404 'grunt-bower-installer' is not in the npm registry.
53 error 404 You should bug the author to publish it
53 error 404
53 error 404 Note that you can also install from a
53 error 404 tarball, folder, or http url, or git url.
54 error System Linux 3.0.0-17-generic
55 error command "node" "/usr/bin/npm" "install" "grunt-bower-installer" "--save-dev"
56 error cwd /home/jack/quirky/semantic/node
57 error node -v v0.10.5
58 error npm -v 1.2.21
59 error code E404
60 verbose exit [ 1, true ]

6
node/src/documents/collections/form.html

@ -11,6 +11,7 @@ type : 'UI Collection'
<div class="container"> <div class="container">
<h1 class="ui dividing header">Form</h1> <h1 class="ui dividing header">Form</h1>
<p>Forms are a grouping of elements requiring user input.</p> <p>Forms are a grouping of elements requiring user input.</p>
<p>Form input can be validated using the <a href="/modules/form.html">form validation behavior</a></p>
<p> <p>
Forms always include fields, and fields always contain form elements. Fields themselves may also include: Forms always include fields, and fields always contain form elements. Fields themselves may also include:
<a href="#">standard form fields</a>, like labels, inputs and textareas, as well as: <a href="#">standard form fields</a>, like labels, inputs and textareas, as well as:
@ -40,6 +41,9 @@ type : 'UI Collection'
</div> </div>
<div class="ui form segment"> <div class="ui form segment">
<p>Let's go ahead and get you signed up.</p> <p>Let's go ahead and get you signed up.</p>
<div class="ui error message">
<div class="header">We noticed some issues</div>
</div>
<div class="two fields"> <div class="two fields">
<div class="field"> <div class="field">
<label>First Name</label> <label>First Name</label>
@ -160,7 +164,7 @@ type : 'UI Collection'
<div class="example"> <div class="example">
<h4 class="ui header">Text Block</h4> <h4 class="ui header">Text Block</h4>
<p>Text blocks have special meaning inside a form tag. All message blocks are hidden by default.</p> <p>Text blocks have special meaning inside a form tag. Any info, error, or warning message blocks found inside a form are hidden by default.</p>
<div class="ui form"> <div class="ui form">
<div class="ui message"> <div class="ui message">
<div class="header">We had some issues</div> <div class="header">We had some issues</div>

1
node/src/documents/collections/menu.html

@ -33,6 +33,7 @@ type : 'UI Collection'
</a> </a>
<a class="item"> <a class="item">
<i class="icon mail"></i> Messages <i class="icon mail"></i> Messages
<span class="ui label">22</span>
</a> </a>
<a class="item"> <a class="item">
<i class="icon community"></i> Browse <i class="icon community"></i> Browse

17
node/src/files/components/semantic/collections/form.css

@ -112,6 +112,23 @@
.ui.form .message:first-child { .ui.form .message:first-child {
margin-top: 0px; margin-top: 0px;
} }
/*--------------------
Validation Prompt
---------------------*/
.ui.form .field .prompt.label {
white-space: nowrap;
}
.ui.form .inline.field .prompt {
margin-top: 0em;
margin-left: 1em;
}
.ui.form .inline.field .prompt:before {
margin-top: -0.3em;
bottom: auto;
right: auto;
top: 50%;
left: 0em;
}
/******************************* /*******************************
States States
*******************************/ *******************************/

9
node/src/files/components/semantic/collections/menu.css

@ -199,10 +199,15 @@
---------------*/ ---------------*/
.ui.menu .item > .label, .ui.menu .item > .label,
.ui.menu .item > a > .label { .ui.menu .item > a > .label {
font-size: 0.9em; font-size: 0.8em;
margin: -0.3em 0em -0.3em 0.3em; margin: -0.3em 0em -0.3em 0.3em;
padding: 0.1em 0.5em; padding: 0.1em 0.8em;
vertical-align: baseline; vertical-align: baseline;
text-transform: none;
}
.ui.menu .item > .floating.label,
.ui.menu .item > a > .floating.label {
padding: 0.3em 0.8em;
} }
/*-------------- /*--------------
Images Images

10
node/src/files/components/semantic/elements/label.css

@ -15,7 +15,7 @@
.ui.label { .ui.label {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
background-color: #F5F5F5; background-color: #E8E8E8;
padding: 0.5em 0.8em; padding: 0.5em 0.8em;
color: rgba(0, 0, 0, 0.65); color: rgba(0, 0, 0, 0.65);
text-transform: uppercase; text-transform: uppercase;
@ -42,6 +42,7 @@ a.ui.label {
.ui.label .detail { .ui.label .detail {
display: inline-block; display: inline-block;
margin-left: 1em; margin-left: 1em;
font-weight: bold;
opacity: 0.8; opacity: 0.8;
} }
.ui.label .icon.close { .ui.label .icon.close {
@ -67,12 +68,12 @@ a.ui.label {
--------------------*/ --------------------*/
a.ui.labels .label:hover, a.ui.labels .label:hover,
a.ui.label:hover { a.ui.label:hover {
background-color: #F0F0F0; background-color: #E0E0E0;
color: rgba(0, 0, 0, 0.7); color: rgba(0, 0, 0, 0.7);
} }
.ui.labels a.label:hover:before, .ui.labels a.label:hover:before,
a.ui.label:hover:before { a.ui.label:hover:before {
background-color: #F0F0F0; background-color: #E0E0E0;
color: rgba(0, 0, 0, 0.7); color: rgba(0, 0, 0, 0.7);
} }
.ui.label .icon.close:hover { .ui.label .icon.close:hover {
@ -341,6 +342,9 @@ a.ui.teal.tag.label:hover:before {
; ;
} }
/*--- Above ---*/ /*--- Above ---*/
.ui.pointing.label:before {
background-color: #E8E8E8;
}
.ui.pointing.label, .ui.pointing.label,
.ui.pointing.above.label { .ui.pointing.above.label {
margin-top: 1em; margin-top: 1em;

458
node/src/files/components/semantic/modules/behavior/form.js

@ -3,7 +3,7 @@
Author: Jack Lukic Author: Jack Lukic
Notes: First Commit April 08, 2012 Notes: First Commit April 08, 2012
Refactored Feb 22, 2012 Refactored May 28, 2013
Allows you to validate forms based on a form validation object Allows you to validate forms based on a form validation object
Form validation objects are bound by either data-validate="" metadata, or form id or name tags Form validation objects are bound by either data-validate="" metadata, or form id or name tags
@ -12,32 +12,42 @@
;(function ( $, window, document, undefined ) { ;(function ( $, window, document, undefined ) {
$.fn.validateForm = function(fields, parameters) { $.fn.form = function(fields, parameters) {
var var
$allModules = $(this), $allModules = $(this),
settings = $.extend(true, {}, $.fn.validateForm.settings, parameters), settings = $.extend(true, {}, $.fn.form.settings, parameters),
// make arguments available validation = $.extend({}, $.fn.form.settings.defaults, fields),
eventNamespace = '.' + settings.namespace,
moduleNamespace = 'module-' + settings.namespace,
selector = $allModules.selector || '',
time = new Date().getTime(),
performance = [],
query = arguments[0], query = arguments[0],
passedArguments = [].slice.call(arguments, 1), methodInvoked = (typeof query == 'string'),
queryArguments = [].slice.call(arguments, 1),
invokedResponse invokedResponse
; ;
$allModules $allModules
.each(function() { .each(function() {
var var
$module = $(this), $module = $(this),
$group = $(this).find(settings.selector.group),
$field = $(this).find(settings.selector.field), $field = $(this).find(settings.selector.field),
$errorPrompt = $(this).find(settings.selector.prompt), $group = $(this).find(settings.selector.group),
$message = $(this).find(settings.selector.message),
$prompt = $(this).find(settings.selector.prompt),
$submit = $(this).find(settings.selector.submit),
formErrors = [], formErrors = [],
selector = $module.selector || '',
element = this, element = this,
instance = $module.data('module-' + settings.namespace), instance = $module.data('module-' + settings.namespace),
methodInvoked = (typeof query == 'string'),
namespace = settings.namespace, namespace = settings.namespace,
selector = settings.selector,
metadata = settings.metadata, metadata = settings.metadata,
className = settings.className, className = settings.className,
errors = settings.errors, errors = settings.errors,
@ -48,21 +58,20 @@ $.fn.validateForm = function(fields, parameters) {
initialize: function() { initialize: function() {
module.verbose('Initializing form validation'); module.verbose('Initializing form validation');
if(fields !== undefined || !$.isEmptyObject(fields) ) { if(settings.keyboardShortcuts) {
// add default text if set $field
if($.fn.defaultText !== undefined) { .on('keydown' + eventNamespace, module.event.field.keydown)
$.each(fields, function(fieldName, field) { ;
module.field.add.defaultText(field);
});
} }
// attach event handler
$module $module
.on('submit.' + namespace, module.validate.form) .on('submit' + eventNamespace, module.validate.form)
;
$field
.on('change' + eventNamespace, module.event.field.change)
;
$submit
.on('click' + eventNamespace, module.submit)
; ;
}
else {
module.error(errors.noFields, $module);
}
}, },
destroy: function() { destroy: function() {
@ -71,11 +80,66 @@ $.fn.validateForm = function(fields, parameters) {
; ;
}, },
refresh: function() {
$field = $module.find(selector.field);
},
submit: function() {
module.verbose('Submitting form', $module);
$module.submit();
},
event: {
field: { field: {
find: function(identifier) { keydown: function(event) {
var var
$field = $module.find(settings.selector.field) $field = $(this),
key = event.which,
keyCode = {
enter : 13,
escape : 27
}
; ;
if( key == keyCode.escape) {
module.verbose('Escape key pressed blurring field');
$field.blur();
}
if( 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();
},
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: {
field: function(identifier) {
if( $field.filter('#' + identifier).size() > 0 ) { if( $field.filter('#' + identifier).size() > 0 ) {
return $field.filter('#' + identifier); return $field.filter('#' + identifier);
} }
@ -87,54 +151,67 @@ $.fn.validateForm = function(fields, parameters) {
} }
return $('<input/>'); return $('<input/>');
}, },
add: { validation: function($field) {
defaultText: function(field) {
var var
$field = module.field.find(field.identifier) rules
; ;
if(field.defaultText !== undefined) { $.each(validation, function(fieldName, field) {
$field.defaultText(field.defaultText); if( module.get.field(field.identifier).get(0) == $field.get(0) ) {
rules = field;
}
});
return rules || false;
} }
}, },
error: function(field, errors) {
add: {
prompt: function(field, errors) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
$errorGroup = $field.closest($group), $fieldGroup = $field.closest($group),
$errorPrompt = $group.find($errorPrompt), $prompt = $fieldGroup.find(selector.prompt),
promptExists = ($errorPrompt.size() !== 0) promptExists = ($prompt.size() !== 0)
; ;
$errorGroup module.verbose('Adding inline validation prompt');
$fieldGroup
.addClass(className.error) .addClass(className.error)
; ;
if(settings.inlineError) { if(settings.inlineError) {
// create message container on first invalid validation attempt
if(!promptExists) { if(!promptExists) {
$errorPrompt = $('<div />') $prompt = settings.templates.prompt(errors);
.addClass(className.prompt) $prompt
.insertBefore($field) .appendTo($fieldGroup)
.hide()
; ;
} }
// add prompt message $prompt
$errorPrompt
.html(errors[0]) .html(errors[0])
.fadeIn(settings.animateSpeed)
; ;
if($prompt.is(':not(:visible)')) {
$prompt.fadeIn(200);
}
} }
},
errors: function(errors) {
module.debug('Adding form error messages', errors);
$message
.html( settings.templates.error(errors) )
;
} }
}, },
remove: { remove: {
error: function(field) { prompt: function(field) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
$errorGroup = $field.closest($group), $fieldGroup = $field.closest($group),
$errorPrompt = $group.find($errorPrompt) $prompt = $group.find($prompt)
; ;
$errorGroup $fieldGroup
.removeClass(className.error) .removeClass(className.error)
; ;
if(settings.inlineError) { if(settings.inlineError) {
$errorPrompt.hide(); $prompt.hide();
}
} }
} }
}, },
@ -147,28 +224,32 @@ $.fn.validateForm = function(fields, parameters) {
; ;
// reset errors // reset errors
formErrors = []; formErrors = [];
$.each(fields, function(fieldName, field){ $.each(validation, function(fieldName, field){
// form is invalid after first bad field, but keep checking
if( !( module.validate.field(field) ) ) { if( !( module.validate.field(field) ) ) {
allValid = false; allValid = false;
} }
}); });
// Evaluate form callbacks if(allValid) {
return (allValid) $module.removeClass(className.error);
? $.proxy(settings.onSuccess, this)(event) $.proxy(settings.onSuccess, this)(event);
: $.proxy(settings.onFailure, this)(formErrors) }
; else {
$module.addClass(className.error);
if(!settings.inlineError) {
module.add.errors(formErrors);
}
$.proxy(settings.onFailure, this)(formErrors);
}
}, },
// takes a validation object and returns whether field passes validation // takes a validation object and returns whether field passes validation
field: function(field) { field: function(field) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
fieldValid = true, fieldValid = true,
fieldErrors = [] fieldErrors = []
; ;
if(field.rules !== undefined) { if(field.rules !== undefined) {
// iterate over all validation types for a certain field
$.each(field.rules, function(index, rule) { $.each(field.rules, function(index, rule) {
if( !( module.validate.rule(field, rule) ) ) { if( !( module.validate.rule(field, rule) ) ) {
module.debug('Field is invalid', field.identifier, rule.type); module.debug('Field is invalid', field.identifier, rule.type);
@ -178,12 +259,12 @@ $.fn.validateForm = function(fields, parameters) {
}); });
} }
if(fieldValid) { if(fieldValid) {
module.field.remove.error(field, fieldErrors); module.remove.prompt(field, fieldErrors);
settings.onValid($field); $.proxy(settings.onValid, $field)();
} }
else { else {
formErrors = formErrors.concat(fieldErrors); formErrors = formErrors.concat(fieldErrors);
module.field.add.error(field, fieldErrors); module.add.prompt(field, fieldErrors);
$.proxy(settings.onInvalid, $field)(fieldErrors); $.proxy(settings.onInvalid, $field)(fieldErrors);
return false; return false;
} }
@ -193,14 +274,9 @@ $.fn.validateForm = function(fields, parameters) {
// takes validation rule and returns whether field passes rule // takes validation rule and returns whether field passes rule
rule: function(field, validation) { rule: function(field, validation) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
type = validation.type, type = validation.type,
defaultText = (field.defaultText !== undefined) value = $field.val(),
? field.defaultText
: false,
value = ($field.val() == defaultText)
? ''
: $field.val(),
bracketRegExp = /\[(.*?)\]/i, bracketRegExp = /\[(.*?)\]/i,
bracket = bracketRegExp.exec(type), bracket = bracketRegExp.exec(type),
@ -225,51 +301,104 @@ $.fn.validateForm = function(fields, parameters) {
} }
}, },
/* standard module */
setting: function(name, value) { setting: function(name, value) {
if(value === undefined) { if(value !== undefined) {
return settings[name]; if( $.isPlainObject(name) ) {
$.extend(true, settings, name);
} }
else {
settings[name] = value; settings[name] = value;
}
}
else {
return settings[name];
}
}, },
verbose: function() { internal: function(name, value) {
if(settings.verbose) { if(value !== undefined) {
module.debug.apply(this, arguments); if( $.isPlainObject(name) ) {
$.extend(true, module, name);
}
else {
module[name] = value;
}
}
else {
return module[name];
} }
}, },
debug: function() { debug: function() {
var
output = [],
message = settings.moduleName + ': ' + arguments[0],
variables = [].slice.call( arguments, 1 ),
log = console.info || console.log || function(){}
;
log = Function.prototype.bind.call(log, console);
if(settings.debug) { if(settings.debug) {
output.push(message); module.performance.log(arguments[0]);
log.apply(console, output.concat(variables) ); module.debug = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
}
},
verbose: function() {
if(settings.verbose && settings.debug) {
module.performance.log(arguments[0]);
module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
} }
}, },
error: function() { error: function() {
module.error = Function.prototype.bind.call(console.log, console, settings.moduleName + ':');
},
performance: {
log: function(message) {
var var
output = [], currentTime,
errorMessage = settings.moduleName + ': ' + arguments[0], executionTime,
variables = [].slice.call( arguments, 1 ), previousTime
log = console.warn || console.log || function(){}
; ;
log = Function.prototype.bind.call(log, console); if(settings.performance) {
if(settings.debug) { currentTime = new Date().getTime();
output.push(errorMessage); previousTime = time || currentTime,
output.concat(variables); executionTime = currentTime - previousTime;
log.apply(console, output.concat(variables) ); time = currentTime;
performance.push({
'Element' : element,
'Name' : message,
'Execution Time' : executionTime
});
clearTimeout(module.performance.timer);
module.performance.timer = setTimeout(module.performance.display, 100);
}
},
display: function() {
var
title = settings.moduleName,
caption = settings.moduleName + ': ' + selector + '(' + $allModules.size() + ' elements)',
totalExecutionTime = 0
;
if(selector) {
title += 'Performance (' + selector + ')';
}
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
console.groupCollapsed(title);
if(console.table) {
$.each(performance, function(index, data) {
totalExecutionTime += data['Execution Time'];
});
console.table(performance);
}
else {
$.each(performance, function(index, data) {
totalExecutionTime += data['Execution Time'];
});
}
console.log('Total Execution Time:', totalExecutionTime +'ms');
console.groupEnd();
performance = [];
time = false;
}
} }
}, },
invoke: function(query, context, passedArguments) { invoke: function(query, passedArguments, context) {
var var
maxDepth, maxDepth,
found found
; ;
passedArguments = passedArguments || [].slice.call( arguments, 2 ); passedArguments = passedArguments || queryArguments;
context = element || context;
if(typeof query == 'string' && instance !== undefined) { if(typeof query == 'string' && instance !== undefined) {
query = query.split('.'); query = query.split('.');
maxDepth = query.length - 1; maxDepth = query.length - 1;
@ -287,42 +416,47 @@ $.fn.validateForm = function(fields, parameters) {
}); });
} }
if ( $.isFunction( found ) ) { if ( $.isFunction( found ) ) {
module.verbose('Executing invoked function', found);
return found.apply(context, passedArguments); return found.apply(context, passedArguments);
} }
// return retrieved variable or chain return found || false;
return found;
} }
}; };
// check for invoking internal method
if(methodInvoked) { if(methodInvoked) {
invokedResponse = module.invoke(query, this, passedArguments); if(instance === undefined) {
module.initialize();
}
invokedResponse = module.invoke(query);
} }
// otherwise initialize
else { else {
if(instance !== undefined) {
module.destroy();
}
module.initialize(); module.initialize();
} }
}) })
; ;
// chain or return queried method return (invokedResponse)
return (invokedResponse !== undefined)
? invokedResponse ? invokedResponse
: this : this
; ;
}; };
$.fn.validateForm.settings = { $.fn.form.settings = {
// module info // module info
moduleName : 'Validate Form Module', moduleName : 'Validate Form Module',
debug : true, debug : true,
verbose : false, verbose : true,
namespace : 'validate', namespace : 'validate',
keyboardShortcuts : true,
on : 'change',
animateSpeed : 150, animateSpeed : 150,
inlineError : false, inlineError : false,
onValid : function() {}, onValid : function() {},
onInvalid : function() {}, onInvalid : function() {},
onSuccess : function() { return true; }, onSuccess : function() { return true; },
@ -332,22 +466,122 @@ $.fn.validateForm.settings = {
validate: 'validate' validate: 'validate'
}, },
// errors
errors: {
method : 'The method you called is not defined.',
noFields : 'No validation object specified.'
},
selector : { selector : {
message : '.error.message',
field : 'input, textarea, select',
group : '.field', group : '.field',
input : 'input',
prompt : '.prompt', prompt : '.prompt',
field : 'input, textarea, select' submit : '.submit'
}, },
className : { className : {
error : 'error', error : 'error',
prompt : 'prompt' down : 'down',
label : 'ui label prompt'
},
// errors
errors: {
method : 'The method you called is not defined.'
},
defaults: {
firstName: {
identifier : 'first-name',
rules: [
{
type : 'empty',
prompt : 'Please enter your first name'
}
]
},
lastName: {
identifier : 'last-name',
rules: [
{
type : 'empty',
prompt : 'Please enter your last name'
}
]
},
username: {
identifier : 'username',
rules: [
{
type : 'empty',
prompt : 'Please enter a username'
}
]
},
email: {
identifier : 'email',
rules: [
{
type : 'empty',
prompt : 'Please enter your email'
},
{
type : 'email',
prompt : 'Please enter a valid email'
}
]
},
password: {
identifier : 'password',
rules: [
{
type : 'empty',
prompt : 'Please enter a password'
},
{
type : 'length[6]',
prompt : 'Your password must be at least 6 characters'
}
]
},
passwordConfirm: {
identifier : 'password-confirm',
rules: [
{
type : 'empty',
prompt : 'Please confirm your password'
},
{
identifier : 'password-confirm',
type : 'match[password]',
prompt : 'Please verify password matches'
}
]
},
terms: {
identifier : 'terms',
rules: [
{
type : 'checked',
prompt : 'You must agree to the terms and conditions'
}
]
}
},
templates: {
error: function(errors) {
var
html = '<ul class="list">'
;
$.each(errors, function(index, value) {
html += '<li>' + value + '</li>';
});
html += '</ul>';
return $(html);
},
prompt: function(errors) {
return $('<div/>')
.addClass('ui red pointing prompt label')
.html(errors[0])
;
}
}, },
rules: { rules: {

2
node/src/files/components/semantic/modules/dropdown.js

@ -394,7 +394,7 @@ $.fn.dropdown = function(parameters) {
debug: function() { debug: function() {
if(settings.debug) { if(settings.debug) {
module.performance.log(arguments[0]); module.performance.log(arguments[0]);
module.debug = Function.prototype.bind.call(console.log, console, settings.moduleName + ':'); module.debug = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
} }
}, },
verbose: function() { verbose: function() {

3
node/src/files/javascript/dropdown.js

@ -21,19 +21,16 @@ semantic.dropdown.ready = function() {
$dropdown $dropdown
.dropdown() .dropdown()
; ;
console.log($dropdown);
$formDropdown $formDropdown
.dropdown({ .dropdown({
action: 'form' action: 'form'
}) })
; ;
console.log($formDropdown);
$hoverDropdown $hoverDropdown
.dropdown({ .dropdown({
on: 'hover' on: 'hover'
}) })
; ;
console.log($hoverDropdown);
}; };

19
src/collections/form.less

@ -161,6 +161,25 @@
margin-top: 0px; margin-top: 0px;
} }
/*--------------------
Validation Prompt
---------------------*/
.ui.form .field .prompt.label {
white-space: nowrap;
}
.ui.form .inline.field .prompt {
margin-top: 0em;
margin-left: 1em;
}
.ui.form .inline.field .prompt:before {
margin-top: -0.3em;
bottom: auto;
right: auto;
top: 50%;
left: 0em;
}
/******************************* /*******************************
States States

9
src/collections/menu.less

@ -277,10 +277,15 @@
.ui.menu .item > .label, .ui.menu .item > .label,
.ui.menu .item > a > .label { .ui.menu .item > a > .label {
font-size: 0.9em; font-size: 0.8em;
margin: -0.3em 0em -0.3em 0.3em; margin: -0.3em 0em -0.3em 0.3em;
padding: 0.1em 0.5em; padding: 0.1em 0.8em;
vertical-align: baseline; vertical-align: baseline;
text-transform: none;
}
.ui.menu .item > .floating.label,
.ui.menu .item > a > .floating.label {
padding: 0.3em 0.8em;
} }
/*-------------- /*--------------

10
src/elements/label.less

@ -18,7 +18,7 @@
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
background-color: #F5F5F5; background-color: #E8E8E8;
padding: 0.5em 0.8em; padding: 0.5em 0.8em;
color: rgba(0, 0, 0, 0.65); color: rgba(0, 0, 0, 0.65);
@ -54,6 +54,7 @@ a.ui.label {
.ui.label .detail { .ui.label .detail {
display: inline-block; display: inline-block;
margin-left: 1em; margin-left: 1em;
font-weight: bold;
opacity: 0.8; opacity: 0.8;
} }
.ui.label .icon.close { .ui.label .icon.close {
@ -88,12 +89,12 @@ a.ui.label {
a.ui.labels .label:hover, a.ui.labels .label:hover,
a.ui.label:hover { a.ui.label:hover {
background-color: #F0F0F0; background-color: #E0E0E0;
color: rgba(0, 0, 0, 0.7); color: rgba(0, 0, 0, 0.7);
} }
.ui.labels a.label:hover:before, .ui.labels a.label:hover:before,
a.ui.label:hover:before { a.ui.label:hover:before {
background-color: #F0F0F0; background-color: #E0E0E0;
color: rgba(0, 0, 0, 0.7); color: rgba(0, 0, 0, 0.7);
} }
@ -421,6 +422,9 @@ a.ui.teal.tag.label:hover:before {
; ;
} }
/*--- Above ---*/ /*--- Above ---*/
.ui.pointing.label:before {
background-color: #E8E8E8;
}
.ui.pointing.label, .ui.pointing.label,
.ui.pointing.above.label { .ui.pointing.above.label {
margin-top: 1em; margin-top: 1em;

104
src/modules/behavior/default-text.js

@ -1,104 +0,0 @@
/* ******************************
Default Text (Form)
Author: Jack Lukic
Notes: First Commit April 08, 2012
Refactored Aug 13, 2012
allows you to set a default text value which will be added and removed on form field focus
****************************** */
;(function ( $, window, document, undefined ) {
$.fn.defaultText = function(parameters) {
var
// overload for shorthand to default value
settings = (typeof parameters == 'string')
? $.extend({}, $.fn.defaultText.settings, { defaultValue: parameters })
: $.extend(true, {}, $.fn.defaultText.settings, parameters)
;
// overload function
if(typeof parameters == 'string') {
parameters = { defaultValue: parameters };
}
$.extend(settings, parameters);
$(this)
.each(function() {
var
$element = $(this),
module = {
checkDefault: function() {
if($element.val().toLowerCase() != settings.defaultValue.toLowerCase()) {
$element.addClass(settings.filledClass);
}
},
placeholder: {
add: function(){
if( $element.filter(settings.disabledClassList).size() === 0 ) {
if( $element.val() == settings.replaceValue ) {
if(settings.alwaysReplace) {
$element
.removeClass(settings.filledClass)
.val($element.attr('last'))
.removeAttr('last')
;
}
else {
$element
.removeClass(settings.filledClass)
.val(settings.defaultValue)
;
}
}
else {
$element
.addClass(settings.filledClass)
;
}
}
},
remove: function() {
if( $element.filter(settings.disabledClassList).size() === 0 ) {
if(settings.alwaysReplace) {
$element
.attr('last', $element.val())
.val(settings.replaceValue)
;
}
else {
if( $element.val().toLowerCase() == settings.defaultValue.toLowerCase() ) {
$element
.val(settings.replaceValue)
;
}
}
}
}
}
}
;
if(settings.defaultValue == 'auto') {
settings.defaultValue = $(this).val();
}
$element
.on('focus', module.placeholder.remove)
.on('blur', module.placeholder.add)
;
// check for user value on load
module.checkDefault();
})
;
return this;
};
$.fn.defaultText.settings = {
defaultValue : 'auto',
replaceValue : '',
alwaysReplace : false,
disabledClassList : '.readonly, .disabled',
filledClass : 'filled'
};
})( jQuery, window , document );

458
src/modules/behavior/form.js

@ -3,7 +3,7 @@
Author: Jack Lukic Author: Jack Lukic
Notes: First Commit April 08, 2012 Notes: First Commit April 08, 2012
Refactored Feb 22, 2012 Refactored May 28, 2013
Allows you to validate forms based on a form validation object Allows you to validate forms based on a form validation object
Form validation objects are bound by either data-validate="" metadata, or form id or name tags Form validation objects are bound by either data-validate="" metadata, or form id or name tags
@ -12,32 +12,42 @@
;(function ( $, window, document, undefined ) { ;(function ( $, window, document, undefined ) {
$.fn.validateForm = function(fields, parameters) { $.fn.form = function(fields, parameters) {
var var
$allModules = $(this), $allModules = $(this),
settings = $.extend(true, {}, $.fn.validateForm.settings, parameters), settings = $.extend(true, {}, $.fn.form.settings, parameters),
// make arguments available validation = $.extend({}, $.fn.form.settings.defaults, fields),
eventNamespace = '.' + settings.namespace,
moduleNamespace = 'module-' + settings.namespace,
selector = $allModules.selector || '',
time = new Date().getTime(),
performance = [],
query = arguments[0], query = arguments[0],
passedArguments = [].slice.call(arguments, 1), methodInvoked = (typeof query == 'string'),
queryArguments = [].slice.call(arguments, 1),
invokedResponse invokedResponse
; ;
$allModules $allModules
.each(function() { .each(function() {
var var
$module = $(this), $module = $(this),
$group = $(this).find(settings.selector.group),
$field = $(this).find(settings.selector.field), $field = $(this).find(settings.selector.field),
$errorPrompt = $(this).find(settings.selector.prompt), $group = $(this).find(settings.selector.group),
$message = $(this).find(settings.selector.message),
$prompt = $(this).find(settings.selector.prompt),
$submit = $(this).find(settings.selector.submit),
formErrors = [], formErrors = [],
selector = $module.selector || '',
element = this, element = this,
instance = $module.data('module-' + settings.namespace), instance = $module.data('module-' + settings.namespace),
methodInvoked = (typeof query == 'string'),
namespace = settings.namespace, namespace = settings.namespace,
selector = settings.selector,
metadata = settings.metadata, metadata = settings.metadata,
className = settings.className, className = settings.className,
errors = settings.errors, errors = settings.errors,
@ -48,21 +58,20 @@ $.fn.validateForm = function(fields, parameters) {
initialize: function() { initialize: function() {
module.verbose('Initializing form validation'); module.verbose('Initializing form validation');
if(fields !== undefined || !$.isEmptyObject(fields) ) { if(settings.keyboardShortcuts) {
// add default text if set $field
if($.fn.defaultText !== undefined) { .on('keydown' + eventNamespace, module.event.field.keydown)
$.each(fields, function(fieldName, field) { ;
module.field.add.defaultText(field);
});
} }
// attach event handler
$module $module
.on('submit.' + namespace, module.validate.form) .on('submit' + eventNamespace, module.validate.form)
;
$field
.on('change' + eventNamespace, module.event.field.change)
;
$submit
.on('click' + eventNamespace, module.submit)
; ;
}
else {
module.error(errors.noFields, $module);
}
}, },
destroy: function() { destroy: function() {
@ -71,11 +80,66 @@ $.fn.validateForm = function(fields, parameters) {
; ;
}, },
refresh: function() {
$field = $module.find(selector.field);
},
submit: function() {
module.verbose('Submitting form', $module);
$module.submit();
},
event: {
field: { field: {
find: function(identifier) { keydown: function(event) {
var var
$field = $module.find(settings.selector.field) $field = $(this),
key = event.which,
keyCode = {
enter : 13,
escape : 27
}
; ;
if( key == keyCode.escape) {
module.verbose('Escape key pressed blurring field');
$field.blur();
}
if( 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();
},
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: {
field: function(identifier) {
if( $field.filter('#' + identifier).size() > 0 ) { if( $field.filter('#' + identifier).size() > 0 ) {
return $field.filter('#' + identifier); return $field.filter('#' + identifier);
} }
@ -87,54 +151,67 @@ $.fn.validateForm = function(fields, parameters) {
} }
return $('<input/>'); return $('<input/>');
}, },
add: { validation: function($field) {
defaultText: function(field) {
var var
$field = module.field.find(field.identifier) rules
; ;
if(field.defaultText !== undefined) { $.each(validation, function(fieldName, field) {
$field.defaultText(field.defaultText); if( module.get.field(field.identifier).get(0) == $field.get(0) ) {
rules = field;
}
});
return rules || false;
} }
}, },
error: function(field, errors) {
add: {
prompt: function(field, errors) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
$errorGroup = $field.closest($group), $fieldGroup = $field.closest($group),
$errorPrompt = $group.find($errorPrompt), $prompt = $fieldGroup.find(selector.prompt),
promptExists = ($errorPrompt.size() !== 0) promptExists = ($prompt.size() !== 0)
; ;
$errorGroup module.verbose('Adding inline validation prompt');
$fieldGroup
.addClass(className.error) .addClass(className.error)
; ;
if(settings.inlineError) { if(settings.inlineError) {
// create message container on first invalid validation attempt
if(!promptExists) { if(!promptExists) {
$errorPrompt = $('<div />') $prompt = settings.templates.prompt(errors);
.addClass(className.prompt) $prompt
.insertBefore($field) .appendTo($fieldGroup)
.hide()
; ;
} }
// add prompt message $prompt
$errorPrompt
.html(errors[0]) .html(errors[0])
.fadeIn(settings.animateSpeed)
; ;
if($prompt.is(':not(:visible)')) {
$prompt.fadeIn(200);
}
} }
},
errors: function(errors) {
module.debug('Adding form error messages', errors);
$message
.html( settings.templates.error(errors) )
;
} }
}, },
remove: { remove: {
error: function(field) { prompt: function(field) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
$errorGroup = $field.closest($group), $fieldGroup = $field.closest($group),
$errorPrompt = $group.find($errorPrompt) $prompt = $group.find($prompt)
; ;
$errorGroup $fieldGroup
.removeClass(className.error) .removeClass(className.error)
; ;
if(settings.inlineError) { if(settings.inlineError) {
$errorPrompt.hide(); $prompt.hide();
}
} }
} }
}, },
@ -147,28 +224,32 @@ $.fn.validateForm = function(fields, parameters) {
; ;
// reset errors // reset errors
formErrors = []; formErrors = [];
$.each(fields, function(fieldName, field){ $.each(validation, function(fieldName, field){
// form is invalid after first bad field, but keep checking
if( !( module.validate.field(field) ) ) { if( !( module.validate.field(field) ) ) {
allValid = false; allValid = false;
} }
}); });
// Evaluate form callbacks if(allValid) {
return (allValid) $module.removeClass(className.error);
? $.proxy(settings.onSuccess, this)(event) $.proxy(settings.onSuccess, this)(event);
: $.proxy(settings.onFailure, this)(formErrors) }
; else {
$module.addClass(className.error);
if(!settings.inlineError) {
module.add.errors(formErrors);
}
$.proxy(settings.onFailure, this)(formErrors);
}
}, },
// takes a validation object and returns whether field passes validation // takes a validation object and returns whether field passes validation
field: function(field) { field: function(field) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
fieldValid = true, fieldValid = true,
fieldErrors = [] fieldErrors = []
; ;
if(field.rules !== undefined) { if(field.rules !== undefined) {
// iterate over all validation types for a certain field
$.each(field.rules, function(index, rule) { $.each(field.rules, function(index, rule) {
if( !( module.validate.rule(field, rule) ) ) { if( !( module.validate.rule(field, rule) ) ) {
module.debug('Field is invalid', field.identifier, rule.type); module.debug('Field is invalid', field.identifier, rule.type);
@ -178,12 +259,12 @@ $.fn.validateForm = function(fields, parameters) {
}); });
} }
if(fieldValid) { if(fieldValid) {
module.field.remove.error(field, fieldErrors); module.remove.prompt(field, fieldErrors);
settings.onValid($field); $.proxy(settings.onValid, $field)();
} }
else { else {
formErrors = formErrors.concat(fieldErrors); formErrors = formErrors.concat(fieldErrors);
module.field.add.error(field, fieldErrors); module.add.prompt(field, fieldErrors);
$.proxy(settings.onInvalid, $field)(fieldErrors); $.proxy(settings.onInvalid, $field)(fieldErrors);
return false; return false;
} }
@ -193,14 +274,9 @@ $.fn.validateForm = function(fields, parameters) {
// takes validation rule and returns whether field passes rule // takes validation rule and returns whether field passes rule
rule: function(field, validation) { rule: function(field, validation) {
var var
$field = module.field.find(field.identifier), $field = module.get.field(field.identifier),
type = validation.type, type = validation.type,
defaultText = (field.defaultText !== undefined) value = $field.val(),
? field.defaultText
: false,
value = ($field.val() == defaultText)
? ''
: $field.val(),
bracketRegExp = /\[(.*?)\]/i, bracketRegExp = /\[(.*?)\]/i,
bracket = bracketRegExp.exec(type), bracket = bracketRegExp.exec(type),
@ -225,51 +301,104 @@ $.fn.validateForm = function(fields, parameters) {
} }
}, },
/* standard module */
setting: function(name, value) { setting: function(name, value) {
if(value === undefined) { if(value !== undefined) {
return settings[name]; if( $.isPlainObject(name) ) {
$.extend(true, settings, name);
} }
else {
settings[name] = value; settings[name] = value;
}
}
else {
return settings[name];
}
}, },
verbose: function() { internal: function(name, value) {
if(settings.verbose) { if(value !== undefined) {
module.debug.apply(this, arguments); if( $.isPlainObject(name) ) {
$.extend(true, module, name);
}
else {
module[name] = value;
}
}
else {
return module[name];
} }
}, },
debug: function() { debug: function() {
var
output = [],
message = settings.moduleName + ': ' + arguments[0],
variables = [].slice.call( arguments, 1 ),
log = console.info || console.log || function(){}
;
log = Function.prototype.bind.call(log, console);
if(settings.debug) { if(settings.debug) {
output.push(message); module.performance.log(arguments[0]);
log.apply(console, output.concat(variables) ); module.debug = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
}
},
verbose: function() {
if(settings.verbose && settings.debug) {
module.performance.log(arguments[0]);
module.verbose = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
} }
}, },
error: function() { error: function() {
module.error = Function.prototype.bind.call(console.log, console, settings.moduleName + ':');
},
performance: {
log: function(message) {
var var
output = [], currentTime,
errorMessage = settings.moduleName + ': ' + arguments[0], executionTime,
variables = [].slice.call( arguments, 1 ), previousTime
log = console.warn || console.log || function(){}
; ;
log = Function.prototype.bind.call(log, console); if(settings.performance) {
if(settings.debug) { currentTime = new Date().getTime();
output.push(errorMessage); previousTime = time || currentTime,
output.concat(variables); executionTime = currentTime - previousTime;
log.apply(console, output.concat(variables) ); time = currentTime;
performance.push({
'Element' : element,
'Name' : message,
'Execution Time' : executionTime
});
clearTimeout(module.performance.timer);
module.performance.timer = setTimeout(module.performance.display, 100);
}
},
display: function() {
var
title = settings.moduleName,
caption = settings.moduleName + ': ' + selector + '(' + $allModules.size() + ' elements)',
totalExecutionTime = 0
;
if(selector) {
title += 'Performance (' + selector + ')';
}
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
console.groupCollapsed(title);
if(console.table) {
$.each(performance, function(index, data) {
totalExecutionTime += data['Execution Time'];
});
console.table(performance);
}
else {
$.each(performance, function(index, data) {
totalExecutionTime += data['Execution Time'];
});
}
console.log('Total Execution Time:', totalExecutionTime +'ms');
console.groupEnd();
performance = [];
time = false;
}
} }
}, },
invoke: function(query, context, passedArguments) { invoke: function(query, passedArguments, context) {
var var
maxDepth, maxDepth,
found found
; ;
passedArguments = passedArguments || [].slice.call( arguments, 2 ); passedArguments = passedArguments || queryArguments;
context = element || context;
if(typeof query == 'string' && instance !== undefined) { if(typeof query == 'string' && instance !== undefined) {
query = query.split('.'); query = query.split('.');
maxDepth = query.length - 1; maxDepth = query.length - 1;
@ -287,42 +416,47 @@ $.fn.validateForm = function(fields, parameters) {
}); });
} }
if ( $.isFunction( found ) ) { if ( $.isFunction( found ) ) {
module.verbose('Executing invoked function', found);
return found.apply(context, passedArguments); return found.apply(context, passedArguments);
} }
// return retrieved variable or chain return found || false;
return found;
} }
}; };
// check for invoking internal method
if(methodInvoked) { if(methodInvoked) {
invokedResponse = module.invoke(query, this, passedArguments); if(instance === undefined) {
module.initialize();
}
invokedResponse = module.invoke(query);
} }
// otherwise initialize
else { else {
if(instance !== undefined) {
module.destroy();
}
module.initialize(); module.initialize();
} }
}) })
; ;
// chain or return queried method return (invokedResponse)
return (invokedResponse !== undefined)
? invokedResponse ? invokedResponse
: this : this
; ;
}; };
$.fn.validateForm.settings = { $.fn.form.settings = {
// module info // module info
moduleName : 'Validate Form Module', moduleName : 'Validate Form Module',
debug : true, debug : true,
verbose : false, verbose : true,
namespace : 'validate', namespace : 'validate',
keyboardShortcuts : true,
on : 'change',
animateSpeed : 150, animateSpeed : 150,
inlineError : false, inlineError : false,
onValid : function() {}, onValid : function() {},
onInvalid : function() {}, onInvalid : function() {},
onSuccess : function() { return true; }, onSuccess : function() { return true; },
@ -332,22 +466,122 @@ $.fn.validateForm.settings = {
validate: 'validate' validate: 'validate'
}, },
// errors
errors: {
method : 'The method you called is not defined.',
noFields : 'No validation object specified.'
},
selector : { selector : {
message : '.error.message',
field : 'input, textarea, select',
group : '.field', group : '.field',
input : 'input',
prompt : '.prompt', prompt : '.prompt',
field : 'input, textarea, select' submit : '.submit'
}, },
className : { className : {
error : 'error', error : 'error',
prompt : 'prompt' down : 'down',
label : 'ui label prompt'
},
// errors
errors: {
method : 'The method you called is not defined.'
},
defaults: {
firstName: {
identifier : 'first-name',
rules: [
{
type : 'empty',
prompt : 'Please enter your first name'
}
]
},
lastName: {
identifier : 'last-name',
rules: [
{
type : 'empty',
prompt : 'Please enter your last name'
}
]
},
username: {
identifier : 'username',
rules: [
{
type : 'empty',
prompt : 'Please enter a username'
}
]
},
email: {
identifier : 'email',
rules: [
{
type : 'empty',
prompt : 'Please enter your email'
},
{
type : 'email',
prompt : 'Please enter a valid email'
}
]
},
password: {
identifier : 'password',
rules: [
{
type : 'empty',
prompt : 'Please enter a password'
},
{
type : 'length[6]',
prompt : 'Your password must be at least 6 characters'
}
]
},
passwordConfirm: {
identifier : 'password-confirm',
rules: [
{
type : 'empty',
prompt : 'Please confirm your password'
},
{
identifier : 'password-confirm',
type : 'match[password]',
prompt : 'Please verify password matches'
}
]
},
terms: {
identifier : 'terms',
rules: [
{
type : 'checked',
prompt : 'You must agree to the terms and conditions'
}
]
}
},
templates: {
error: function(errors) {
var
html = '<ul class="list">'
;
$.each(errors, function(index, value) {
html += '<li>' + value + '</li>';
});
html += '</ul>';
return $(html);
},
prompt: function(errors) {
return $('<div/>')
.addClass('ui red pointing prompt label')
.html(errors[0])
;
}
}, },
rules: { rules: {

2
src/modules/dropdown.js

@ -394,7 +394,7 @@ $.fn.dropdown = function(parameters) {
debug: function() { debug: function() {
if(settings.debug) { if(settings.debug) {
module.performance.log(arguments[0]); module.performance.log(arguments[0]);
module.debug = Function.prototype.bind.call(console.log, console, settings.moduleName + ':'); module.debug = Function.prototype.bind.call(console.info, console, settings.moduleName + ':');
} }
}, },
verbose: function() { verbose: function() {

Loading…
Cancel
Save