summaryrefslogtreecommitdiff
path: root/views/js
diff options
context:
space:
mode:
authorDaniel Schmitzer <noreply@maennchen1.de>2016-01-14 14:55:36 +0000
committerDaniel Schmitzer <noreply@maennchen1.de>2016-01-14 14:55:36 +0000
commitad405c7045c6e242080ec9d3ce4c9e586b517c4f (patch)
treeb41905f4d27f3eaaabd5bad3a39f8d3873540b46 /views/js
- Testweise 4
git-svn-id: https://[internal]/wordpress/plugins/wpsg4@5261 0d5edaf7-2b12-4e95-93f4-047927463d4b
Diffstat (limited to 'views/js')
-rw-r--r--views/js/admin.js193
-rw-r--r--views/js/ajax.js0
-rw-r--r--views/js/ajaxupload.js672
-rw-r--r--views/js/editable.js576
-rw-r--r--views/js/frontend.js121
-rw-r--r--views/js/jquery-cluetip-master/.gitignore2
-rw-r--r--views/js/jquery-cluetip-master/images/darrowdown.gifbin0 -> 69 bytes
-rw-r--r--views/js/jquery-cluetip-master/images/darrowleft.gifbin0 -> 76 bytes
-rw-r--r--views/js/jquery-cluetip-master/images/darrowright.gifbin0 -> 77 bytes
-rw-r--r--views/js/jquery-cluetip-master/images/darrowup.gifbin0 -> 69 bytes
-rw-r--r--views/js/jquery-cluetip-master/jquery.cluetip.css241
-rw-r--r--views/js/jquery-cluetip-master/jquery.cluetip.js880
-rw-r--r--views/js/jquery-cluetip-master/jquery.cluetip.min.js7
-rw-r--r--views/js/jquery-validation-1.11.1/dist/additional-methods.js617
-rw-r--r--views/js/jquery-validation-1.11.1/dist/additional-methods.min.js2
-rw-r--r--views/js/jquery-validation-1.11.1/dist/jquery.validate.js1235
-rw-r--r--views/js/jquery-validation-1.11.1/dist/jquery.validate.min.js1237
-rw-r--r--views/js/jquery.cookie.js117
-rw-r--r--views/js/jquery.validationEngine-de.js131
-rw-r--r--views/js/jquery.validationEngine.js2077
-rw-r--r--views/js/mce_plugin.js45
-rw-r--r--views/js/wpsg_staffel.js117
22 files changed, 8270 insertions, 0 deletions
diff --git a/views/js/admin.js b/views/js/admin.js
new file mode 100644
index 0000000..4c0f7b6
--- /dev/null
+++ b/views/js/admin.js
@@ -0,0 +1,193 @@
+wpsg_number_format = function (number, decimals, dec_point, thousands_sep) {
+
+ var n = !isFinite(+number) ? 0 : + number, prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
+ sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
+ s = '',
+ toFixedFix = function (n, prec) {
+ var k = Math.pow(10, prec);
+ return '' + Math.round(n * k) / k; };
+ s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
+ if (s[0].length > 3) {
+ s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep); }
+ if ((s[1] || '').length < prec) {
+ s[1] = s[1] || '';
+ s[1] += new Array(prec - s[1].length + 1).join('0');
+ } return s.join(dec);
+ };
+
+ var wpsg_Tablefix = function(e, ui) {
+
+ ui.children().each(function() {
+
+ jQuery(this).width(jQuery(this).width());
+
+ } );
+
+ return ui;
+
+ };
+
+jQuery.fn.tipTip = function() {
+
+ if (jQuery(this).hasClass('tipTip')) return;
+ jQuery(this).addClass('tipTip');
+
+ jQuery(this).cluetip( {
+ width: '400px',
+ height: '400px',
+ activation: 'click',
+ sticky: true,
+ /*mouseOutClose: 'both',*/
+ closePosition: 'title',
+ arrows: true,
+ closeText: 'Schließen',
+ onActivate: function() {
+
+ jQuery('#cluetip').hide();
+
+ },
+ onShow: function() {
+
+ jQuery('.cluetip-title').prepend(jQuery('.cluetip-inner h1').first().text());
+ jQuery('.cluetip-inner h1').first().remove();
+
+ jQuery('.cluetip-inner').css('overflow-y', 'show');
+ jQuery('.cluetip-inner').css('height', 'auto');
+
+ var height_content = jQuery('.cluetip-inner').outerHeight();
+ var height_title = jQuery('.cluetip-title').outerHeight();
+
+ if (height_content < 400)
+ {
+
+ jQuery('.cluetip-outer').height((height_content + height_title) + "px");
+
+ }
+ else
+ {
+
+ jQuery('.cluetip-outer').height("400px");
+
+ jQuery('.cluetip-inner').css('overflow-y', 'scroll');
+ jQuery('.cluetip-inner').css('height', '332px');
+
+ }
+
+ }
+ } );
+
+};
+
+jQuery.fn.wpsg_adminbox = function(options) {
+
+ return this.each(function() {
+
+ var adminbox_id = jQuery(this).attr("id");
+
+ jQuery(this).find('.title').bind('click', function() {
+
+ var content = jQuery(this).next();
+
+ if (content.is(':visible'))
+ {
+
+ content.hide();
+ jQuery(this).css('border-bottom', '1px solid #AAAAAA');
+ jQuery.cookie(adminbox_id, '0', { expires: 14000 } );
+
+ }
+ else
+ {
+
+ content.show();
+ jQuery(this).css('border-bottom', '0px');
+ jQuery.cookie(adminbox_id, '1', { expires: 14000 } );
+
+ }
+
+ } );
+
+ if (jQuery.cookie(adminbox_id) == null || jQuery.cookie(adminbox_id) == 0)
+ {
+
+ jQuery(this).find('.title').click();
+
+ }
+
+ } );
+
+}
+
+jQuery.fn.wpsg_tab = function(options) {
+
+ return this.each(function() {
+
+ var tab_obj = jQuery(this);
+
+ // Init
+ tab_obj.find('.tabcontent').hide();
+ tab_obj.find('.tab').removeClass('akttab');
+
+ var aktTab = 1;
+
+ if (jQuery.cookie(options['cookiename']) != null && jQuery.cookie(options['cookiename']) > 0)
+ {
+ aktTab = jQuery.cookie(options['cookiename']);
+ }
+
+ jQuery('#tab' + aktTab).addClass('akttab');
+ jQuery('#tabcontent' + aktTab).show();
+
+ if (typeof options['tab' + aktTab] == 'function')
+ {
+ options['tab' + aktTab]();
+ }
+
+ tab_obj.find('.tab').bind('click', function() {
+
+ tab_obj.find('.tab').removeClass('akttab');
+ tab_obj.find('.tabcontent').hide();
+
+ jQuery(this).addClass('akttab');
+
+ var strID = jQuery(this).attr("id").replace(/tab/, '');
+ jQuery.cookie(options['cookiename'], strID, { expires: 14000 } );
+
+ jQuery('#tabcontent' + strID).show();
+
+ if (typeof options['tab' + strID] == 'function')
+ {
+ options['tab' + strID]();
+ }
+
+ } );
+
+ } );
+
+};
+
+/**
+ * jPlot - Custom Formatter functions
+ */
+wpsg_statistics_number_format = function (formatString, value) {
+ return wpsg_number_format(value, 2, ',', '.');
+}
+
+wpsg_statistics_integer_format = function (formatString, value) {
+ return wpsg_number_format(value, 0, ',', '.');
+}
+
+function wpsg_in_array(needle, haystack)
+{
+
+ var length = haystack.length;
+
+ for(var i = 0; i < length; i++) {
+
+ if (haystack[i] == needle) return true;
+
+ }
+
+ return false;
+
+}
diff --git a/views/js/ajax.js b/views/js/ajax.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/views/js/ajax.js
diff --git a/views/js/ajaxupload.js b/views/js/ajaxupload.js
new file mode 100644
index 0000000..a704008
--- /dev/null
+++ b/views/js/ajaxupload.js
@@ -0,0 +1,672 @@
+/**
+ * AJAX Upload ( http://valums.com/ajax-upload/ )
+ * Copyright (c) Andris Valums
+ * Licensed under the MIT license ( http://valums.com/mit-license/ )
+ * Thanks to Gary Haran, David Mark, Corey Burns and others for contributions
+ */
+(function () {
+ /* global window */
+ /* jslint browser: true, devel: true, undef: true, nomen: true, bitwise: true, regexp: true, newcap: true, immed: true */
+
+ /**
+ * Wrapper for FireBug's console.log
+ */
+ function log(){
+ if (typeof(console) != 'undefined' && typeof(console.log) == 'function'){
+ Array.prototype.unshift.call(arguments, '[Ajax Upload]');
+ console.log( Array.prototype.join.call(arguments, ' '));
+ }
+ }
+
+ /**
+ * Attaches event to a dom element.
+ * @param {Element} el
+ * @param type event name
+ * @param fn callback This refers to the passed element
+ */
+ function addEvent(el, type, fn){
+ if (el.addEventListener) {
+ el.addEventListener(type, fn, false);
+ } else if (el.attachEvent) {
+ el.attachEvent('on' + type, function(){
+ fn.call(el);
+ });
+ } else {
+ throw new Error('not supported or DOM not loaded');
+ }
+ }
+
+ /**
+ * Attaches resize event to a window, limiting
+ * number of event fired. Fires only when encounteres
+ * delay of 100 after series of events.
+ *
+ * Some browsers fire event multiple times when resizing
+ * http://www.quirksmode.org/dom/events/resize.html
+ *
+ * @param fn callback This refers to the passed element
+ */
+ function addResizeEvent(fn){
+ var timeout;
+
+ addEvent(window, 'resize', function(){
+ if (timeout){
+ clearTimeout(timeout);
+ }
+ timeout = setTimeout(fn, 100);
+ });
+ }
+
+ // Needs more testing, will be rewriten for next version
+ // getOffset function copied from jQuery lib (http://jquery.com/)
+ if (document.documentElement.getBoundingClientRect){
+ // Get Offset using getBoundingClientRect
+ // http://ejohn.org/blog/getboundingclientrect-is-awesome/
+ var getOffset = function(el){
+ var box = el.getBoundingClientRect();
+ var doc = el.ownerDocument;
+ var body = doc.body;
+ var docElem = doc.documentElement; // for ie
+ var clientTop = docElem.clientTop || body.clientTop || 0;
+ var clientLeft = docElem.clientLeft || body.clientLeft || 0;
+
+ // In Internet Explorer 7 getBoundingClientRect property is treated as physical,
+ // while others are logical. Make all logical, like in IE8.
+ var zoom = 1;
+ if (body.getBoundingClientRect) {
+ var bound = body.getBoundingClientRect();
+ zoom = (bound.right - bound.left) / body.clientWidth;
+ }
+
+ if (zoom > 1) {
+ clientTop = 0;
+ clientLeft = 0;
+ }
+
+ var top = box.top / zoom + (window.pageYOffset || docElem && docElem.scrollTop / zoom || body.scrollTop / zoom) - clientTop, left = box.left / zoom + (window.pageXOffset || docElem && docElem.scrollLeft / zoom || body.scrollLeft / zoom) - clientLeft;
+
+ return {
+ top: top,
+ left: left
+ };
+ };
+ } else {
+ // Get offset adding all offsets
+ var getOffset = function(el){
+ var top = 0, left = 0;
+ do {
+ top += el.offsetTop || 0;
+ left += el.offsetLeft || 0;
+ el = el.offsetParent;
+ } while (el);
+
+ return {
+ left: left,
+ top: top
+ };
+ };
+ }
+
+ /**
+ * Returns left, top, right and bottom properties describing the border-box,
+ * in pixels, with the top-left relative to the body
+ * @param {Element} el
+ * @return {Object} Contains left, top, right,bottom
+ */
+ function getBox(el){
+ var left, right, top, bottom;
+ var offset = getOffset(el);
+ left = offset.left;
+ top = offset.top;
+
+ right = left + el.offsetWidth;
+ bottom = top + el.offsetHeight;
+
+ return {
+ left: left,
+ right: right,
+ top: top,
+ bottom: bottom
+ };
+ }
+
+ /**
+ * Helper that takes object literal
+ * and add all properties to element.style
+ * @param {Element} el
+ * @param {Object} styles
+ */
+ function addStyles(el, styles){
+ for (var name in styles) {
+ if (styles.hasOwnProperty(name)) {
+ el.style[name] = styles[name];
+ }
+ }
+ }
+
+ /**
+ * Function places an absolutely positioned
+ * element on top of the specified element
+ * copying position and dimentions.
+ * @param {Element} from
+ * @param {Element} to
+ */
+ function copyLayout(from, to){
+ var box = getBox(from);
+
+ addStyles(to, {
+ position: 'absolute',
+ left : box.left + 'px',
+ top : box.top + 'px',
+ width : from.offsetWidth + 'px',
+ height : from.offsetHeight + 'px'
+ });
+ }
+
+ /**
+ * Creates and returns element from html chunk
+ * Uses innerHTML to create an element
+ */
+ var toElement = (function(){
+ var div = document.createElement('div');
+ return function(html){
+ div.innerHTML = html;
+ var el = div.firstChild;
+ return div.removeChild(el);
+ };
+ })();
+
+ /**
+ * Function generates unique id
+ * @return unique id
+ */
+ var getUID = (function(){
+ var id = 0;
+ return function(){
+ return 'ValumsAjaxUpload' + id++;
+ };
+ })();
+
+ /**
+ * Get file name from path
+ * @param {String} file path to file
+ * @return filename
+ */
+ function fileFromPath(file){
+ return file.replace(/.*(\/|\\)/, "");
+ }
+
+ /**
+ * Get file extension lowercase
+ * @param {String} file name
+ * @return file extenstion
+ */
+ function getExt(file){
+ return (-1 !== file.indexOf('.')) ? file.replace(/.*[.]/, '') : '';
+ }
+
+ function hasClass(el, name){
+ var re = new RegExp('\\b' + name + '\\b');
+ return re.test(el.className);
+ }
+ function addClass(el, name){
+ if ( ! hasClass(el, name)){
+ el.className += ' ' + name;
+ }
+ }
+ function removeClass(el, name){
+ var re = new RegExp('\\b' + name + '\\b');
+ el.className = el.className.replace(re, '');
+ }
+
+ function removeNode(el){
+ el.parentNode.removeChild(el);
+ }
+
+ /**
+ * Easy styling and uploading
+ * @constructor
+ * @param button An element you want convert to
+ * upload button. Tested dimentions up to 500x500px
+ * @param {Object} options See defaults below.
+ */
+ window.AjaxUpload = function(button, options){
+ this._settings = {
+ // Location of the server-side upload script
+ action: 'upload.php',
+ // File upload name
+ name: 'userfile',
+ // Additional data to send
+ data: {},
+ // Submit file as soon as it's selected
+ autoSubmit: true,
+ // The type of data that you're expecting back from the server.
+ // html and xml are detected automatically.
+ // Only useful when you are using json data as a response.
+ // Set to "json" in that case.
+ responseType: false,
+ // Class applied to button when mouse is hovered
+ hoverClass: 'hover',
+ // Class applied to button when AU is disabled
+ disabledClass: 'disabled',
+ // When user selects a file, useful with autoSubmit disabled
+ // You can return false to cancel upload
+ onChange: function(file, extension){
+ },
+ // Callback to fire before file is uploaded
+ // You can return false to cancel upload
+ onSubmit: function(file, extension){
+ },
+ // Fired when file upload is completed
+ // WARNING! DO NOT USE "FALSE" STRING AS A RESPONSE!
+ onComplete: function(file, response){
+ }
+ };
+
+ // Merge the users options with our defaults
+ for (var i in options) {
+ if (options.hasOwnProperty(i)){
+ this._settings[i] = options[i];
+ }
+ }
+
+ // button isn't necessary a dom element
+ if (button.jquery){
+ // jQuery object was passed
+ button = button[0];
+ } else if (typeof button == "string") {
+ if (/^#.*/.test(button)){
+ // If jQuery user passes #elementId don't break it
+ button = button.slice(1);
+ }
+
+ button = document.getElementById(button);
+ }
+
+ if ( ! button || button.nodeType !== 1){
+ throw new Error("Please make sure that you're passing a valid element");
+ }
+
+ if ( button.nodeName.toUpperCase() == 'A'){
+ // disable link
+ addEvent(button, 'click', function(e){
+ if (e && e.preventDefault){
+ e.preventDefault();
+ } else if (window.event){
+ window.event.returnValue = false;
+ }
+ });
+ }
+
+ // DOM element
+ this._button = button;
+ // DOM element
+ this._input = null;
+ // If disabled clicking on button won't do anything
+ this._disabled = false;
+
+ // if the button was disabled before refresh if will remain
+ // disabled in FireFox, let's fix it
+ this.enable();
+
+ this._rerouteClicks();
+ };
+
+ // assigning methods to our class
+ AjaxUpload.prototype = {
+ setData: function(data){
+ this._settings.data = data;
+ },
+ disable: function(){
+ addClass(this._button, this._settings.disabledClass);
+ this._disabled = true;
+
+ var nodeName = this._button.nodeName.toUpperCase();
+ if (nodeName == 'INPUT' || nodeName == 'BUTTON'){
+ this._button.setAttribute('disabled', 'disabled');
+ }
+
+ // hide input
+ if (this._input){
+ // We use visibility instead of display to fix problem with Safari 4
+ // The problem is that the value of input doesn't change if it
+ // has display none when user selects a file
+ this._input.parentNode.style.visibility = 'hidden';
+ }
+ },
+ enable: function(){
+ removeClass(this._button, this._settings.disabledClass);
+ this._button.removeAttribute('disabled');
+ this._disabled = false;
+
+ },
+ /**
+ * Creates invisible file input
+ * that will hover above the button
+ * <div><input type='file' /></div>
+ */
+ _createInput: function(){
+ var self = this;
+
+ var input = document.createElement("input");
+ input.setAttribute('type', 'file');
+ input.setAttribute('name', this._settings.name);
+
+ addStyles(input, {
+ 'position' : 'absolute',
+ // in Opera only 'browse' button
+ // is clickable and it is located at
+ // the right side of the input
+ 'right' : 0,
+ 'margin' : 0,
+ 'padding' : 0,
+ 'fontSize' : '480px',
+ 'cursor' : 'pointer'
+ });
+
+ var div = document.createElement("div");
+ addStyles(div, {
+ 'display' : 'block',
+ 'position' : 'absolute',
+ 'overflow' : 'hidden',
+ 'margin' : 0,
+ 'padding' : 0,
+ 'opacity' : 0,
+ // Make sure browse button is in the right side
+ // in Internet Explorer
+ 'direction' : 'ltr',
+ //Max zIndex supported by Opera 9.0-9.2
+ 'zIndex': 2147483583
+ });
+
+ // Make sure that element opacity exists.
+ // Otherwise use IE filter
+ if ( div.style.opacity !== "0") {
+ if (typeof(div.filters) == 'undefined'){
+ throw new Error('Opacity not supported by the browser');
+ }
+ div.style.filter = "alpha(opacity=0)";
+ }
+
+ addEvent(input, 'change', function(){
+
+ if ( ! input || input.value === ''){
+ return;
+ }
+
+ // Get filename from input, required
+ // as some browsers have path instead of it
+ var file = fileFromPath(input.value);
+
+ if (false === self._settings.onChange.call(self, file, getExt(file))){
+ self._clearInput();
+ return;
+ }
+
+ // Submit form when value is changed
+ if (self._settings.autoSubmit) {
+ self.submit();
+ }
+ });
+
+ addEvent(input, 'mouseover', function(){
+ addClass(self._button, self._settings.hoverClass);
+ });
+
+ addEvent(input, 'mouseout', function(){
+ removeClass(self._button, self._settings.hoverClass);
+
+ // We use visibility instead of display to fix problem with Safari 4
+ // The problem is that the value of input doesn't change if it
+ // has display none when user selects a file
+ input.parentNode.style.visibility = 'hidden';
+
+ });
+
+ div.appendChild(input);
+ document.body.appendChild(div);
+
+ this._input = input;
+ },
+ _clearInput : function(){
+ if (!this._input){
+ return;
+ }
+
+ removeNode(this._input.parentNode);
+ this._input = null;
+ this._createInput();
+
+ removeClass(this._button, this._settings.hoverClass);
+ },
+ /**
+ * Function makes sure that when user clicks upload button,
+ * the this._input is clicked instead
+ */
+ _rerouteClicks: function(){
+ var self = this;
+
+ // IE will later display 'access denied' error
+ // if you use using self._input.click()
+ // other browsers just ignore click()
+
+ addEvent(self._button, 'mouseover', function(){
+ if (self._disabled){
+ return;
+ }
+
+ if ( ! self._input){
+ self._createInput();
+ }
+
+ var div = self._input.parentNode;
+ copyLayout(self._button, div);
+ div.style.visibility = 'visible';
+
+ });
+
+
+ // commented because we now hide input on mouseleave
+ /**
+ * When the window is resized the elements
+ * can be misaligned if button position depends
+ * on window size
+ */
+ //addResizeEvent(function(){
+ // if (self._input){
+ // copyLayout(self._button, self._input.parentNode);
+ // }
+ //});
+
+ },
+ /**
+ * Creates iframe with unique name
+ * @return {Element} iframe
+ */
+ _createIframe: function(){
+ // We can't use getTime, because it sometimes return
+ // same value in safari :(
+ var id = getUID();
+
+ // We can't use following code as the name attribute
+ // won't be properly registered in IE6, and new window
+ // on form submit will open
+ // var iframe = document.createElement('iframe');
+ // iframe.setAttribute('name', id);
+
+ var iframe = toElement('<iframe src="javascript:false;" name="' + id + '" />');
+ // src="javascript:false; was added
+ // because it possibly removes ie6 prompt
+ // "This page contains both secure and nonsecure items"
+ // Anyway, it doesn't do any harm.
+ iframe.setAttribute('id', id);
+
+ iframe.style.display = 'none';
+ document.body.appendChild(iframe);
+
+ return iframe;
+ },
+ /**
+ * Creates form, that will be submitted to iframe
+ * @param {Element} iframe Where to submit
+ * @return {Element} form
+ */
+ _createForm: function(iframe){
+ var settings = this._settings;
+
+ // We can't use the following code in IE6
+ // var form = document.createElement('form');
+ // form.setAttribute('method', 'post');
+ // form.setAttribute('enctype', 'multipart/form-data');
+ // Because in this case file won't be attached to request
+ var form = toElement('<form method="post" enctype="multipart/form-data"></form>');
+
+ form.setAttribute('action', settings.action);
+ form.setAttribute('target', iframe.name);
+ form.style.display = 'none';
+ document.body.appendChild(form);
+
+ // Create hidden input element for each data key
+ for (var prop in settings.data) {
+ if (settings.data.hasOwnProperty(prop)){
+ var el = document.createElement("input");
+ el.setAttribute('type', 'hidden');
+ el.setAttribute('name', prop);
+ el.setAttribute('value', settings.data[prop]);
+ form.appendChild(el);
+ }
+ }
+ return form;
+ },
+ /**
+ * Gets response from iframe and fires onComplete event when ready
+ * @param iframe
+ * @param file Filename to use in onComplete callback
+ */
+ _getResponse : function(iframe, file){
+ // getting response
+ var toDeleteFlag = false, self = this, settings = this._settings;
+
+ addEvent(iframe, 'load', function(){
+
+ if (// For Safari
+ iframe.src == "javascript:'%3Chtml%3E%3C/html%3E';" ||
+ // For FF, IE
+ iframe.src == "javascript:'<html></html>';"){
+ // First time around, do not delete.
+ // We reload to blank page, so that reloading main page
+ // does not re-submit the post.
+
+ if (toDeleteFlag) {
+ // Fix busy state in FF3
+ setTimeout(function(){
+ removeNode(iframe);
+ }, 0);
+ }
+
+ return;
+ }
+
+ var doc = iframe.contentDocument ? iframe.contentDocument : window.frames[iframe.id].document;
+
+ // fixing Opera 9.26,10.00
+ if (doc.readyState && doc.readyState != 'complete') {
+ // Opera fires load event multiple times
+ // Even when the DOM is not ready yet
+ // this fix should not affect other browsers
+ return;
+ }
+
+ // fixing Opera 9.64
+ if (doc.body && doc.body.innerHTML == "false") {
+ // In Opera 9.64 event was fired second time
+ // when body.innerHTML changed from false
+ // to server response approx. after 1 sec
+ return;
+ }
+
+ var response;
+
+ if (doc.XMLDocument) {
+ // response is a xml document Internet Explorer property
+ response = doc.XMLDocument;
+ } else if (doc.body){
+ // response is html document or plain text
+ response = doc.body.innerHTML;
+
+ if (settings.responseType && settings.responseType.toLowerCase() == 'json') {
+ // If the document was sent as 'application/javascript' or
+ // 'text/javascript', then the browser wraps the text in a <pre>
+ // tag and performs html encoding on the contents. In this case,
+ // we need to pull the original text content from the text node's
+ // nodeValue property to retrieve the unmangled content.
+ // Note that IE6 only understands text/html
+ if (doc.body.firstChild && doc.body.firstChild.nodeName.toUpperCase() == 'PRE') {
+ response = doc.body.firstChild.firstChild.nodeValue;
+ }
+
+ if (response) {
+ response = eval("(" + response + ")");
+ } else {
+ response = {};
+ }
+ }
+ } else {
+ // response is a xml document
+ response = doc;
+ }
+
+ settings.onComplete.call(self, file, response);
+
+ // Reload blank page, so that reloading main page
+ // does not re-submit the post. Also, remember to
+ // delete the frame
+ toDeleteFlag = true;
+
+ // Fix IE mixed content issue
+ iframe.src = "javascript:'<html></html>';";
+ });
+ },
+ /**
+ * Upload file contained in this._input
+ */
+ submit: function(){
+ var self = this, settings = this._settings;
+
+ if ( ! this._input || this._input.value === ''){
+ return;
+ }
+
+ var file = fileFromPath(this._input.value);
+
+ // user returned false to cancel upload
+ if (false === settings.onSubmit.call(this, file, getExt(file))){
+ this._clearInput();
+ return;
+ }
+
+ // sending request
+ var iframe = this._createIframe();
+ var form = this._createForm(iframe);
+
+ // assuming following structure
+ // div -> input type='file'
+ removeNode(this._input.parentNode);
+ removeClass(self._button, self._settings.hoverClass);
+
+ form.appendChild(this._input);
+
+ form.submit();
+
+ // request set, clean up
+ removeNode(form); form = null;
+ removeNode(this._input); this._input = null;
+
+ // Get response from iframe and fire onComplete event when ready
+ this._getResponse(iframe, file);
+
+ // get ready for next request
+ this._createInput();
+ }
+ };
+})();
diff --git a/views/js/editable.js b/views/js/editable.js
new file mode 100644
index 0000000..362b001
--- /dev/null
+++ b/views/js/editable.js
@@ -0,0 +1,576 @@
+/*
+ * Jeditable - jQuery in place edit plugin
+ *
+ * Copyright (c) 2006-2009 Mika Tuupola, Dylan Verheul
+ *
+ * Licensed under the MIT license:
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * Project home:
+ * http://www.appelsiini.net/projects/jeditable
+ *
+ * Based on editable by Dylan Verheul <dylan_at_dyve.net>:
+ * http://www.dyve.net/jquery/?editable
+ *
+ */
+
+/**
+ * Version 1.7.1
+ *
+ * ** means there is basic unit tests for this parameter.
+ *
+ * @name Jeditable
+ * @type jQuery
+ * @param String target (POST) URL or function to send edited content to **
+ * @param Hash options additional options
+ * @param String options[method] method to use to send edited content (POST or PUT) **
+ * @param Function options[callback] Function to run after submitting edited content **
+ * @param String options[name] POST parameter name of edited content
+ * @param String options[id] POST parameter name of edited div id
+ * @param Hash options[submitdata] Extra parameters to send when submitting edited content.
+ * @param String options[type] text, textarea or select (or any 3rd party input type) **
+ * @param Integer options[rows] number of rows if using textarea **
+ * @param Integer options[cols] number of columns if using textarea **
+ * @param Mixed options[height] 'auto', 'none' or height in pixels **
+ * @param Mixed options[width] 'auto', 'none' or width in pixels **
+ * @param String options[loadurl] URL to fetch input content before editing **
+ * @param String options[loadtype] Request type for load url. Should be GET or POST.
+ * @param String options[loadtext] Text to display while loading external content.
+ * @param Mixed options[loaddata] Extra parameters to pass when fetching content before editing.
+ * @param Mixed options[data] Or content given as paramameter. String or function.**
+ * @param String options[indicator] indicator html to show when saving
+ * @param String options[tooltip] optional tooltip text via title attribute **
+ * @param String options[event] jQuery event such as 'click' of 'dblclick' **
+ * @param String options[submit] submit button value, empty means no button **
+ * @param String options[cancel] cancel button value, empty means no button **
+ * @param String options[cssclass] CSS class to apply to input form. 'inherit' to copy from parent. **
+ * @param String options[style] Style to apply to input form 'inherit' to copy from parent. **
+ * @param String options[select] true or false, when true text is highlighted ??
+ * @param String options[placeholder] Placeholder text or html to insert when element is empty. **
+ * @param String options[onblur] 'cancel', 'submit', 'ignore' or function ??
+ *
+ * @param Function options[onsubmit] function(settings, original) { ... } called before submit
+ * @param Function options[onreset] function(settings, original) { ... } called before reset
+ * @param Function options[onerror] function(settings, original, xhr) { ... } called on error
+ *
+ * @param Hash options[ajaxoptions] jQuery Ajax options. See docs.jquery.com.
+ *
+ */
+
+(function($) {
+
+ $.fn.editable = function(target, options) {
+
+ if ('disable' == target) {
+ $(this).data('disabled.editable', true);
+ return;
+ }
+ if ('enable' == target) {
+ $(this).data('disabled.editable', false);
+ return;
+ }
+ if ('destroy' == target) {
+ $(this)
+ .unbind($(this).data('event.editable'))
+ .removeData('disabled.editable')
+ .removeData('event.editable');
+ return;
+ }
+
+ var settings = $.extend({}, $.fn.editable.defaults, {target:target}, options);
+
+ /* setup some functions */
+ var plugin = $.editable.types[settings.type].plugin || function() { };
+ var submit = $.editable.types[settings.type].submit || function() { };
+ var buttons = $.editable.types[settings.type].buttons
+ || $.editable.types['defaults'].buttons;
+ var content = $.editable.types[settings.type].content
+ || $.editable.types['defaults'].content;
+ var element = $.editable.types[settings.type].element
+ || $.editable.types['defaults'].element;
+ var reset = $.editable.types[settings.type].reset
+ || $.editable.types['defaults'].reset;
+ var callback = settings.callback || function() { };
+ var onedit = settings.onedit || function() { };
+ var onsubmit = settings.onsubmit || function() { };
+ var onreset = settings.onreset || function() { };
+ var onerror = settings.onerror || reset;
+ var json = false;
+
+ /* show tooltip */
+ if (settings.tooltip) {
+ $(this).attr('title', settings.tooltip);
+ }
+
+ settings.autowidth = 'auto' == settings.width;
+ settings.autoheight = 'auto' == settings.height;
+
+ return this.each(function() {
+
+ /* save this to self because this changes when scope changes */
+ var self = this;
+
+ /* inlined block elements lose their width and height after first edit */
+ /* save them for later use as workaround */
+ var savedwidth = $(self).width();
+ var savedheight = $(self).height();
+
+ /* save so it can be later used by $.editable('destroy') */
+ $(this).data('event.editable', settings.event);
+
+ /* if element is empty add something clickable (if requested) */
+ if (!$.trim($(this).html())) {
+ $(this).html(settings.placeholder);
+ }
+
+ $(this).bind(settings.event, function(e) {
+
+ /* abort if disabled for this element */
+ if (true === $(this).data('disabled.editable')) {
+ return;
+ }
+
+ /* prevent throwing an exeption if edit field is clicked again */
+ if (self.editing) {
+ return;
+ }
+
+ /* abort if onedit hook returns false */
+ if (false === onedit.apply(this, [settings, self])) {
+ return;
+ }
+
+ /* prevent default action and bubbling */
+ e.preventDefault();
+ e.stopPropagation();
+
+ /* remove tooltip */
+ if (settings.tooltip) {
+ $(self).removeAttr('title');
+ }
+
+ /* figure out how wide and tall we are, saved width and height */
+ /* are workaround for http://dev.jquery.com/ticket/2190 */
+ if (0 == $(self).width()) {
+ //$(self).css('visibility', 'hidden');
+ settings.width = savedwidth;
+ settings.height = savedheight;
+ } else {
+ if (settings.width != 'none') {
+ settings.width =
+ settings.autowidth ? $(self).width() : settings.width;
+ }
+ if (settings.height != 'none') {
+ settings.height =
+ settings.autoheight ? $(self).height() : settings.height;
+ }
+ }
+ //$(this).css('visibility', '');
+
+ /* remove placeholder text, replace is here because of IE */
+ if ($(this).html().toLowerCase().replace(/(;|")/g, '') ==
+ settings.placeholder.toLowerCase().replace(/(;|")/g, '')) {
+ $(this).html('');
+ }
+
+ self.editing = true;
+ self.revert = $(self).html();
+ $(self).html('');
+
+ /* create the form object */
+ var form = $('<form />');
+
+ /* apply css or style or both */
+ if (settings.cssclass) {
+ if ('inherit' == settings.cssclass) {
+ form.attr('class', $(self).attr('class'));
+ } else {
+ form.attr('class', settings.cssclass);
+ }
+ }
+
+ if (settings.style) {
+ if ('inherit' == settings.style) {
+ form.attr('style', $(self).attr('style'));
+ /* IE needs the second line or display wont be inherited */
+ form.css('display', $(self).css('display'));
+ } else {
+ form.attr('style', settings.style);
+ }
+ }
+
+ /* add main input element to form and store it in input */
+ var input = element.apply(form, [settings, self]);
+
+ /* set input content via POST, GET, given data or existing value */
+ var input_content;
+
+ if (settings.loadurl) {
+ var t = setTimeout(function() {
+ input.disabled = true;
+ content.apply(form, [settings.loadtext, settings, self]);
+ }, 100);
+
+ var loaddata = {};
+ loaddata[settings.id] = self.id;
+ if ($.isFunction(settings.loaddata)) {
+ $.extend(loaddata, settings.loaddata.apply(self, [self.revert, settings]));
+ } else {
+ $.extend(loaddata, settings.loaddata);
+ }
+ $.ajax({
+ type : settings.loadtype,
+ url : settings.loadurl,
+ data : loaddata,
+ async : false,
+ success: function(result) {
+ window.clearTimeout(t);
+ input_content = result;
+ input.disabled = false;
+ }
+ });
+ } else if (settings.data) {
+ input_content = settings.data;
+ if ($.isFunction(settings.data)) {
+ input_content = settings.data.apply(self, [self.revert, settings]);
+ }
+ } else {
+ input_content = self.revert;
+ }
+ content.apply(form, [input_content, settings, self]);
+
+ input.attr('name', settings.name);
+
+ /* add buttons to the form */
+ buttons.apply(form, [settings, self]);
+
+ /* add created form to self */
+ $(self).append(form);
+
+ /* attach 3rd party plugin if requested */
+ plugin.apply(form, [settings, self]);
+
+ /* focus to first visible form element */
+ $(':input:visible:enabled:first', form).focus();
+
+ /* highlight input contents when requested */
+ if (settings.select) {
+ input.select();
+ }
+
+ /* discard changes if pressing esc */
+ input.keydown(function(e) {
+ if (e.keyCode == 27) {
+ e.preventDefault();
+ //self.reset();
+ reset.apply(form, [settings, self]);
+ }
+ });
+
+ /* discard, submit or nothing with changes when clicking outside */
+ /* do nothing is usable when navigating with tab */
+ var t;
+ if ('cancel' == settings.onblur) {
+ input.blur(function(e) {
+ /* prevent canceling if submit was clicked */
+ t = setTimeout(function() {
+ reset.apply(form, [settings, self]);
+ }, 500);
+ });
+ } else if ('submit' == settings.onblur) {
+ input.blur(function(e) {
+ /* prevent double submit if submit was clicked */
+ t = setTimeout(function() {
+ form.submit();
+ }, 200);
+ });
+ } else if ($.isFunction(settings.onblur)) {
+ input.blur(function(e) {
+ settings.onblur.apply(self, [input.val(), settings]);
+ });
+ } else {
+ input.blur(function(e) {
+ /* TODO: maybe something here */
+ });
+ }
+
+ form.submit(function(e) {
+
+ if (t) {
+ clearTimeout(t);
+ }
+
+ /* do no submit */
+ e.preventDefault();
+
+ /* call before submit hook. */
+ /* if it returns false abort submitting */
+ if (false !== onsubmit.apply(form, [settings, self])) {
+ /* custom inputs call before submit hook. */
+ /* if it returns false abort submitting */
+ if (false !== submit.apply(form, [settings, self])) {
+
+ /* check if given target is function */
+ if ($.isFunction(settings.target)) {
+ var str = settings.target.apply(self, [input.val(), settings]);
+ $(self).html(str);
+ self.editing = false;
+ callback.apply(self, [self.innerHTML, settings]);
+ /* TODO: this is not dry */
+ if (!$.trim($(self).html())) {
+ $(self).html(settings.placeholder);
+ }
+ } else {
+ /* add edited content and id of edited element to POST */
+ var submitdata = {};
+ submitdata[settings.name] = input.val();
+ submitdata[settings.id] = self.id;
+ /* add extra data to be POST:ed */
+ if ($.isFunction(settings.submitdata)) {
+ $.extend(submitdata, settings.submitdata.apply(self, [self.revert, settings]));
+ } else {
+ $.extend(submitdata, settings.submitdata);
+ }
+
+ /* quick and dirty PUT support */
+ if ('PUT' == settings.method) {
+ submitdata['_method'] = 'put';
+ }
+
+ /* show the saving indicator */
+ $(self).html(settings.indicator);
+
+ /* defaults for ajaxoptions */
+ var ajaxoptions = {
+ type : 'POST',
+ data : submitdata,
+ dataType: 'html',
+ url : settings.target,
+ success : function(result, status) {
+ if (ajaxoptions.dataType == 'html') {
+ $(self).html(result);
+ settings.data = result;
+ }
+ self.editing = false;
+ callback.apply(self, [result, settings]);
+ if (!$.trim($(self).html())) {
+ $(self).html(settings.placeholder);
+ }
+ },
+ error : function(xhr, status, error) {
+ onerror.apply(form, [settings, self, xhr]);
+ }
+ };
+
+ /* override with what is given in settings.ajaxoptions */
+ $.extend(ajaxoptions, settings.ajaxoptions);
+ $.ajax(ajaxoptions);
+
+ }
+ }
+ }
+
+ /* show tooltip again */
+ $(self).attr('title', settings.tooltip);
+
+ return false;
+ });
+ });
+
+ /* privileged methods */
+ this.reset = function(form) {
+ /* prevent calling reset twice when blurring */
+ if (this.editing) {
+ /* before reset hook, if it returns false abort reseting */
+ if (false !== onreset.apply(form, [settings, self])) {
+ $(self).html(self.revert);
+ self.editing = false;
+ if (!$.trim($(self).html())) {
+ $(self).html(settings.placeholder);
+ }
+ /* show tooltip again */
+ if (settings.tooltip) {
+ $(self).attr('title', settings.tooltip);
+ }
+ }
+ }
+ };
+ });
+
+ };
+
+
+ $.editable = {
+ types: {
+ defaults: {
+ element : function(settings, original) {
+ var input = $('<input type="hidden"></input>');
+ $(this).append(input);
+ return(input);
+ },
+ content : function(string, settings, original) {
+ $(':input:first', this).val(string);
+ },
+ reset : function(settings, original) {
+ original.reset(this);
+ },
+ buttons : function(settings, original) {
+ var form = this;
+ if (settings.submit) {
+ /* if given html string use that */
+ if (settings.submit.match(/>$/)) {
+ var submit = $(settings.submit).click(function() {
+ if (submit.attr("type") != "submit") {
+ form.submit();
+ }
+ });
+ /* otherwise use button with given string as text */
+ } else {
+ var submit = $('<button class="button" type="submit" />');
+ submit.html(settings.submit);
+ }
+ $(this).append(submit);
+ }
+ if (settings.cancel) {
+ /* if given html string use that */
+ if (settings.cancel.match(/>$/)) {
+ var cancel = $(settings.cancel);
+ /* otherwise use button with given string as text */
+ } else {
+ var cancel = $('<button type="cancel" />');
+ cancel.html(settings.cancel);
+ }
+ $(this).append(cancel);
+
+ $(cancel).click(function(event) {
+ //original.reset();
+ if ($.isFunction($.editable.types[settings.type].reset)) {
+ var reset = $.editable.types[settings.type].reset;
+ } else {
+ var reset = $.editable.types['defaults'].reset;
+ }
+ reset.apply(form, [settings, original]);
+ return false;
+ });
+ }
+ }
+ },
+ text: {
+ element : function(settings, original) {
+ var input = $('<input />');
+ if (settings.width != 'none') { input.width(settings.width); }
+ if (settings.height != 'none') { input.height(settings.height); }
+ /* https://bugzilla.mozilla.org/show_bug.cgi?id=236791 */
+ //input[0].setAttribute('autocomplete','off');
+ input.attr('autocomplete','off');
+ $(this).append(input);
+ return(input);
+ }
+ },
+ textarea: {
+ element : function(settings, original) {
+ var textarea = $('<textarea />');
+ if (settings.rows) {
+ textarea.attr('rows', settings.rows);
+ } else if (settings.height != "none") {
+ textarea.height(settings.height);
+ }
+ if (settings.cols) {
+ textarea.attr('cols', settings.cols);
+ } else if (settings.width != "none") {
+ textarea.width(settings.width);
+ }
+ $(this).append(textarea);
+ return(textarea);
+ }
+ },
+ select: {
+ element : function(settings, original) {
+ var select = $('<select />');
+ $(this).append(select);
+ return(select);
+ },
+ content : function(data, settings, original) {
+
+ if (typeof settings.json == "undefined")
+ {
+
+ /* If it is string assume it is json. */
+ if (String == data.constructor) {
+ eval ('var json = ' + data);
+ } else {
+ /* Otherwise assume it is a hash already. */
+ var json = data;
+ }
+
+ settings.json = json;
+
+ }
+ else
+ {
+
+ json = settings.json;
+
+ }
+
+ for (var key in json) {
+ if (!json.hasOwnProperty(key)) {
+ continue;
+ }
+ if ('selected' == key) {
+ continue;
+ }
+
+ if (typeof json[key]['name'] == 'string')
+ {
+
+ var option = $('<optgroup />').attr('label', json[key]['name']);
+
+ for (var key2 in json[key]['fields'])
+ {
+ option.append($('<option />').val(key2).append(json[key]['fields'][key2]));
+ }
+
+ }
+ else
+ {
+ var option = $('<option />').val(key).append(json[key]);
+ }
+
+ $('select', this).append(option);
+ }
+ /* Loop option again to set selected. IE needed this... */
+ $('select', this).find('option').each(function() {
+ if ($(this).val() == json['selected'] ||
+ $(this).text() == $.trim(original.revert)) {
+ $(this).attr('selected', 'selected');
+ }
+ });
+ }
+ }
+ },
+
+ /* Add new input type */
+ addInputType: function(name, input) {
+ $.editable.types[name] = input;
+ }
+ };
+
+ // publicly accessible defaults
+ $.fn.editable.defaults = {
+ name : 'value',
+ id : 'id',
+ type : 'text',
+ width : 'auto',
+ height : '25px',
+ event : 'click.editable',
+ onblur : 'cancel',
+ loadtype : 'GET',
+ loadtext : 'Loading...',
+ placeholder: 'Click to edit',
+ loaddata : {},
+ submitdata : {},
+ ajaxoptions: {}
+ };
+
+})(jQuery);
diff --git a/views/js/frontend.js b/views/js/frontend.js
new file mode 100644
index 0000000..b4b0119
--- /dev/null
+++ b/views/js/frontend.js
@@ -0,0 +1,121 @@
+
+ /**
+ * Funktion für das Modul basketteaser
+ * Fügt die Produkte im Warenkorb ein
+ */
+ function wpsg_mod_basketteaser_add(produkt_id)
+ {
+
+ var menge = jQuery('.wpsg_mod_basketteaser_row_' + produkt_id + ' input').val();
+
+ if (menge <= 0) menge = 1;
+
+ location.href = wpsg_ajax.ajaxurl + '?wpsg[menge]=' + menge + '&wpsg[produkt_id]=' + produkt_id + '&wpsg[submit]=1';
+
+ return false;
+
+ } // wpsg_mod_basketteaser_add(produkt_id)
+
+ function wpsg_customerquestion(url_redirect)
+ {
+
+ jQuery('body,html').addClass('wpsg_noscroll');
+ jQuery('body').append('<div id="wpsg_calc_layer"><div class="content"><img class="loading" src="' + wpsg_ajax.img_ajaxloading + '" alt="' + wpsg_ajax.label_pleasewait + '" /></div></div>');
+ jQuery.ajax( {
+ url: wpsg_ajax.url_basket,
+ data: {
+ 'wpsg[ajax]': 1,
+ 'wpsg[action]': 'customerquestion',
+ 'wpsg[url]': url_redirect
+ },
+ success: function(data) {
+
+ jQuery('#wpsg_calc_layer .content').html(data);
+
+ }
+ } );
+
+ return false;
+
+ }
+
+ wpsg_numberformat = function (number, decimals, dec_point, thousands_sep)
+ {
+
+ var n = !isFinite(+number) ? 0 : +number,
+ prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
+ sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
+ s = '',
+
+ toFixedFix = function (n, prec)
+ {
+
+ var k = Math.pow(10, prec);
+ return '' + Math.round(n * k) / k;
+ };
+
+ s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
+
+ if (s[0].length > 3)
+ {
+ s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
+ }
+ if ((s[1] || '').length < prec)
+ {
+
+ s[1] = s[1] || '';
+ s[1] += new Array(prec - s[1].length + 1).join('0');
+
+ }
+
+ return s.join(dec);
+
+ };
+
+ wpsg_tf = function(value)
+ {
+
+ if (value == null) return;
+ if (typeof value == "number") return parseFloat(value);
+
+ if (value.lastIndexOf(".") == -1)
+ {
+
+ // 1500,50
+ return parseFloat(value.replace(/,/, "."));
+
+ }
+ else
+ {
+
+ if (value.lastIndexOf(",") == -1)
+ {
+
+ // 1500.50
+ return parseFloat(value);
+
+ }
+ else
+ {
+
+ if (value.lastIndexOf(",") > value.lastIndexOf("."))
+ {
+
+ // 1.500,50
+ return parseFloat(value.replace(/\./, "").replace(/,/, "."));
+
+ }
+ else
+ {
+
+ // 1,500.50
+ return parseFloat(value.replace(/,/, ""));
+
+ }
+
+ }
+
+ }
+
+ };
+ \ No newline at end of file
diff --git a/views/js/jquery-cluetip-master/.gitignore b/views/js/jquery-cluetip-master/.gitignore
new file mode 100644
index 0000000..aa6c4c9
--- /dev/null
+++ b/views/js/jquery-cluetip-master/.gitignore
@@ -0,0 +1,2 @@
+.DS_Store
+demo-more* \ No newline at end of file
diff --git a/views/js/jquery-cluetip-master/images/darrowdown.gif b/views/js/jquery-cluetip-master/images/darrowdown.gif
new file mode 100644
index 0000000..e138d9b
--- /dev/null
+++ b/views/js/jquery-cluetip-master/images/darrowdown.gif
Binary files differ
diff --git a/views/js/jquery-cluetip-master/images/darrowleft.gif b/views/js/jquery-cluetip-master/images/darrowleft.gif
new file mode 100644
index 0000000..e22d11c
--- /dev/null
+++ b/views/js/jquery-cluetip-master/images/darrowleft.gif
Binary files differ
diff --git a/views/js/jquery-cluetip-master/images/darrowright.gif b/views/js/jquery-cluetip-master/images/darrowright.gif
new file mode 100644
index 0000000..d36d7e4
--- /dev/null
+++ b/views/js/jquery-cluetip-master/images/darrowright.gif
Binary files differ
diff --git a/views/js/jquery-cluetip-master/images/darrowup.gif b/views/js/jquery-cluetip-master/images/darrowup.gif
new file mode 100644
index 0000000..fd74057
--- /dev/null
+++ b/views/js/jquery-cluetip-master/images/darrowup.gif
Binary files differ
diff --git a/views/js/jquery-cluetip-master/jquery.cluetip.css b/views/js/jquery-cluetip-master/jquery.cluetip.css
new file mode 100644
index 0000000..12209d1
--- /dev/null
+++ b/views/js/jquery-cluetip-master/jquery.cluetip.css
@@ -0,0 +1,241 @@
+/* global */
+div.ui-cluetip {
+ font-size: 1em;
+}
+.ui-cluetip-header,
+.ui-cluetip-content {
+ padding: 12px;
+}
+.ui-cluetip-header {
+ font-size: 1em;
+ margin: 0;
+ overflow: hidden;
+}
+
+.cluetip-title .cluetip-close {
+ float: right;
+ position: relative;
+}
+.cluetip-close img {
+ border: 0;
+}
+
+#cluetip-waitimage {
+ width: 43px;
+ height: 11px;
+ position: absolute;
+ background-image: url(../../gfx/ajax-loader.gif);
+ background-repeat:no-repeat;
+ background-position:50% 50%;
+}
+.cluetip-arrows {
+ display: none;
+ position: absolute;
+ top: 0;
+ left: -11px;
+ width: 11px;
+ height: 22px;
+ background-repeat: no-repeat;
+ background-position: 0 0;
+ border-width: 0;
+}
+.cluetip-extra {
+ display: none;
+}
+
+/***************************************
+ =cluetipClass: 'default'
+-------------------------------------- */
+
+.cluetip-default,
+.cluetip-default .cluetip-outer {
+ background-color: #d9d9c2;
+}
+.cluetip-default .ui-cluetip-header {
+ background-color: #87876a;
+}
+
+
+/*
+.cluetip-default #cluetip-outer {
+ position: relative;
+ margin: 0;
+ background-color: #d9d9c2;
+}
+.cluetip-default h3#cluetip-title {
+ margin: 0 0 5px;
+ padding: 8px 10px 4px;
+ font-size: 1.1em;
+ font-weight: normal;
+ background-color: #87876a;
+ color: #fff;
+}
+.cluetip-default #cluetip-title a {
+ color: #d9d9c2;
+ font-size: 0.95em;
+}
+.cluetip-default #cluetip-inner {
+ padding: 10px;
+}
+.cluetip-default div#cluetip-close {
+ text-align: right;
+ margin: 0 5px 5px;
+ color: #900;
+}
+*/
+/* default arrows */
+div.cluetip-default .cluetip-arrows {
+ border-width: 0;
+ background: transparent none;
+}
+div.clue-right-default .cluetip-arrows {
+ background-image: url(images/darrowleft.gif);
+}
+div.clue-left-default .cluetip-arrows {
+ background-image: url(images/darrowright.gif);
+ left: 100%;
+ margin-right: -11px;
+}
+div.clue-top-default .cluetip-arrows {
+ background-image: url(images/darrowdown.gif);
+ top: 100%;
+ left: 50%;
+ margin-left: -11px;
+ width: 22px;
+ height: 11px;
+}
+div.clue-bottom-default .cluetip-arrows {
+ background-image: url(images/darrowup.gif);
+ top: -11px;
+ left: 50%;
+ margin-left: -11px;
+ width: 22px;
+ height: 11px;
+}
+
+/***************************************
+ =cluetipClass: 'jtip'
+-------------------------------------- */
+.cluetip-jtip {
+ background-color: #fff;
+}
+.cluetip-jtip .cluetip-outer {
+ border: 2px solid #ccc;
+ position: relative;
+ /*background-color: #fff;*/
+}
+
+.cluetip-jtip .cluetip-inner {
+ padding: 5px;
+ display: inline-block;
+}
+.cluetip-jtip div.cluetip-close {
+ text-align: right;
+ margin: 0 5px 0;
+ color: #900;
+}
+
+.cluetip-jtip .ui-cluetip-header {
+ background-color: #ccc;
+ padding: 6px;
+/* margin-bottom: 1em;*/
+}
+
+/* jtip arrows */
+div.cluetip-jtip .cluetip-arrows {
+ border-width: 0;
+ background: transparent none;
+}
+div.clue-right-jtip .cluetip-arrows {
+ background-image: url(images/arrowleft.gif);
+}
+div.clue-left-jtip .cluetip-arrows {
+ background-image: url(images/arrowright.gif);
+ left: 100%;
+ margin-right: -11px;
+}
+div.clue-top-jtip .cluetip-arrows {
+ background-image: url(images/arrowdown.gif);
+ top: 100%;
+ left: 50%;
+ width: 22px;
+ height: 11px;
+ margin-left: -11px;
+}
+div.clue-bottom-jtip .cluetip-arrows {
+ background-image: url(images/arrowup.gif);
+ top: -11px;
+ left: 50%;
+ width: 22px;
+ height: 11px;
+ margin-left: -11px;
+}
+
+/***************************************
+ =cluetipClass: 'rounded'
+-------------------------------------- */
+.cluetip-rounded {
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ background-color: #fff;
+ border: 1px solid #ccc;
+}
+
+.cluetip-rounded .cluetip-outer {
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ background-color: #fff;
+}
+
+.cluetip-rounded .cluetip-arrows {
+ border-color: #ccc;
+}
+
+/* need to be more specific here to override ThemeRoller defaults */
+div.cluetip-rounded .cluetip-arrows {
+ font-size: 0;
+ line-height: 0%;
+ width: 0;
+ height: 0;
+ border-style: solid;
+ background: transparent none;
+}
+div.clue-right-rounded .cluetip-arrows {
+ border-width: 11px 11px 11px 0;
+ border-top-color: transparent;
+ border-bottom-color: transparent;
+ border-left-color: transparent;
+}
+div.clue-left-rounded .cluetip-arrows {
+ left: 100%;
+ margin-right: -11px;
+ border-width: 11px 0 11px 11px;
+ border-top-color: transparent;
+ border-right-color: transparent;
+ border-bottom-color: transparent;
+
+}
+div.clue-top-rounded .cluetip-arrows {
+ top: 100%;
+ left: 50%;
+ border-width: 11px 11px 0 11px;
+ border-right-color: transparent;
+ border-bottom-color: transparent;
+ border-left-color: transparent;
+}
+.clue-bottom-rounded .cluetip-arrows {
+ top: -11px;
+ left: 50%;
+ border-width: 0 11px 11px 11px;
+ border-top-color: transparent;
+ border-right-color: transparent;
+ border-left-color: transparent;
+
+}
+/* stupid IE6 HasLayout hack */
+.cluetip-rounded .cluetip-title,
+.cluetip-rounded .cluetip-inner {
+ zoom: 1;
+}
diff --git a/views/js/jquery-cluetip-master/jquery.cluetip.js b/views/js/jquery-cluetip-master/jquery.cluetip.js
new file mode 100644
index 0000000..35808df
--- /dev/null
+++ b/views/js/jquery-cluetip-master/jquery.cluetip.js
@@ -0,0 +1,880 @@
+/*!
+ * clueTip - v1.2.9 - 2013-06-02
+ * http://plugins.learningjquery.com/cluetip/
+ * Copyright (c) 2013 Karl Swedberg
+ * Licensed MIT (http://www.opensource.org/licenses/mit-license.php)
+ */
+
+(function($) {
+
+ $.cluetip = {
+ version: '1.2.9',
+
+ // the HTML that will be used for the tooltip
+ template: ['<div>',
+ '<div class="cluetip-outer">',
+ '<h3 class="cluetip-title ui-widget-header ui-cluetip-header"></h3>',
+ '<div class="cluetip-inner ui-widget-content ui-cluetip-content"></div>',
+ '</div>',
+ '<div class="cluetip-extra"></div>',
+ '</div>'].join(''),
+
+ /* clueTip setup
+ * the setup options are applied each time .cluetip() is called,
+ * BUT only if <div id="cluetip"> is not already in the document
+ */
+ setup: {
+ // method to be used for inserting the clueTip into the DOM.
+ // Permitted values are 'appendTo', 'prependTo', 'insertBefore', and 'insertAfter'
+ insertionType: 'appendTo',
+ // element in the DOM the plugin will reference when inserting the clueTip.
+ insertionElement: 'body'
+ },
+
+ /*
+ * clueTip options
+ *
+ * each one can be explicitly overridden by changing its value.
+ * for example: $.cluetip.defaults.width = 200;
+ * or: $.fn.cluetip.defaults.width = 200; // for compatibility with previous clueTip versions
+ * would change the default width for all clueTips to 200.
+ *
+ * each one can also be overridden by passing an options map to the cluetip method.
+ * for example: $('a.example').cluetip({width: 200});
+ * would change the default width to 200 for clueTips invoked by a link with class of "example"
+ *
+ */
+ defaults: {
+ multiple: false, // Allow a new tooltip to be created for each .cluetip() call
+ width: 275, // The width of the clueTip
+ height: 'auto', // The height of the clueTip
+ cluezIndex: 97, // Sets the z-index style property of the clueTip
+ positionBy: 'auto', // Sets the type of positioning: 'auto', 'mouse','bottomTop', 'topBottom', fixed'
+ topOffset: 15, // Number of px to offset clueTip from top of invoking element
+ leftOffset: 15, // Number of px to offset clueTip from left of invoking element
+ snapToEdge: false, // For bottomTop and topBottom, snap to the top or bottom of the element.
+ local: false, // Whether to use content from the same page for the clueTip's body
+ localPrefix: null, // string to be prepended to the tip attribute if local is true
+ localIdSuffix: null, // string to be appended to the cluetip content element's id if local is true
+ hideLocal: true, // If local option is set to true, this determines whether local content
+ // to be shown in clueTip should be hidden at its original location
+ attribute: 'rel', // the attribute to be used for fetching the clueTip's body content
+ titleAttribute: 'title', // the attribute to be used for fetching the clueTip's title
+ splitTitle: '', // A character used to split the title attribute into the clueTip title and divs
+ // within the clueTip body. more info below [6]
+ escapeTitle: false, // whether to html escape the title attribute
+ showTitle: true, // show title bar of the clueTip, even if title attribute not set
+ cluetipClass: 'default',// class added to outermost clueTip div in the form of 'cluetip-' + clueTipClass.
+ hoverClass: '', // class applied to the invoking element onmouseover and removed onmouseout
+ waitImage: true, // whether to show a "loading" img, which is set in jquery.cluetip.css
+ cursor: 'help',
+ arrows: false, // if true, displays arrow on appropriate side of clueTip
+ dropShadow: true, // set to false if you don't want the drop-shadow effect on the clueTip
+ dropShadowSteps: 6, // adjusts the size of the drop shadow
+ sticky: false, // keep visible until manually closed
+ mouseOutClose: false, // close when clueTip is moused out: false, 'cluetip', 'link', 'both'
+ delayedClose: 50, // close clueTip on a timed delay
+ activation: 'hover', // set to 'click' to force user to click to show clueTip
+ // set to 'focus' to show on focus of a form element and hide on blur
+ clickThrough: true, // if true, and activation is not 'click', then clicking on link will take user to the link's href,
+ // even if href and tipAttribute are equal
+ tracking: false, // if true, clueTip will track mouse movement (experimental)
+ closePosition: 'top', // location of close text for sticky cluetips; can be 'top', 'bottom', 'title' or 'none'
+ closeText: 'Close', // text (or HTML) to to be clicked to close sticky clueTips
+ truncate: 0, // number of characters to truncate clueTip's contents. if 0, no truncation occurs
+
+ // effect and speed for opening clueTips
+ fx: {
+ open: 'show', // can be 'show' or 'slideDown' or 'fadeIn'
+ openSpeed: ''
+ },
+
+ // settings for when hoverIntent plugin is used
+ hoverIntent: {
+ sensitivity: 3,
+ interval: 50,
+ timeout: 0
+ },
+
+ // short-circuit function to run just before clueTip is shown.
+ onActivate: function(e) {return true;},
+ // function to run just after clueTip is shown.
+ onShow: function(ct, ci){},
+ // function to run just after clueTip is hidden.
+ onHide: function(ct, ci){},
+ // whether to cache results of ajax request to avoid unnecessary hits to server
+ ajaxCache: true,
+
+ // process data retrieved via xhr before it's displayed
+ ajaxProcess: function(data) {
+ data = data.replace(/<(script|style|title)[^<]+<\/(script|style|title)>/gm, '').replace(/<(link|meta)[^>]+>/g,'');
+ return data;
+ },
+
+ // can pass in standard $.ajax() parameters. Callback functions, such as beforeSend,
+ // will be queued first within the default callbacks.
+ // The only exception is error, which overrides the default
+ ajaxSettings: {
+ // error: function(ct, ci) { /* override default error callback */ },
+ // beforeSend: function(ct, ci) { /* called first within default beforeSend callback */ },
+ dataType: 'html'
+ },
+ debug: false
+
+ }
+ };
+ var $cluetipWait,
+ standardClasses = 'cluetip ui-widget ui-widget-content ui-cluetip',
+ caches = {},
+ counter = 0,
+ imgCount = 0;
+
+ // use $.fn.prop() if available (jQuery 1.6+); otherwise, $.fn.attr()
+ $.fn.attrProp = $.fn.prop || $.fn.attr;
+
+ // .cluetip() method
+ $.fn.cluetip = function(js, options) {
+ var $cluetip, $cluetipInner, $cluetipOuter, $cluetipTitle, $cluetipArrows, $dropShadow;
+ if (typeof js == 'object') {
+ options = js;
+ js = null;
+ }
+ if (js == 'destroy') {
+ this.each(function(index) {
+ var $l = $(this),
+ data = $l.data('cluetip');
+ if ( data ) {
+ $(data.selector).remove();
+ $.removeData(this, 'title');
+ $.removeData(this, 'cluetip');
+ }
+ if (data.title) {
+ $l.attrProp('title', data.title);
+ }
+ $l.unbind('.cluetip').unbind('cluetipMoc');
+ });
+ if ( !$('[id^="cluetip"]').length ) {
+ $(document).unbind('.cluetip');
+ }
+ return this;
+ }
+
+ // merge per-call options with defaults
+ options = $.extend(true, {}, $.cluetip.defaults, options || {});
+
+ /** =create cluetip divs **/
+ counter++;
+ var cluezIndex,
+ cluetipId = $.cluetip.backCompat || !options.multiple ? 'cluetip' : 'cluetip-' + counter,
+ cluetipSelector = '#' + cluetipId,
+ prefix = $.cluetip.backCompat ? '#' : '.',
+ insertionType = $.cluetip.setup.insertionType,
+ insertionElement = $.cluetip.setup.insertionElement || 'body';
+
+ insertionType = (/appendTo|prependTo|insertBefore|insertAfter/).test(insertionType) ? insertionType : 'appendTo';
+ $cluetip = $(cluetipSelector);
+ if (!$cluetip.length) {
+
+ $cluetip = $($.cluetip.template)
+ [insertionType](insertionElement)
+ .attr('id', cluetipId)
+ .css({position: 'absolute', display: 'none'});
+
+ cluezIndex = +options.cluezIndex;
+ $cluetipOuter = $cluetip.find(prefix + 'cluetip-outer').css({position: 'relative', zIndex: cluezIndex});
+ $cluetipInner = $cluetip.find(prefix + 'cluetip-inner');
+ $cluetipTitle = $cluetip.find(prefix + 'cluetip-title');
+
+ $cluetip.bind('mouseenter mouseleave', function(event) {
+ $(this).data('entered', event.type === 'mouseenter');
+ });
+ }
+
+ $cluetipWait = $('#cluetip-waitimage');
+ if (!$cluetipWait.length && options.waitImage) {
+ $cluetipWait = $('<div></div>').attr('id', 'cluetip-waitimage').css({position: 'absolute'});
+ $cluetipWait.insertBefore($cluetip).hide();
+ }
+
+
+ var cluetipPadding = (parseInt($cluetip.css('paddingLeft'), 10) || 0) + (parseInt($cluetip.css('paddingRight'), 10) || 0);
+
+
+ this.each(function(index) {
+ var link = this,
+ $link = $(this),
+ // support metadata plugin (v1.0 and 2.0)
+ opts = $.extend(true, {}, options, $.metadata ? $link.metadata() : $.meta ? $link.data() : $link.data('cluetip') || {}),
+ // start out with no contents (for ajax activation)
+ cluetipContents = false,
+ isActive = false,
+ closeOnDelay = null,
+ tipAttribute = opts[opts.attribute] ||
+ ( opts.attribute == 'href' ? $link.attr(opts.attribute) : $link.attrProp(opts.attribute) || $link.attr(opts.attribute) ),
+ ctClass = opts.cluetipClass;
+
+ cluezIndex = +opts.cluezIndex;
+ $link.data('cluetip', {title: link.title, zIndex: cluezIndex, selector: cluetipSelector, cursor: link.style.cursor || ''});
+
+ if (opts.arrows && !$cluetip.find('.cluetip-arrows').length) {
+ $cluetip.append('<div class="cluetip-arrows ui-state-default"></div>');
+ }
+
+ if (!tipAttribute && !opts.splitTitle && !js) {
+ return true;
+ }
+ // if hideLocal is set to true, on DOM ready hide the local content that will be displayed in the clueTip
+ if (opts.local && opts.localPrefix) {tipAttribute = opts.localPrefix + tipAttribute;}
+ if (opts.local && opts.hideLocal && tipAttribute) { $(tipAttribute + ':first').hide(); }
+
+ var tOffset = parseInt(opts.topOffset, 10), lOffset = parseInt(opts.leftOffset, 10);
+ // vertical measurement variables
+ var tipHeight, wHeight,
+ defHeight = isNaN(parseInt(opts.height, 10)) ? 'auto' : (/\D/g).test(opts.height) ? opts.height : opts.height + 'px';
+ var sTop, linkTop, linkBottom, posY, tipY, mouseY, baseline;
+ // horizontal measurement variables
+ var tipInnerWidth = parseInt(opts.width, 10) || 275,
+ tipWidth = tipInnerWidth + cluetipPadding + opts.dropShadowSteps,
+ linkWidth = this.offsetWidth,
+ linkLeft, posX, tipX, mouseX, winWidth;
+
+ // parse the title
+ var tipParts;
+ var tipTitle = (opts.attribute != 'title') ? $link.attr(opts.titleAttribute) || '' : '';
+ if (opts.splitTitle) {
+ tipParts = tipTitle.split(opts.splitTitle);
+ tipTitle = opts.showTitle || tipParts[0] === '' ? tipParts.shift() : '';
+ }
+ if (opts.escapeTitle) {
+ tipTitle = tipTitle.replace(/&/g,'&amp;').replace(/>/g,'&gt;').replace(/</g,'&lt;');
+ }
+
+ var localContent;
+ function returnFalse() { return false; }
+
+ // Keep track of mouse entered state on link
+ $link.bind('mouseenter mouseleave', function(event) {
+ var data = $link.data('cluetip');
+ data.entered = event.type === 'entered';
+ $link.data('cluetip', data);
+ });
+
+/***************************************
+* ACTIVATION
+****************************************/
+
+//activate clueTip
+ var activate = function(event) {
+ var pY, ajaxMergedSettings, cacheKey,
+ continueOn = opts.onActivate.call(link, event);
+
+ if (continueOn === false) {
+ return false;
+ }
+
+ isActive = true;
+
+ // activate function may get called after an initialization of a
+ // different target so need to re-get the Correct Cluetip object here
+ $cluetip = $(cluetipSelector).css({position: 'absolute'});
+ $cluetipOuter = $cluetip.find(prefix + 'cluetip-outer');
+ $cluetipInner = $cluetip.find(prefix + 'cluetip-inner');
+ $cluetipTitle = $cluetip.find(prefix + 'cluetip-title');
+ $cluetipArrows = $cluetip.find(prefix + 'cluetip-arrows');
+ $cluetip.removeClass().css({width: tipInnerWidth});
+ if (tipAttribute == $link.attr('href')) {
+ $link.css('cursor', opts.cursor);
+ }
+ if (opts.hoverClass) {
+ $link.addClass(opts.hoverClass);
+ }
+ linkTop = posY = $link.offset().top;
+ linkBottom = linkTop + $link.innerHeight();
+ linkLeft = $link.offset().left;
+ if ( $(insertionElement).css('position') === 'relative' ) {
+ linkLeft -= $(insertionElement)[0].getBoundingClientRect().left;
+ }
+
+ // FIX: (bug 4412)
+ linkWidth = $link.innerWidth();
+ if ( event.type == focus ) {
+ // in focus event, no mouse position is available; this is needed with bottomTop:
+ mouseX = linkLeft + ( linkWidth / 2 ) + lOffset;
+ $cluetip.css({left: posX});
+ mouseY = posY + tOffset;
+ } else {
+ mouseX = event.pageX;
+ mouseY = event.pageY;
+ }
+ //END OF FIX
+
+ if (link.tagName.toLowerCase() != 'area') {
+ sTop = $(document).scrollTop();
+ winWidth = $(window).width();
+ }
+// position clueTip horizontally
+ if (opts.positionBy == 'fixed') {
+ posX = linkWidth + linkLeft + lOffset;
+ $cluetip.css({left: posX});
+ } else {
+ posX = (linkWidth > linkLeft && linkLeft > tipWidth) ||
+ linkLeft + linkWidth + tipWidth + lOffset > winWidth ?
+ linkLeft - tipWidth - lOffset :
+ linkWidth + linkLeft + lOffset;
+ if (link.tagName.toLowerCase() == 'area' || opts.positionBy == 'mouse' || linkWidth + tipWidth > winWidth) { // position by mouse
+ if (mouseX + 20 + tipWidth > winWidth) {
+ $cluetip.addClass('cluetip-' + ctClass);
+ posX = (mouseX - tipWidth - lOffset) >= 0 ? mouseX - tipWidth - lOffset - parseInt($cluetip.css('marginLeft'),10) + parseInt($cluetipInner.css('marginRight'),10) : mouseX - (tipWidth/2);
+ } else {
+ posX = mouseX + lOffset;
+ }
+ }
+ pY = posX < 0 ? event.pageY + tOffset : event.pageY;
+ if (posX < 0 || opts.positionBy == 'bottomTop' || opts.positionBy == 'topBottom') {
+ posX = (mouseX + (tipWidth/2) > winWidth) ? winWidth/2 - tipWidth/2 : Math.max(mouseX - (tipWidth/2),0);
+ }
+ }
+
+ $cluetipArrows.css({zIndex: $link.data('cluetip').zIndex+1});
+ $cluetip.css({
+ left: posX,
+ zIndex: $link.data('cluetip').zIndex
+ });
+ wHeight = $(window).height();
+
+/***************************************
+* load a string from cluetip method's first argument
+***************************************/
+ if (js) {
+ if (typeof js == 'function') {
+ js = js.call(link);
+ }
+ $cluetipInner.html(js);
+ cluetipShow(pY);
+ }
+/***************************************
+* load the title attribute only (or user-selected attribute).
+* clueTip title is the string before the first delimiter
+* subsequent delimiters place clueTip body text on separate lines
+***************************************/
+
+ else if (tipParts) {
+ var tpl = tipParts.length;
+ $cluetipInner.html(tpl ? tipParts[0] : '');
+ if (tpl > 1) {
+ for (var i=1; i < tpl; i++){
+ $cluetipInner.append('<div class="split-body">' + tipParts[i] + '</div>');
+ }
+ }
+ cluetipShow(pY);
+ }
+/***************************************
+* load external file via ajax
+***************************************/
+
+ else if ( !opts.local && tipAttribute.indexOf('#') !== 0 ) {
+ if (/\.(jpe?g|tiff?|gif|png)(?:\?.*)?$/i.test(tipAttribute)) {
+ $cluetipInner.html('<img src="' + tipAttribute + '" alt="' + tipTitle + '" />');
+ cluetipShow(pY);
+ } else {
+ var optionBeforeSend = opts.ajaxSettings.beforeSend,
+ optionError = opts.ajaxSettings.error,
+ optionSuccess = opts.ajaxSettings.success,
+ optionComplete = opts.ajaxSettings.complete;
+
+ cacheKey = getCacheKey(tipAttribute, opts.ajaxSettings.data);
+
+ var ajaxSettings = {
+ cache: opts.ajaxCache, // force requested page not to be cached by browser
+ url: tipAttribute,
+ beforeSend: function(xhr, settings) {
+ if (optionBeforeSend) {optionBeforeSend.call(link, xhr, $cluetip, $cluetipInner, settings);}
+ $cluetipOuter.children().empty();
+ if (opts.waitImage) {
+ $cluetipWait
+ .css({top: mouseY+20, left: mouseX+20, zIndex: $link.data('cluetip').zIndex-1})
+ .show();
+ }
+ },
+ error: function(xhr, textStatus) {
+ if ( options.ajaxCache && !caches[cacheKey] ) {
+ caches[cacheKey] = {status: 'error', textStatus: textStatus, xhr: xhr};
+ }
+
+ if (isActive) {
+ if (optionError) {
+ optionError.call(link, xhr, textStatus, $cluetip, $cluetipInner);
+ } else {
+ $cluetipInner.html('<i>sorry, the contents could not be loaded</i>');
+ }
+ }
+ },
+ success: function(data, textStatus, xhr) {
+ if ( options.ajaxCache && !caches[cacheKey] ) {
+ caches[cacheKey] = {status: 'success', data: data, textStatus: textStatus, xhr: xhr};
+ }
+
+ cluetipContents = opts.ajaxProcess.call(link, data);
+
+ // allow for changing the title based on data returned by xhr
+ if ( typeof cluetipContents == 'object' && cluetipContents !== null ) {
+ tipTitle = cluetipContents.title;
+ cluetipContents = cluetipContents.content;
+ }
+
+ if (isActive) {
+ if (optionSuccess) {
+ optionSuccess.call(link, data, textStatus, $cluetip, $cluetipInner);
+ }
+ $cluetipInner.html(cluetipContents);
+
+ }
+ },
+ complete: function(xhr, textStatus) {
+ if (optionComplete) {
+ optionComplete.call(link, xhr, textStatus, $cluetip, $cluetipInner);
+ }
+ var imgs = $cluetipInner[0].getElementsByTagName('img');
+ imgCount = imgs.length;
+ for (var i=0, l = imgs.length; i < l; i++) {
+ if (imgs[i].complete) {
+ imgCount--;
+ }
+ }
+ if (imgCount) {
+ $(imgs).bind('load.ct error.ct', function() {
+ imgCount--;
+ if (imgCount === 0) {
+ $cluetipWait.hide();
+ $(imgs).unbind('.ct');
+ if (isActive) { cluetipShow(pY); }
+ }
+ });
+ } else {
+ $cluetipWait.hide();
+ if (isActive) { cluetipShow(pY); }
+ }
+ }
+ };
+
+ ajaxMergedSettings = $.extend(true, {}, opts.ajaxSettings, ajaxSettings);
+
+ if ( caches[cacheKey] ) {
+ cachedAjax( caches[cacheKey], ajaxMergedSettings );
+ } else {
+ $.ajax(ajaxMergedSettings);
+ }
+ }
+ }
+/***************************************
+* load an element from the same page
+***************************************/
+ else if (opts.local) {
+ var $localContent = $(tipAttribute + (/^#\S+$/.test(tipAttribute) ? '' : ':eq(' + index + ')')).clone(true).show();
+ if (opts.localIdSuffix) {
+ $localContent.attr('id', $localContent[0].id + opts.localIdSuffix);
+ }
+ $cluetipInner.html($localContent);
+ cluetipShow(pY);
+ }
+ };
+
+// get dimensions and options for cluetip and prepare it to be shown
+ var cluetipShow = function(bpY) {
+ var $closeLink, dynamicClasses, heightDiff,
+ titleHTML = tipTitle || opts.showTitle && '&nbsp;',
+ bgY = '', direction = '', insufficientX = false;
+ var stickyClose = {
+ bottom: function($cLink) {
+ $cLink.appendTo($cluetipInner);
+ },
+ top: function($cLink) {
+ $cLink.prependTo($cluetipInner);
+ },
+ title: function($cLink) {
+ $cLink.prependTo($cluetipTitle);
+ }
+ };
+
+ $cluetip.addClass('cluetip-' + ctClass);
+ if (opts.truncate) {
+ var $truncloaded = $cluetipInner.text().slice(0,opts.truncate) + '...';
+ $cluetipInner.html($truncloaded);
+ }
+
+ if (titleHTML) {
+ $cluetipTitle.show().html(titleHTML);
+ } else {
+ $cluetipTitle.hide();
+ }
+
+ if (opts.sticky) {
+ if (stickyClose[opts.closePosition]) {
+ $closeLink = $('<div class="cluetip-close"><a href="#">' + opts.closeText + '</a></div>');
+ stickyClose[opts.closePosition]( $closeLink );
+ $closeLink.bind('click.cluetip', function() {
+ cluetipClose();
+ return false;
+ });
+ }
+ if (opts.mouseOutClose) {
+ $link.unbind('mouseleave.cluetipMoc');
+ $cluetip.unbind('mouseleave.cluetipMoc');
+ if (opts.mouseOutClose == 'both' || opts.mouseOutClose == 'cluetip' || opts.mouseOutClose === true) { // true implies 'cluetip' for backwards compatability
+ $cluetip.bind('mouseleave.cluetipMoc', mouseOutClose);
+ }
+ if (opts.mouseOutClose == 'both' || opts.mouseOutClose == 'link') {
+ $link.bind('mouseleave.cluetipMoc', mouseOutClose);
+ }
+ }
+ }
+
+// now that content is loaded, finish the positioning
+ $cluetipOuter.css({zIndex: $link.data('cluetip').zIndex, overflow: defHeight == 'auto' ? 'visible' : 'auto', height: defHeight});
+ tipHeight = defHeight == 'auto' ? Math.max($cluetip.outerHeight(),$cluetip.height()) : parseInt(defHeight,10);
+ tipY = posY;
+ baseline = sTop + wHeight;
+ insufficientX = (posX < mouseX && (Math.max(posX, 0) + tipWidth > mouseX));
+ if (opts.positionBy == 'fixed') {
+ tipY = posY - opts.dropShadowSteps + tOffset;
+ } else if (opts.positionBy == 'topBottom' || opts.positionBy == 'bottomTop' || insufficientX) {
+ if (opts.positionBy == 'topBottom') {
+ if (posY + tipHeight + tOffset < baseline && mouseY - sTop < tipHeight + tOffset) {
+ direction = 'bottom';
+ } else {
+ direction = 'top';
+ }
+ } else if (opts.positionBy == 'bottomTop' || insufficientX) {
+ if (posY + tipHeight + tOffset > baseline && mouseY - sTop > tipHeight + tOffset) {
+ direction = 'top';
+ } else {
+ direction = 'bottom';
+ }
+ }
+ // We should now have a direction. Compute tipY
+ if (opts.snapToEdge) {
+ if (direction == 'top') {
+ tipY = linkTop - tipHeight - tOffset;
+ } else if (direction == 'bottom') {
+ tipY = linkBottom + tOffset;
+ }
+ } else {
+ if (direction == 'top') {
+ tipY = mouseY - tipHeight - tOffset;
+ } else if (direction == 'bottom') {
+ tipY = mouseY + tOffset;
+ }
+ }
+ } else if ( posY + tipHeight + tOffset > baseline ) {
+ tipY = (tipHeight >= wHeight) ? sTop : baseline - tipHeight - tOffset;
+ } else if ($link.css('display') == 'block' || link.tagName.toLowerCase() == 'area' || opts.positionBy == "mouse") {
+ tipY = bpY - tOffset;
+ } else {
+ tipY = posY - opts.dropShadowSteps;
+ }
+ if (direction === '') {
+ direction = posX < linkLeft ? 'left' : 'right';
+ }
+ // add classes
+ dynamicClasses = ' clue-' + direction + '-' + ctClass + ' cluetip-' + ctClass;
+ if (ctClass == 'rounded') {
+ dynamicClasses += ' ui-corner-all';
+ }
+ $cluetip.css({top: tipY + 'px'}).attrProp({'className': standardClasses + dynamicClasses});
+ // set up arrow positioning to align with element
+ if (opts.arrows) {
+ if ( /(left|right)/.test(direction) ) {
+ heightDiff = $cluetip.height() - $cluetipArrows.height();
+ bgY = posX >= 0 && bpY > 0 ? (posY - tipY - opts.dropShadowSteps) : 0;
+ bgY = heightDiff > bgY ? bgY : heightDiff;
+ bgY += 'px';
+ }
+ $cluetipArrows.css({top: bgY}).show();
+ } else {
+ $cluetipArrows.hide();
+ }
+
+// (first hide, then) ***SHOW THE CLUETIP***
+ // handle dropshadow divs first
+ $dropShadow = createDropShadows($cluetip, opts);
+ if ($dropShadow && $dropShadow.length) {
+ $dropShadow.hide().css({height: tipHeight, width: tipInnerWidth, zIndex: $link.data('cluetip').zIndex-1}).show();
+ }
+
+ if (!closeOnDelay) {
+ $cluetip.hide();
+ }
+ clearTimeout(closeOnDelay);
+ closeOnDelay = null;
+
+ // show the cluetip
+ $cluetip[opts.fx.open](opts.fx.openSpeed || 0);
+
+ if ($.fn.bgiframe) { $cluetip.bgiframe(); }
+
+ // trigger the optional onShow function
+ opts.onShow.call(link, $cluetip, $cluetipInner);
+ };
+
+/***************************************
+ =INACTIVATION
+-------------------------------------- */
+ var inactivate = function(event) {
+ isActive = false;
+ $cluetipWait.hide();
+ if (!opts.sticky || (/click|toggle/).test(opts.activation) ) {
+ // delayed close (not fully tested)
+ if (opts.delayedClose > 0) {
+ clearTimeout(closeOnDelay);
+ closeOnDelay = null;
+ closeOnDelay = setTimeout(cluetipClose, opts.delayedClose);
+ } else {
+ cluetipClose();
+ clearTimeout(closeOnDelay);
+ }
+ }
+
+ if (opts.hoverClass) {
+ $link.removeClass(opts.hoverClass);
+ }
+ };
+
+ // close cluetip and reset some things
+ var cluetipClose = function(el) {
+ var $closer = el && el.data('cluetip') ? el : $link,
+ ct = $closer.data('cluetip') && $closer.data('cluetip').selector,
+ ctSelector = ct || 'div.cluetip',
+ $cluetip = $(ctSelector),
+ $cluetipInner = $cluetip.find(prefix + 'cluetip-inner'),
+ $cluetipArrows = $cluetip.find(prefix + 'cluetip-arrows');
+
+ $cluetip.hide().removeClass();
+ opts.onHide.call($closer[0], $cluetip, $cluetipInner);
+
+ if (ct) {
+ $closer.removeClass('cluetip-clicked');
+ $link.css('cursor', $link.data('cluetip').cursor);
+ }
+ if (ct && tipTitle) {
+ $closer.attrProp(opts.titleAttribute, tipTitle);
+ }
+
+ if (opts.arrows) {
+ $cluetipArrows.css({top: ''});
+ }
+ if ($dropShadow) {
+ $dropShadow.hide();
+ }
+ };
+
+ // Check to see if we should be closing by checking where the user is hovering.
+ // We do a short 50ms delay for two reasons: to prevent flicker, and to allow the user time to hover on other element
+ var mouseOutClose = function() {
+ var el = this;
+ clearTimeout(closeOnDelay);
+ closeOnDelay = setTimeout(function() {
+ var linkOver = $link.data('cluetip').entered,
+ cluetipOver = $cluetip.data('entered'),
+ entered = false;
+
+ if ( opts.mouseOutClose == 'both' && (linkOver || cluetipOver) ) {
+ entered = true;
+ }
+ // true implies 'cluetip' for backwards compatibility
+ else if ( (opts.mouseOutClose === true || opts.mouseOutClose == 'cluetip') && cluetipOver) {
+ entered = true;
+ }
+ else if (opts.mouseOutClose == 'link' && linkOver) {
+ entered = true;
+ }
+
+ if ( !entered ) {
+ // All checks pass, close the cluetip
+ cluetipClose.call(el);
+ }
+
+ }, opts.delayedClose);
+ };
+
+ $(document).unbind('hideCluetip.cluetip').bind('hideCluetip.cluetip', function(e) {
+ cluetipClose( $(e.target) );
+ });
+/***************************************
+ =BIND EVENTS
+-------------------------------------- */
+ // activate by click
+ if ( (/click|toggle/).test(opts.activation) ) {
+ $link.bind('click.cluetip', function(event) {
+ if ($cluetip.is(':hidden') || !$link.is('.cluetip-clicked')) {
+ activate(event);
+ $('.cluetip-clicked').removeClass('cluetip-clicked');
+ $link.addClass('cluetip-clicked');
+ } else {
+ inactivate(event);
+ }
+ return false;
+ });
+ // activate by focus; inactivate by blur
+ } else if (opts.activation == 'focus') {
+ $link.bind('focus.cluetip', function(event) {
+ $link.attrProp('title','');
+ activate(event);
+ });
+ $link.bind('blur.cluetip', function(event) {
+ $link.attrProp('title', $link.data('cluetip').title);
+ inactivate(event);
+ });
+ // activate by hover
+ } else {
+
+ // clicking is returned false if clickThrough option is set to false
+ $link[opts.clickThrough ? 'unbind' : 'bind']('click.cluetip', returnFalse);
+
+ //set up mouse tracking
+ var mouseTracks = function(evt) {
+ if (opts.tracking) {
+ var trackX = posX - evt.pageX;
+ var trackY = tipY ? tipY - evt.pageY : posY - evt.pageY;
+ $link.bind('mousemove.cluetip', function(evt) {
+ $cluetip.css({left: evt.pageX + trackX, top: evt.pageY + trackY });
+ });
+ }
+ };
+
+ if ($.fn.hoverIntent && opts.hoverIntent) {
+ $link.hoverIntent({
+ sensitivity: opts.hoverIntent.sensitivity,
+ interval: opts.hoverIntent.interval,
+ over: function(event) {
+ activate(event);
+ mouseTracks(event);
+ },
+ timeout: opts.hoverIntent.timeout,
+ out: function(event) {
+ inactivate(event);
+ $link.unbind('mousemove.cluetip');
+ }
+ });
+ } else {
+ $link.bind('mouseenter.cluetip', function(event) {
+ activate(event);
+ mouseTracks(event);
+ })
+ .bind('mouseleave.cluetip', function(event) {
+ inactivate(event);
+ $link.unbind('mousemove.cluetip');
+ });
+ }
+
+ $link.bind('mouseover.cluetip', function(event) {
+ $link.attrProp('title','');
+ }).bind('mouseleave.cluetip', function(event) {
+ $link.attrProp('title', $link.data('cluetip').title);
+ });
+ }
+
+ // trigger a cached Ajax response
+ function cachedAjax(info, settings) {
+ var status = info.status;
+ settings.beforeSend(info.xhr, settings);
+ if ( status == 'error' ) {
+ settings[status](info.xhr, info.textStatus);
+ } else if (status == 'success') {
+ settings[status](info.data, info.textStatus, info.xhr);
+ }
+ settings.complete(info.xhr, settings.textStatus);
+ }
+
+ }); // end this.each
+
+ /** =private functions
+ ************************************************************/
+ //empty function
+ function doNothing() {}
+
+ // create a string to be used as an identifier for ajax caches
+ function getCacheKey(url, data) {
+ var cacheKey = url || '';
+ data = data || '';
+
+ if (typeof data == 'object') {
+ $.each(data, function(key, val) {
+ cacheKey += '-' + key + '-' + val;
+ });
+ } else if (typeof data == 'string') {
+ cacheKey += data;
+ }
+
+ return cacheKey;
+ }
+
+ /** =create dropshadow divs **/
+
+ function createDropShadows($cluetip, options, newDropShadow) {
+ var dsStyle = '',
+ dropShadowSteps = (options.dropShadow && options.dropShadowSteps) ? +options.dropShadowSteps : 0;
+
+ if ($.support.boxShadow) {
+ if ( dropShadowSteps ) {
+ dsStyle = '1px 1px ' + dropShadowSteps + 'px rgba(0,0,0,0.5)';
+ }
+ var dsOffsets = dropShadowSteps === 0 ? '0 0 ' : '1px 1px ';
+ $cluetip.css($.support.boxShadow, dsStyle);
+ return false;
+ }
+ var oldDropShadow = $cluetip.find('.cluetip-drop-shadow');
+ if (dropShadowSteps == oldDropShadow.length) {
+ return oldDropShadow;
+ }
+ oldDropShadow.remove();
+ var dropShadows = [];
+ for (var i=0; i < dropShadowSteps;) {
+ dropShadows[i++] = '<div style="top:' + i + 'px;left:' + i + 'px;"></div>';
+ }
+
+ newDropShadow = $(dropShadows.join(''))
+ .css({
+ position: 'absolute',
+ backgroundColor: '#000',
+ zIndex: cluezIndex -1,
+ opacity: 0.1
+ })
+ .addClass('cluetip-drop-shadow')
+ .prependTo($cluetip);
+ return newDropShadow;
+
+ }
+
+ return this;
+ };
+
+ (function() {
+ $.support = $.support || {};
+ // check support for CSS3 properties (currently only boxShadow)
+ var div = document.createElement('div'),
+ divStyle = div.style,
+ styleProps = ['boxShadow'],
+ prefixes = ['moz', 'Moz', 'webkit', 'o'];
+
+ for (var i=0, sl = styleProps.length; i < sl; i++) {
+ var prop = styleProps[i],
+ uProp = prop.charAt(0).toUpperCase() + prop.slice(1);
+
+ if ( typeof divStyle[ prop ] !== 'undefined' ) {
+ $.support[ prop ] = prop;
+ } else {
+ for (var j=0, pl = prefixes.length; j < pl; j++) {
+
+ if (typeof divStyle[ prefixes[j] + uProp ] !== 'undefined') {
+ $.support[ prop ] = prefixes[j] + uProp;
+ break;
+ }
+ }
+ }
+ }
+ div = null;
+ })();
+
+ $.fn.cluetip.defaults = $.cluetip.defaults;
+
+})(jQuery);
diff --git a/views/js/jquery-cluetip-master/jquery.cluetip.min.js b/views/js/jquery-cluetip-master/jquery.cluetip.min.js
new file mode 100644
index 0000000..70ff84f
--- /dev/null
+++ b/views/js/jquery-cluetip-master/jquery.cluetip.min.js
@@ -0,0 +1,7 @@
+/*!
+ * clueTip - v1.2.9 - 2013-06-02
+ * http://plugins.learningjquery.com/cluetip/
+ * Copyright (c) 2013 Karl Swedberg
+ * Licensed MIT (http://www.opensource.org/licenses/mit-license.php)
+ */
+(function(t){t.cluetip={version:"1.2.9",template:["<div>",'<div class="cluetip-outer">','<h3 class="cluetip-title ui-widget-header ui-cluetip-header"></h3>','<div class="cluetip-inner ui-widget-content ui-cluetip-content"></div>',"</div>",'<div class="cluetip-extra"></div>',"</div>"].join(""),setup:{insertionType:"appendTo",insertionElement:"body"},defaults:{multiple:!1,width:275,height:"auto",cluezIndex:97,positionBy:"auto",topOffset:15,leftOffset:15,snapToEdge:!1,local:!1,localPrefix:null,localIdSuffix:null,hideLocal:!0,attribute:"rel",titleAttribute:"title",splitTitle:"",escapeTitle:!1,showTitle:!0,cluetipClass:"default",hoverClass:"",waitImage:!0,cursor:"help",arrows:!1,dropShadow:!0,dropShadowSteps:6,sticky:!1,mouseOutClose:!1,delayedClose:50,activation:"hover",clickThrough:!0,tracking:!1,closePosition:"top",closeText:"Close",truncate:0,fx:{open:"show",openSpeed:""},hoverIntent:{sensitivity:3,interval:50,timeout:0},onActivate:function(){return!0},onShow:function(){},onHide:function(){},ajaxCache:!0,ajaxProcess:function(t){return t=t.replace(/<(script|style|title)[^<]+<\/(script|style|title)>/gm,"").replace(/<(link|meta)[^>]+>/g,"")},ajaxSettings:{dataType:"html"},debug:!1}};var e,i="cluetip ui-widget ui-widget-content ui-cluetip",o={},a=0,l=0;t.fn.attrProp=t.fn.prop||t.fn.attr,t.fn.cluetip=function(s,n){function c(e,i){var o=e||"";return i=i||"","object"==typeof i?t.each(i,function(t,e){o+="-"+t+"-"+e}):"string"==typeof i&&(o+=i),o}function u(e,i,o){var a="",l=i.dropShadow&&i.dropShadowSteps?+i.dropShadowSteps:0;if(t.support.boxShadow)return l&&(a="1px 1px "+l+"px rgba(0,0,0,0.5)"),e.css(t.support.boxShadow,a),!1;var s=e.find(".cluetip-drop-shadow");if(l==s.length)return s;s.remove();for(var n=[],c=0;l>c;)n[c++]='<div style="top:'+c+"px;left:"+c+'px;"></div>';return o=t(n.join("")).css({position:"absolute",backgroundColor:"#000",zIndex:v-1,opacity:.1}).addClass("cluetip-drop-shadow").prependTo(e)}var r,p,d,f,h,m;if("object"==typeof s&&(n=s,s=null),"destroy"==s)return this.each(function(){var e=t(this),i=e.data("cluetip");i&&(t(i.selector).remove(),t.removeData(this,"title"),t.removeData(this,"cluetip")),i.title&&e.attrProp("title",i.title),e.unbind(".cluetip").unbind("cluetipMoc")}),t('[id^="cluetip"]').length||t(document).unbind(".cluetip"),this;n=t.extend(!0,{},t.cluetip.defaults,n||{}),a++;var v,g=t.cluetip.backCompat||!n.multiple?"cluetip":"cluetip-"+a,b="#"+g,x=t.cluetip.backCompat?"#":".",w=t.cluetip.setup.insertionType,y=t.cluetip.setup.insertionElement||"body";w=/appendTo|prependTo|insertBefore|insertAfter/.test(w)?w:"appendTo",r=t(b),r.length||(r=t(t.cluetip.template)[w](y).attr("id",g).css({position:"absolute",display:"none"}),v=+n.cluezIndex,d=r.find(x+"cluetip-outer").css({position:"relative",zIndex:v}),p=r.find(x+"cluetip-inner"),f=r.find(x+"cluetip-title"),r.bind("mouseenter mouseleave",function(e){t(this).data("entered","mouseenter"===e.type)})),e=t("#cluetip-waitimage"),!e.length&&n.waitImage&&(e=t("<div></div>").attr("id","cluetip-waitimage").css({position:"absolute"}),e.insertBefore(r).hide());var C=(parseInt(r.css("paddingLeft"),10)||0)+(parseInt(r.css("paddingRight"),10)||0);return this.each(function(a){function g(){return!1}function w(t,e){var i=t.status;e.beforeSend(t.xhr,e),"error"==i?e[i](t.xhr,t.textStatus):"success"==i&&e[i](t.data,t.textStatus,t.xhr),e.complete(t.xhr,e.textStatus)}var S=this,I=t(this),T=t.extend(!0,{},n,t.metadata?I.metadata():t.meta?I.data():I.data("cluetip")||{}),k=!1,j=!1,z=null,B=T[T.attribute]||("href"==T.attribute?I.attr(T.attribute):I.attrProp(T.attribute)||I.attr(T.attribute)),P=T.cluetipClass;if(v=+T.cluezIndex,I.data("cluetip",{title:S.title,zIndex:v,selector:b,cursor:S.style.cursor||""}),T.arrows&&!r.find(".cluetip-arrows").length&&r.append('<div class="cluetip-arrows ui-state-default"></div>'),!B&&!T.splitTitle&&!s)return!0;T.local&&T.localPrefix&&(B=T.localPrefix+B),T.local&&T.hideLocal&&B&&t(B+":first").hide();var O,M,A,L,N,E,Y,H,D,R,X,W,$,q,Q=parseInt(T.topOffset,10),U=parseInt(T.leftOffset,10),F=isNaN(parseInt(T.height,10))?"auto":/\D/g.test(T.height)?T.height:T.height+"px",G=parseInt(T.width,10)||275,J=G+C+T.dropShadowSteps,K=this.offsetWidth,V="title"!=T.attribute?I.attr(T.titleAttribute)||"":"";T.splitTitle&&(q=V.split(T.splitTitle),V=T.showTitle||""===q[0]?q.shift():""),T.escapeTitle&&(V=V.replace(/&/g,"&amp;").replace(/>/g,"&gt;").replace(/</g,"&lt;")),I.bind("mouseenter mouseleave",function(t){var e=I.data("cluetip");e.entered="entered"===t.type,I.data("cluetip",e)});var Z=function(i){var u,m,v,g=T.onActivate.call(S,i);if(g===!1)return!1;if(j=!0,r=t(b).css({position:"absolute"}),d=r.find(x+"cluetip-outer"),p=r.find(x+"cluetip-inner"),f=r.find(x+"cluetip-title"),h=r.find(x+"cluetip-arrows"),r.removeClass().css({width:G}),B==I.attr("href")&&I.css("cursor",T.cursor),T.hoverClass&&I.addClass(T.hoverClass),L=E=I.offset().top,N=L+I.innerHeight(),R=I.offset().left,"relative"===t(y).css("position")&&(R-=t(y)[0].getBoundingClientRect().left),K=I.innerWidth(),i.type==focus?(W=R+K/2+U,r.css({left:X}),H=E+Q):(W=i.pageX,H=i.pageY),"area"!=S.tagName.toLowerCase()&&(A=t(document).scrollTop(),$=t(window).width()),"fixed"==T.positionBy?(X=K+R+U,r.css({left:X})):(X=K>R&&R>J||R+K+J+U>$?R-J-U:K+R+U,("area"==S.tagName.toLowerCase()||"mouse"==T.positionBy||K+J>$)&&(W+20+J>$?(r.addClass("cluetip-"+P),X=W-J-U>=0?W-J-U-parseInt(r.css("marginLeft"),10)+parseInt(p.css("marginRight"),10):W-J/2):X=W+U),u=0>X?i.pageY+Q:i.pageY,(0>X||"bottomTop"==T.positionBy||"topBottom"==T.positionBy)&&(X=W+J/2>$?$/2-J/2:Math.max(W-J/2,0))),h.css({zIndex:I.data("cluetip").zIndex+1}),r.css({left:X,zIndex:I.data("cluetip").zIndex}),M=t(window).height(),s)"function"==typeof s&&(s=s.call(S)),p.html(s),_(u);else if(q){var C=q.length;if(p.html(C?q[0]:""),C>1)for(var z=1;C>z;z++)p.append('<div class="split-body">'+q[z]+"</div>");_(u)}else if(T.local||0===B.indexOf("#")){if(T.local){var O=t(B+(/^#\S+$/.test(B)?"":":eq("+a+")")).clone(!0).show();T.localIdSuffix&&O.attr("id",O[0].id+T.localIdSuffix),p.html(O),_(u)}}else if(/\.(jpe?g|tiff?|gif|png)(?:\?.*)?$/i.test(B))p.html('<img src="'+B+'" alt="'+V+'" />'),_(u);else{var Y=T.ajaxSettings.beforeSend,D=T.ajaxSettings.error,F=T.ajaxSettings.success,Z=T.ajaxSettings.complete;v=c(B,T.ajaxSettings.data);var te={cache:T.ajaxCache,url:B,beforeSend:function(t,i){Y&&Y.call(S,t,r,p,i),d.children().empty(),T.waitImage&&e.css({top:H+20,left:W+20,zIndex:I.data("cluetip").zIndex-1}).show()},error:function(t,e){n.ajaxCache&&!o[v]&&(o[v]={status:"error",textStatus:e,xhr:t}),j&&(D?D.call(S,t,e,r,p):p.html("<i>sorry, the contents could not be loaded</i>"))},success:function(t,e,i){n.ajaxCache&&!o[v]&&(o[v]={status:"success",data:t,textStatus:e,xhr:i}),k=T.ajaxProcess.call(S,t),"object"==typeof k&&null!==k&&(V=k.title,k=k.content),j&&(F&&F.call(S,t,e,r,p),p.html(k))},complete:function(i,o){Z&&Z.call(S,i,o,r,p);var a=p[0].getElementsByTagName("img");l=a.length;for(var s=0,n=a.length;n>s;s++)a[s].complete&&l--;l?t(a).bind("load.ct error.ct",function(){l--,0===l&&(e.hide(),t(a).unbind(".ct"),j&&_(u))}):(e.hide(),j&&_(u))}};m=t.extend(!0,{},T.ajaxSettings,te),o[v]?w(o[v],m):t.ajax(m)}},_=function(e){var o,a,l,s=V||T.showTitle&&"&nbsp;",n="",c="",v=!1,g={bottom:function(t){t.appendTo(p)},top:function(t){t.prependTo(p)},title:function(t){t.prependTo(f)}};if(r.addClass("cluetip-"+P),T.truncate){var b=p.text().slice(0,T.truncate)+"...";p.html(b)}s?f.show().html(s):f.hide(),T.sticky&&(g[T.closePosition]&&(o=t('<div class="cluetip-close"><a href="#">'+T.closeText+"</a></div>"),g[T.closePosition](o),o.bind("click.cluetip",function(){return ee(),!1})),T.mouseOutClose&&(I.unbind("mouseleave.cluetipMoc"),r.unbind("mouseleave.cluetipMoc"),("both"==T.mouseOutClose||"cluetip"==T.mouseOutClose||T.mouseOutClose===!0)&&r.bind("mouseleave.cluetipMoc",ie),("both"==T.mouseOutClose||"link"==T.mouseOutClose)&&I.bind("mouseleave.cluetipMoc",ie))),d.css({zIndex:I.data("cluetip").zIndex,overflow:"auto"==F?"visible":"auto",height:F}),O="auto"==F?Math.max(r.outerHeight(),r.height()):parseInt(F,10),Y=E,D=A+M,v=W>X&&Math.max(X,0)+J>W,"fixed"==T.positionBy?Y=E-T.dropShadowSteps+Q:"topBottom"==T.positionBy||"bottomTop"==T.positionBy||v?("topBottom"==T.positionBy?c=D>E+O+Q&&O+Q>H-A?"bottom":"top":("bottomTop"==T.positionBy||v)&&(c=E+O+Q>D&&H-A>O+Q?"top":"bottom"),T.snapToEdge?"top"==c?Y=L-O-Q:"bottom"==c&&(Y=N+Q):"top"==c?Y=H-O-Q:"bottom"==c&&(Y=H+Q)):Y=E+O+Q>D?O>=M?A:D-O-Q:"block"==I.css("display")||"area"==S.tagName.toLowerCase()||"mouse"==T.positionBy?e-Q:E-T.dropShadowSteps,""===c&&(c=R>X?"left":"right"),a=" clue-"+c+"-"+P+" cluetip-"+P,"rounded"==P&&(a+=" ui-corner-all"),r.css({top:Y+"px"}).attrProp({className:i+a}),T.arrows?(/(left|right)/.test(c)&&(l=r.height()-h.height(),n=X>=0&&e>0?E-Y-T.dropShadowSteps:0,n=l>n?n:l,n+="px"),h.css({top:n}).show()):h.hide(),m=u(r,T),m&&m.length&&m.hide().css({height:O,width:G,zIndex:I.data("cluetip").zIndex-1}).show(),z||r.hide(),clearTimeout(z),z=null,r[T.fx.open](T.fx.openSpeed||0),t.fn.bgiframe&&r.bgiframe(),T.onShow.call(S,r,p)},te=function(){j=!1,e.hide(),(!T.sticky||/click|toggle/.test(T.activation))&&(T.delayedClose>0?(clearTimeout(z),z=null,z=setTimeout(ee,T.delayedClose)):(ee(),clearTimeout(z))),T.hoverClass&&I.removeClass(T.hoverClass)},ee=function(e){var i=e&&e.data("cluetip")?e:I,o=i.data("cluetip")&&i.data("cluetip").selector,a=o||"div.cluetip",l=t(a),s=l.find(x+"cluetip-inner"),n=l.find(x+"cluetip-arrows");l.hide().removeClass(),T.onHide.call(i[0],l,s),o&&(i.removeClass("cluetip-clicked"),I.css("cursor",I.data("cluetip").cursor)),o&&V&&i.attrProp(T.titleAttribute,V),T.arrows&&n.css({top:""}),m&&m.hide()},ie=function(){var t=this;clearTimeout(z),z=setTimeout(function(){var e=I.data("cluetip").entered,i=r.data("entered"),o=!1;"both"==T.mouseOutClose&&(e||i)?o=!0:T.mouseOutClose!==!0&&"cluetip"!=T.mouseOutClose||!i?"link"==T.mouseOutClose&&e&&(o=!0):o=!0,o||ee.call(t)},T.delayedClose)};if(t(document).unbind("hideCluetip.cluetip").bind("hideCluetip.cluetip",function(e){ee(t(e.target))}),/click|toggle/.test(T.activation))I.bind("click.cluetip",function(e){return r.is(":hidden")||!I.is(".cluetip-clicked")?(Z(e),t(".cluetip-clicked").removeClass("cluetip-clicked"),I.addClass("cluetip-clicked")):te(e),!1});else if("focus"==T.activation)I.bind("focus.cluetip",function(t){I.attrProp("title",""),Z(t)}),I.bind("blur.cluetip",function(t){I.attrProp("title",I.data("cluetip").title),te(t)});else{I[T.clickThrough?"unbind":"bind"]("click.cluetip",g);var oe=function(t){if(T.tracking){var e=X-t.pageX,i=Y?Y-t.pageY:E-t.pageY;I.bind("mousemove.cluetip",function(t){r.css({left:t.pageX+e,top:t.pageY+i})})}};t.fn.hoverIntent&&T.hoverIntent?I.hoverIntent({sensitivity:T.hoverIntent.sensitivity,interval:T.hoverIntent.interval,over:function(t){Z(t),oe(t)},timeout:T.hoverIntent.timeout,out:function(t){te(t),I.unbind("mousemove.cluetip")}}):I.bind("mouseenter.cluetip",function(t){Z(t),oe(t)}).bind("mouseleave.cluetip",function(t){te(t),I.unbind("mousemove.cluetip")}),I.bind("mouseover.cluetip",function(){I.attrProp("title","")}).bind("mouseleave.cluetip",function(){I.attrProp("title",I.data("cluetip").title)})}}),this},function(){t.support=t.support||{};for(var e=document.createElement("div"),i=e.style,o=["boxShadow"],a=["moz","Moz","webkit","o"],l=0,s=o.length;s>l;l++){var n=o[l],c=n.charAt(0).toUpperCase()+n.slice(1);if(i[n]!==void 0)t.support[n]=n;else for(var u=0,r=a.length;r>u;u++)if(i[a[u]+c]!==void 0){t.support[n]=a[u]+c;break}}e=null}(),t.fn.cluetip.defaults=t.cluetip.defaults})(jQuery); \ No newline at end of file
diff --git a/views/js/jquery-validation-1.11.1/dist/additional-methods.js b/views/js/jquery-validation-1.11.1/dist/additional-methods.js
new file mode 100644
index 0000000..b0534b5
--- /dev/null
+++ b/views/js/jquery-validation-1.11.1/dist/additional-methods.js
@@ -0,0 +1,617 @@
+/*!
+ * jQuery Validation Plugin 1.11.1
+ *
+ * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
+ * http://docs.jquery.com/Plugins/Validation
+ *
+ * Copyright 2013 Jörn Zaefferer
+ * Released under the MIT license:
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+
+(function() {
+
+ function stripHtml(value) {
+ // remove html tags and space chars
+ return value.replace(/<.[^<>]*?>/g, ' ').replace(/&nbsp;|&#160;/gi, ' ')
+ // remove punctuation
+ .replace(/[.(),;:!?%#$'"_+=\/\-]*/g,'');
+ }
+ jQuery.validator.addMethod("maxWords", function(value, element, params) {
+ return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length <= params;
+ }, jQuery.validator.format("Please enter {0} words or less."));
+
+ jQuery.validator.addMethod("minWords", function(value, element, params) {
+ return this.optional(element) || stripHtml(value).match(/\b\w+\b/g).length >= params;
+ }, jQuery.validator.format("Please enter at least {0} words."));
+
+ jQuery.validator.addMethod("rangeWords", function(value, element, params) {
+ var valueStripped = stripHtml(value);
+ var regex = /\b\w+\b/g;
+ return this.optional(element) || valueStripped.match(regex).length >= params[0] && valueStripped.match(regex).length <= params[1];
+ }, jQuery.validator.format("Please enter between {0} and {1} words."));
+
+}());
+
+jQuery.validator.addMethod("letterswithbasicpunc", function(value, element) {
+ return this.optional(element) || /^[a-z\-.,()'"\s]+$/i.test(value);
+}, "Letters or punctuation only please");
+
+jQuery.validator.addMethod("alphanumeric", function(value, element) {
+ return this.optional(element) || /^\w+$/i.test(value);
+}, "Letters, numbers, and underscores only please");
+
+jQuery.validator.addMethod("lettersonly", function(value, element) {
+ return this.optional(element) || /^[a-z]+$/i.test(value);
+}, "Letters only please");
+
+jQuery.validator.addMethod("nowhitespace", function(value, element) {
+ return this.optional(element) || /^\S+$/i.test(value);
+}, "No white space please");
+
+jQuery.validator.addMethod("ziprange", function(value, element) {
+ return this.optional(element) || /^90[2-5]\d\{2\}-\d{4}$/.test(value);
+}, "Your ZIP-code must be in the range 902xx-xxxx to 905-xx-xxxx");
+
+jQuery.validator.addMethod("zipcodeUS", function(value, element) {
+ return this.optional(element) || /\d{5}-\d{4}$|^\d{5}$/.test(value);
+}, "The specified US ZIP Code is invalid");
+
+jQuery.validator.addMethod("integer", function(value, element) {
+ return this.optional(element) || /^-?\d+$/.test(value);
+}, "A positive or negative non-decimal number please");
+
+/**
+ * Return true, if the value is a valid vehicle identification number (VIN).
+ *
+ * Works with all kind of text inputs.
+ *
+ * @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" />
+ * @desc Declares a required input element whose value must be a valid vehicle identification number.
+ *
+ * @name jQuery.validator.methods.vinUS
+ * @type Boolean
+ * @cat Plugins/Validate/Methods
+ */
+jQuery.validator.addMethod("vinUS", function(v) {
+ if (v.length !== 17) {
+ return false;
+ }
+ var i, n, d, f, cd, cdv;
+ var LL = ["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"];
+ var VL = [1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9];
+ var FL = [8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2];
+ var rs = 0;
+ for(i = 0; i < 17; i++){
+ f = FL[i];
+ d = v.slice(i,i+1);
+ if (i === 8) {
+ cdv = d;
+ }
+ if (!isNaN(d)) {
+ d *= f;
+ } else {
+ for (n = 0; n < LL.length; n++) {
+ if (d.toUpperCase() === LL[n]) {
+ d = VL[n];
+ d *= f;
+ if (isNaN(cdv) && n === 8) {
+ cdv = LL[n];
+ }
+ break;
+ }
+ }
+ }
+ rs += d;
+ }
+ cd = rs % 11;
+ if (cd === 10) {
+ cd = "X";
+ }
+ if (cd === cdv) {
+ return true;
+ }
+ return false;
+}, "The specified vehicle identification number (VIN) is invalid.");
+
+/**
+ * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.
+ *
+ * @example jQuery.validator.methods.date("01/01/1900")
+ * @result true
+ *
+ * @example jQuery.validator.methods.date("01/13/1990")
+ * @result false
+ *
+ * @example jQuery.validator.methods.date("01.01.1900")
+ * @result false
+ *
+ * @example <input name="pippo" class="{dateITA:true}" />
+ * @desc Declares an optional input element whose value must be a valid date.
+ *
+ * @name jQuery.validator.methods.dateITA
+ * @type Boolean
+ * @cat Plugins/Validate/Methods
+ */
+jQuery.validator.addMethod("dateITA", function(value, element) {
+ var check = false;
+ var re = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
+ if( re.test(value)) {
+ var adata = value.split('/');
+ var gg = parseInt(adata[0],10);
+ var mm = parseInt(adata[1],10);
+ var aaaa = parseInt(adata[2],10);
+ var xdata = new Date(aaaa,mm-1,gg);
+ if ( ( xdata.getFullYear() === aaaa ) && ( xdata.getMonth() === mm - 1 ) && ( xdata.getDate() === gg ) ){
+ check = true;
+ } else {
+ check = false;
+ }
+ } else {
+ check = false;
+ }
+ return this.optional(element) || check;
+}, "Please enter a correct date");
+
+/**
+ * IBAN is the international bank account number.
+ * It has a country - specific format, that is checked here too
+ */
+jQuery.validator.addMethod("iban", function(value, element) {
+ // some quick simple tests to prevent needless work
+ if (this.optional(element)) {
+ return true;
+ }
+ if (!(/^([a-zA-Z0-9]{4} ){2,8}[a-zA-Z0-9]{1,4}|[a-zA-Z0-9]{12,34}$/.test(value))) {
+ return false;
+ }
+
+ // check the country code and find the country specific format
+ var iban = value.replace(/ /g,'').toUpperCase(); // remove spaces and to upper case
+ var countrycode = iban.substring(0,2);
+ var bbancountrypatterns = {
+ 'AL': "\\d{8}[\\dA-Z]{16}",
+ 'AD': "\\d{8}[\\dA-Z]{12}",
+ 'AT': "\\d{16}",
+ 'AZ': "[\\dA-Z]{4}\\d{20}",
+ 'BE': "\\d{12}",
+ 'BH': "[A-Z]{4}[\\dA-Z]{14}",
+ 'BA': "\\d{16}",
+ 'BR': "\\d{23}[A-Z][\\dA-Z]",
+ 'BG': "[A-Z]{4}\\d{6}[\\dA-Z]{8}",
+ 'CR': "\\d{17}",
+ 'HR': "\\d{17}",
+ 'CY': "\\d{8}[\\dA-Z]{16}",
+ 'CZ': "\\d{20}",
+ 'DK': "\\d{14}",
+ 'DO': "[A-Z]{4}\\d{20}",
+ 'EE': "\\d{16}",
+ 'FO': "\\d{14}",
+ 'FI': "\\d{14}",
+ 'FR': "\\d{10}[\\dA-Z]{11}\\d{2}",
+ 'GE': "[\\dA-Z]{2}\\d{16}",
+ 'DE': "\\d{18}",
+ 'GI': "[A-Z]{4}[\\dA-Z]{15}",
+ 'GR': "\\d{7}[\\dA-Z]{16}",
+ 'GL': "\\d{14}",
+ 'GT': "[\\dA-Z]{4}[\\dA-Z]{20}",
+ 'HU': "\\d{24}",
+ 'IS': "\\d{22}",
+ 'IE': "[\\dA-Z]{4}\\d{14}",
+ 'IL': "\\d{19}",
+ 'IT': "[A-Z]\\d{10}[\\dA-Z]{12}",
+ 'KZ': "\\d{3}[\\dA-Z]{13}",
+ 'KW': "[A-Z]{4}[\\dA-Z]{22}",
+ 'LV': "[A-Z]{4}[\\dA-Z]{13}",
+ 'LB': "\\d{4}[\\dA-Z]{20}",
+ 'LI': "\\d{5}[\\dA-Z]{12}",
+ 'LT': "\\d{16}",
+ 'LU': "\\d{3}[\\dA-Z]{13}",
+ 'MK': "\\d{3}[\\dA-Z]{10}\\d{2}",
+ 'MT': "[A-Z]{4}\\d{5}[\\dA-Z]{18}",
+ 'MR': "\\d{23}",
+ 'MU': "[A-Z]{4}\\d{19}[A-Z]{3}",
+ 'MC': "\\d{10}[\\dA-Z]{11}\\d{2}",
+ 'MD': "[\\dA-Z]{2}\\d{18}",
+ 'ME': "\\d{18}",
+ 'NL': "[A-Z]{4}\\d{10}",
+ 'NO': "\\d{11}",
+ 'PK': "[\\dA-Z]{4}\\d{16}",
+ 'PS': "[\\dA-Z]{4}\\d{21}",
+ 'PL': "\\d{24}",
+ 'PT': "\\d{21}",
+ 'RO': "[A-Z]{4}[\\dA-Z]{16}",
+ 'SM': "[A-Z]\\d{10}[\\dA-Z]{12}",
+ 'SA': "\\d{2}[\\dA-Z]{18}",
+ 'RS': "\\d{18}",
+ 'SK': "\\d{20}",
+ 'SI': "\\d{15}",
+ 'ES': "\\d{20}",
+ 'SE': "\\d{20}",
+ 'CH': "\\d{5}[\\dA-Z]{12}",
+ 'TN': "\\d{20}",
+ 'TR': "\\d{5}[\\dA-Z]{17}",
+ 'AE': "\\d{3}\\d{16}",
+ 'GB': "[A-Z]{4}\\d{14}",
+ 'VG': "[\\dA-Z]{4}\\d{16}"
+ };
+ var bbanpattern = bbancountrypatterns[countrycode];
+ // As new countries will start using IBAN in the
+ // future, we only check if the countrycode is known.
+ // This prevents false negatives, while almost all
+ // false positives introduced by this, will be caught
+ // by the checksum validation below anyway.
+ // Strict checking should return FALSE for unknown
+ // countries.
+ if (typeof bbanpattern !== 'undefined') {
+ var ibanregexp = new RegExp("^[A-Z]{2}\\d{2}" + bbanpattern + "$", "");
+ if (!(ibanregexp.test(iban))) {
+ return false; // invalid country specific format
+ }
+ }
+
+ // now check the checksum, first convert to digits
+ var ibancheck = iban.substring(4,iban.length) + iban.substring(0,4);
+ var ibancheckdigits = "";
+ var leadingZeroes = true;
+ var charAt;
+ for (var i =0; i<ibancheck.length; i++) {
+ charAt = ibancheck.charAt(i);
+ if (charAt !== "0") {
+ leadingZeroes = false;
+ }
+ if (!leadingZeroes) {
+ ibancheckdigits += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(charAt);
+ }
+ }
+
+ // calculate the result of: ibancheckdigits % 97
+ var cRest = '';
+ var cOperator = '';
+ for (var p=0; p<ibancheckdigits.length; p++) {
+ var cChar = ibancheckdigits.charAt(p);
+ cOperator = '' + cRest + '' + cChar;
+ cRest = cOperator % 97;
+ }
+ return cRest === 1;
+}, "Please specify a valid IBAN");
+
+jQuery.validator.addMethod("dateNL", function(value, element) {
+ return this.optional(element) || /^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(value);
+}, "Please enter a correct date");
+
+/**
+ * Dutch phone numbers have 10 digits (or 11 and start with +31).
+ */
+jQuery.validator.addMethod("phoneNL", function(value, element) {
+ return this.optional(element) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test(value);
+}, "Please specify a valid phone number.");
+
+jQuery.validator.addMethod("mobileNL", function(value, element) {
+ return this.optional(element) || /^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test(value);
+}, "Please specify a valid mobile number");
+
+jQuery.validator.addMethod("postalcodeNL", function(value, element) {
+ return this.optional(element) || /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(value);
+}, "Please specify a valid postal code");
+
+/*
+ * Dutch bank account numbers (not 'giro' numbers) have 9 digits
+ * and pass the '11 check'.
+ * We accept the notation with spaces, as that is common.
+ * acceptable: 123456789 or 12 34 56 789
+ */
+jQuery.validator.addMethod("bankaccountNL", function(value, element) {
+ if (this.optional(element)) {
+ return true;
+ }
+ if (!(/^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test(value))) {
+ return false;
+ }
+ // now '11 check'
+ var account = value.replace(/ /g,''); // remove spaces
+ var sum = 0;
+ var len = account.length;
+ for (var pos=0; pos<len; pos++) {
+ var factor = len - pos;
+ var digit = account.substring(pos, pos+1);
+ sum = sum + factor * digit;
+ }
+ return sum % 11 === 0;
+}, "Please specify a valid bank account number");
+
+/**
+ * Dutch giro account numbers (not bank numbers) have max 7 digits
+ */
+jQuery.validator.addMethod("giroaccountNL", function(value, element) {
+ return this.optional(element) || /^[0-9]{1,7}$/.test(value);
+}, "Please specify a valid giro account number");
+
+jQuery.validator.addMethod("bankorgiroaccountNL", function(value, element) {
+ return this.optional(element) ||
+ ($.validator.methods["bankaccountNL"].call(this, value, element)) ||
+ ($.validator.methods["giroaccountNL"].call(this, value, element));
+}, "Please specify a valid bank or giro account number");
+
+
+jQuery.validator.addMethod("time", function(value, element) {
+ return this.optional(element) || /^([01]\d|2[0-3])(:[0-5]\d){1,2}$/.test(value);
+}, "Please enter a valid time, between 00:00 and 23:59");
+jQuery.validator.addMethod("time12h", function(value, element) {
+ return this.optional(element) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(value);
+}, "Please enter a valid time in 12-hour am/pm format");
+
+/**
+ * matches US phone number format
+ *
+ * where the area code may not start with 1 and the prefix may not start with 1
+ * allows '-' or ' ' as a separator and allows parens around area code
+ * some people may want to put a '1' in front of their number
+ *
+ * 1(212)-999-2345 or
+ * 212 999 2344 or
+ * 212-999-0983
+ *
+ * but not
+ * 111-123-5434
+ * and not
+ * 212 123 4567
+ */
+jQuery.validator.addMethod("phoneUS", function(phone_number, element) {
+ phone_number = phone_number.replace(/\s+/g, "");
+ return this.optional(element) || phone_number.length > 9 &&
+ phone_number.match(/^(\+?1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/);
+}, "Please specify a valid phone number");
+
+jQuery.validator.addMethod('phoneUK', function(phone_number, element) {
+ phone_number = phone_number.replace(/\(|\)|\s+|-/g,'');
+ return this.optional(element) || phone_number.length > 9 &&
+ phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/);
+}, 'Please specify a valid phone number');
+
+jQuery.validator.addMethod('mobileUK', function(phone_number, element) {
+ phone_number = phone_number.replace(/\(|\)|\s+|-/g,'');
+ return this.optional(element) || phone_number.length > 9 &&
+ phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[45789]\d{2}|624)\s?\d{3}\s?\d{3})$/);
+}, 'Please specify a valid mobile number');
+
+//Matches UK landline + mobile, accepting only 01-3 for landline or 07 for mobile to exclude many premium numbers
+jQuery.validator.addMethod('phonesUK', function(phone_number, element) {
+ phone_number = phone_number.replace(/\(|\)|\s+|-/g,'');
+ return this.optional(element) || phone_number.length > 9 &&
+ phone_number.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[45789]\d{8}|624\d{6})))$/);
+}, 'Please specify a valid uk phone number');
+// On the above three UK functions, do the following server side processing:
+// Compare original input with this RegEx pattern:
+// ^\(?(?:(?:00\)?[\s\-]?\(?|\+)(44)\)?[\s\-]?\(?(?:0\)?[\s\-]?\(?)?|0)([1-9]\d{1,4}\)?[\s\d\-]+)$
+// Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'
+// Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.
+// A number of very detailed GB telephone number RegEx patterns can also be found at:
+// http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers
+
+// Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK)
+jQuery.validator.addMethod('postcodeUK', function(value, element) {
+ return this.optional(element) || /^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(value);
+}, 'Please specify a valid UK postcode');
+
+// TODO check if value starts with <, otherwise don't try stripping anything
+jQuery.validator.addMethod("strippedminlength", function(value, element, param) {
+ return jQuery(value).text().length >= param;
+}, jQuery.validator.format("Please enter at least {0} characters"));
+
+// same as email, but TLD is optional
+jQuery.validator.addMethod("email2", function(value, element, param) {
+ return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
+}, jQuery.validator.messages.email);
+
+// same as url, but TLD is optional
+jQuery.validator.addMethod("url2", function(value, element, param) {
+ return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
+}, jQuery.validator.messages.url);
+
+// NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator
+// Redistributed under the the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0
+// Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings)
+jQuery.validator.addMethod("creditcardtypes", function(value, element, param) {
+ if (/[^0-9\-]+/.test(value)) {
+ return false;
+ }
+
+ value = value.replace(/\D/g, "");
+
+ var validTypes = 0x0000;
+
+ if (param.mastercard) {
+ validTypes |= 0x0001;
+ }
+ if (param.visa) {
+ validTypes |= 0x0002;
+ }
+ if (param.amex) {
+ validTypes |= 0x0004;
+ }
+ if (param.dinersclub) {
+ validTypes |= 0x0008;
+ }
+ if (param.enroute) {
+ validTypes |= 0x0010;
+ }
+ if (param.discover) {
+ validTypes |= 0x0020;
+ }
+ if (param.jcb) {
+ validTypes |= 0x0040;
+ }
+ if (param.unknown) {
+ validTypes |= 0x0080;
+ }
+ if (param.all) {
+ validTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;
+ }
+ if (validTypes & 0x0001 && /^(5[12345])/.test(value)) { //mastercard
+ return value.length === 16;
+ }
+ if (validTypes & 0x0002 && /^(4)/.test(value)) { //visa
+ return value.length === 16;
+ }
+ if (validTypes & 0x0004 && /^(3[47])/.test(value)) { //amex
+ return value.length === 15;
+ }
+ if (validTypes & 0x0008 && /^(3(0[012345]|[68]))/.test(value)) { //dinersclub
+ return value.length === 14;
+ }
+ if (validTypes & 0x0010 && /^(2(014|149))/.test(value)) { //enroute
+ return value.length === 15;
+ }
+ if (validTypes & 0x0020 && /^(6011)/.test(value)) { //discover
+ return value.length === 16;
+ }
+ if (validTypes & 0x0040 && /^(3)/.test(value)) { //jcb
+ return value.length === 16;
+ }
+ if (validTypes & 0x0040 && /^(2131|1800)/.test(value)) { //jcb
+ return value.length === 15;
+ }
+ if (validTypes & 0x0080) { //unknown
+ return true;
+ }
+ return false;
+}, "Please enter a valid credit card number.");
+
+jQuery.validator.addMethod("ipv4", function(value, element, param) {
+ return this.optional(element) || /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test(value);
+}, "Please enter a valid IP v4 address.");
+
+jQuery.validator.addMethod("ipv6", function(value, element, param) {
+ return this.optional(element) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test(value);
+}, "Please enter a valid IP v6 address.");
+
+/**
+* Return true if the field value matches the given format RegExp
+*
+* @example jQuery.validator.methods.pattern("AR1004",element,/^AR\d{4}$/)
+* @result true
+*
+* @example jQuery.validator.methods.pattern("BR1004",element,/^AR\d{4}$/)
+* @result false
+*
+* @name jQuery.validator.methods.pattern
+* @type Boolean
+* @cat Plugins/Validate/Methods
+*/
+jQuery.validator.addMethod("pattern", function(value, element, param) {
+ if (this.optional(element)) {
+ return true;
+ }
+ if (typeof param === 'string') {
+ param = new RegExp('^(?:' + param + ')$');
+ }
+ return param.test(value);
+}, "Invalid format.");
+
+
+/*
+ * Lets you say "at least X inputs that match selector Y must be filled."
+ *
+ * The end result is that neither of these inputs:
+ *
+ * <input class="productinfo" name="partnumber">
+ * <input class="productinfo" name="description">
+ *
+ * ...will validate unless at least one of them is filled.
+ *
+ * partnumber: {require_from_group: [1,".productinfo"]},
+ * description: {require_from_group: [1,".productinfo"]}
+ *
+ */
+jQuery.validator.addMethod("require_from_group", function(value, element, options) {
+ var validator = this;
+ var selector = options[1];
+ var validOrNot = $(selector, element.form).filter(function() {
+ return validator.elementValue(this);
+ }).length >= options[0];
+
+ if(!$(element).data('being_validated')) {
+ var fields = $(selector, element.form);
+ fields.data('being_validated', true);
+ fields.valid();
+ fields.data('being_validated', false);
+ }
+ return validOrNot;
+}, jQuery.format("Please fill at least {0} of these fields."));
+
+/*
+ * Lets you say "either at least X inputs that match selector Y must be filled,
+ * OR they must all be skipped (left blank)."
+ *
+ * The end result, is that none of these inputs:
+ *
+ * <input class="productinfo" name="partnumber">
+ * <input class="productinfo" name="description">
+ * <input class="productinfo" name="color">
+ *
+ * ...will validate unless either at least two of them are filled,
+ * OR none of them are.
+ *
+ * partnumber: {skip_or_fill_minimum: [2,".productinfo"]},
+ * description: {skip_or_fill_minimum: [2,".productinfo"]},
+ * color: {skip_or_fill_minimum: [2,".productinfo"]}
+ *
+ */
+jQuery.validator.addMethod("skip_or_fill_minimum", function(value, element, options) {
+ var validator = this,
+ numberRequired = options[0],
+ selector = options[1];
+ var numberFilled = $(selector, element.form).filter(function() {
+ return validator.elementValue(this);
+ }).length;
+ var valid = numberFilled >= numberRequired || numberFilled === 0;
+
+ if(!$(element).data('being_validated')) {
+ var fields = $(selector, element.form);
+ fields.data('being_validated', true);
+ fields.valid();
+ fields.data('being_validated', false);
+ }
+ return valid;
+}, jQuery.format("Please either skip these fields or fill at least {0} of them."));
+
+// Accept a value from a file input based on a required mimetype
+jQuery.validator.addMethod("accept", function(value, element, param) {
+ // Split mime on commas in case we have multiple types we can accept
+ var typeParam = typeof param === "string" ? param.replace(/\s/g, '').replace(/,/g, '|') : "image/*",
+ optionalValue = this.optional(element),
+ i, file;
+
+ // Element is optional
+ if (optionalValue) {
+ return optionalValue;
+ }
+
+ if ($(element).attr("type") === "file") {
+ // If we are using a wildcard, make it regex friendly
+ typeParam = typeParam.replace(/\*/g, ".*");
+
+ // Check if the element has a FileList before checking each file
+ if (element.files && element.files.length) {
+ for (i = 0; i < element.files.length; i++) {
+ file = element.files[i];
+
+ // Grab the mimetype from the loaded file, verify it matches
+ if (!file.type.match(new RegExp( ".?(" + typeParam + ")$", "i"))) {
+ return false;
+ }
+ }
+ }
+ }
+
+ // Either return true because we've validated each file, or because the
+ // browser does not support element.files and the FileList feature
+ return true;
+}, jQuery.format("Please enter a value with a valid mimetype."));
+
+// Older "accept" file extension method. Old docs: http://docs.jquery.com/Plugins/Validation/Methods/accept
+jQuery.validator.addMethod("extension", function(value, element, param) {
+ param = typeof param === "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
+ return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
+}, jQuery.format("Please enter a value with a valid extension."));
diff --git a/views/js/jquery-validation-1.11.1/dist/additional-methods.min.js b/views/js/jquery-validation-1.11.1/dist/additional-methods.min.js
new file mode 100644
index 0000000..0c5539a
--- /dev/null
+++ b/views/js/jquery-validation-1.11.1/dist/additional-methods.min.js
@@ -0,0 +1,2 @@
+/*! jQuery Validation Plugin - v1.11.1 - 3/22/2013\n* https://github.com/jzaefferer/jquery-validation
+* Copyright (c) 2013 Jörn Zaefferer; Licensed MIT */(function(){function t(t){return t.replace(/<.[^<>]*?>/g," ").replace(/&nbsp;|&#160;/gi," ").replace(/[.(),;:!?%#$'"_+=\/\-]*/g,"")}jQuery.validator.addMethod("maxWords",function(e,i,a){return this.optional(i)||a>=t(e).match(/\b\w+\b/g).length},jQuery.validator.format("Please enter {0} words or less.")),jQuery.validator.addMethod("minWords",function(e,i,a){return this.optional(i)||t(e).match(/\b\w+\b/g).length>=a},jQuery.validator.format("Please enter at least {0} words.")),jQuery.validator.addMethod("rangeWords",function(e,i,a){var r=t(e),n=/\b\w+\b/g;return this.optional(i)||r.match(n).length>=a[0]&&r.match(n).length<=a[1]},jQuery.validator.format("Please enter between {0} and {1} words."))})(),jQuery.validator.addMethod("letterswithbasicpunc",function(t,e){return this.optional(e)||/^[a-z\-.,()'"\s]+$/i.test(t)},"Letters or punctuation only please"),jQuery.validator.addMethod("alphanumeric",function(t,e){return this.optional(e)||/^\w+$/i.test(t)},"Letters, numbers, and underscores only please"),jQuery.validator.addMethod("lettersonly",function(t,e){return this.optional(e)||/^[a-z]+$/i.test(t)},"Letters only please"),jQuery.validator.addMethod("nowhitespace",function(t,e){return this.optional(e)||/^\S+$/i.test(t)},"No white space please"),jQuery.validator.addMethod("ziprange",function(t,e){return this.optional(e)||/^90[2-5]\d\{2\}-\d{4}$/.test(t)},"Your ZIP-code must be in the range 902xx-xxxx to 905-xx-xxxx"),jQuery.validator.addMethod("zipcodeUS",function(t,e){return this.optional(e)||/\d{5}-\d{4}$|^\d{5}$/.test(t)},"The specified US ZIP Code is invalid"),jQuery.validator.addMethod("integer",function(t,e){return this.optional(e)||/^-?\d+$/.test(t)},"A positive or negative non-decimal number please"),jQuery.validator.addMethod("vinUS",function(t){if(17!==t.length)return!1;var e,i,a,r,n,s,u=["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"],d=[1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9],o=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2],l=0;for(e=0;17>e;e++){if(r=o[e],a=t.slice(e,e+1),8===e&&(s=a),isNaN(a)){for(i=0;u.length>i;i++)if(a.toUpperCase()===u[i]){a=d[i],a*=r,isNaN(s)&&8===i&&(s=u[i]);break}}else a*=r;l+=a}return n=l%11,10===n&&(n="X"),n===s?!0:!1},"The specified vehicle identification number (VIN) is invalid."),jQuery.validator.addMethod("dateITA",function(t,e){var i=!1,a=/^\d{1,2}\/\d{1,2}\/\d{4}$/;if(a.test(t)){var r=t.split("/"),n=parseInt(r[0],10),s=parseInt(r[1],10),u=parseInt(r[2],10),d=new Date(u,s-1,n);i=d.getFullYear()===u&&d.getMonth()===s-1&&d.getDate()===n?!0:!1}else i=!1;return this.optional(e)||i},"Please enter a correct date"),jQuery.validator.addMethod("iban",function(t,e){if(this.optional(e))return!0;if(!/^([a-zA-Z0-9]{4} ){2,8}[a-zA-Z0-9]{1,4}|[a-zA-Z0-9]{12,34}$/.test(t))return!1;var i=t.replace(/ /g,"").toUpperCase(),a=i.substring(0,2),r={AL:"\\d{8}[\\dA-Z]{16}",AD:"\\d{8}[\\dA-Z]{12}",AT:"\\d{16}",AZ:"[\\dA-Z]{4}\\d{20}",BE:"\\d{12}",BH:"[A-Z]{4}[\\dA-Z]{14}",BA:"\\d{16}",BR:"\\d{23}[A-Z][\\dA-Z]",BG:"[A-Z]{4}\\d{6}[\\dA-Z]{8}",CR:"\\d{17}",HR:"\\d{17}",CY:"\\d{8}[\\dA-Z]{16}",CZ:"\\d{20}",DK:"\\d{14}",DO:"[A-Z]{4}\\d{20}",EE:"\\d{16}",FO:"\\d{14}",FI:"\\d{14}",FR:"\\d{10}[\\dA-Z]{11}\\d{2}",GE:"[\\dA-Z]{2}\\d{16}",DE:"\\d{18}",GI:"[A-Z]{4}[\\dA-Z]{15}",GR:"\\d{7}[\\dA-Z]{16}",GL:"\\d{14}",GT:"[\\dA-Z]{4}[\\dA-Z]{20}",HU:"\\d{24}",IS:"\\d{22}",IE:"[\\dA-Z]{4}\\d{14}",IL:"\\d{19}",IT:"[A-Z]\\d{10}[\\dA-Z]{12}",KZ:"\\d{3}[\\dA-Z]{13}",KW:"[A-Z]{4}[\\dA-Z]{22}",LV:"[A-Z]{4}[\\dA-Z]{13}",LB:"\\d{4}[\\dA-Z]{20}",LI:"\\d{5}[\\dA-Z]{12}",LT:"\\d{16}",LU:"\\d{3}[\\dA-Z]{13}",MK:"\\d{3}[\\dA-Z]{10}\\d{2}",MT:"[A-Z]{4}\\d{5}[\\dA-Z]{18}",MR:"\\d{23}",MU:"[A-Z]{4}\\d{19}[A-Z]{3}",MC:"\\d{10}[\\dA-Z]{11}\\d{2}",MD:"[\\dA-Z]{2}\\d{18}",ME:"\\d{18}",NL:"[A-Z]{4}\\d{10}",NO:"\\d{11}",PK:"[\\dA-Z]{4}\\d{16}",PS:"[\\dA-Z]{4}\\d{21}",PL:"\\d{24}",PT:"\\d{21}",RO:"[A-Z]{4}[\\dA-Z]{16}",SM:"[A-Z]\\d{10}[\\dA-Z]{12}",SA:"\\d{2}[\\dA-Z]{18}",RS:"\\d{18}",SK:"\\d{20}",SI:"\\d{15}",ES:"\\d{20}",SE:"\\d{20}",CH:"\\d{5}[\\dA-Z]{12}",TN:"\\d{20}",TR:"\\d{5}[\\dA-Z]{17}",AE:"\\d{3}\\d{16}",GB:"[A-Z]{4}\\d{14}",VG:"[\\dA-Z]{4}\\d{16}"},n=r[a];if(n!==void 0){var s=RegExp("^[A-Z]{2}\\d{2}"+n+"$","");if(!s.test(i))return!1}for(var u,d=i.substring(4,i.length)+i.substring(0,4),o="",l=!0,h=0;d.length>h;h++)u=d.charAt(h),"0"!==u&&(l=!1),l||(o+="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(u));for(var F="",c="",m=0;o.length>m;m++){var f=o.charAt(m);c=""+F+f,F=c%97}return 1===F},"Please specify a valid IBAN"),jQuery.validator.addMethod("dateNL",function(t,e){return this.optional(e)||/^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(t)},"Please enter a correct date"),jQuery.validator.addMethod("phoneNL",function(t,e){return this.optional(e)||/^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test(t)},"Please specify a valid phone number."),jQuery.validator.addMethod("mobileNL",function(t,e){return this.optional(e)||/^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)6((\s|\s?\-\s?)?[0-9]){8}$/.test(t)},"Please specify a valid mobile number"),jQuery.validator.addMethod("postalcodeNL",function(t,e){return this.optional(e)||/^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(t)},"Please specify a valid postal code"),jQuery.validator.addMethod("bankaccountNL",function(t,e){if(this.optional(e))return!0;if(!/^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test(t))return!1;for(var i=t.replace(/ /g,""),a=0,r=i.length,n=0;r>n;n++){var s=r-n,u=i.substring(n,n+1);a+=s*u}return 0===a%11},"Please specify a valid bank account number"),jQuery.validator.addMethod("giroaccountNL",function(t,e){return this.optional(e)||/^[0-9]{1,7}$/.test(t)},"Please specify a valid giro account number"),jQuery.validator.addMethod("bankorgiroaccountNL",function(t,e){return this.optional(e)||$.validator.methods.bankaccountNL.call(this,t,e)||$.validator.methods.giroaccountNL.call(this,t,e)},"Please specify a valid bank or giro account number"),jQuery.validator.addMethod("time",function(t,e){return this.optional(e)||/^([01]\d|2[0-3])(:[0-5]\d){1,2}$/.test(t)},"Please enter a valid time, between 00:00 and 23:59"),jQuery.validator.addMethod("time12h",function(t,e){return this.optional(e)||/^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(t)},"Please enter a valid time in 12-hour am/pm format"),jQuery.validator.addMethod("phoneUS",function(t,e){return t=t.replace(/\s+/g,""),this.optional(e)||t.length>9&&t.match(/^(\+?1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/)},"Please specify a valid phone number"),jQuery.validator.addMethod("phoneUK",function(t,e){return t=t.replace(/\(|\)|\s+|-/g,""),this.optional(e)||t.length>9&&t.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/)},"Please specify a valid phone number"),jQuery.validator.addMethod("mobileUK",function(t,e){return t=t.replace(/\(|\)|\s+|-/g,""),this.optional(e)||t.length>9&&t.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[45789]\d{2}|624)\s?\d{3}\s?\d{3})$/)},"Please specify a valid mobile number"),jQuery.validator.addMethod("phonesUK",function(t,e){return t=t.replace(/\(|\)|\s+|-/g,""),this.optional(e)||t.length>9&&t.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[45789]\d{8}|624\d{6})))$/)},"Please specify a valid uk phone number"),jQuery.validator.addMethod("postcodeUK",function(t,e){return this.optional(e)||/^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(t)},"Please specify a valid UK postcode"),jQuery.validator.addMethod("strippedminlength",function(t,e,i){return jQuery(t).text().length>=i},jQuery.validator.format("Please enter at least {0} characters")),jQuery.validator.addMethod("email2",function(t,e){return this.optional(e)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(t)},jQuery.validator.messages.email),jQuery.validator.addMethod("url2",function(t,e){return this.optional(e)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(t)},jQuery.validator.messages.url),jQuery.validator.addMethod("creditcardtypes",function(t,e,i){if(/[^0-9\-]+/.test(t))return!1;t=t.replace(/\D/g,"");var a=0;return i.mastercard&&(a|=1),i.visa&&(a|=2),i.amex&&(a|=4),i.dinersclub&&(a|=8),i.enroute&&(a|=16),i.discover&&(a|=32),i.jcb&&(a|=64),i.unknown&&(a|=128),i.all&&(a=255),1&a&&/^(5[12345])/.test(t)?16===t.length:2&a&&/^(4)/.test(t)?16===t.length:4&a&&/^(3[47])/.test(t)?15===t.length:8&a&&/^(3(0[012345]|[68]))/.test(t)?14===t.length:16&a&&/^(2(014|149))/.test(t)?15===t.length:32&a&&/^(6011)/.test(t)?16===t.length:64&a&&/^(3)/.test(t)?16===t.length:64&a&&/^(2131|1800)/.test(t)?15===t.length:128&a?!0:!1},"Please enter a valid credit card number."),jQuery.validator.addMethod("ipv4",function(t,e){return this.optional(e)||/^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i.test(t)},"Please enter a valid IP v4 address."),jQuery.validator.addMethod("ipv6",function(t,e){return this.optional(e)||/^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test(t)},"Please enter a valid IP v6 address."),jQuery.validator.addMethod("pattern",function(t,e,i){return this.optional(e)?!0:("string"==typeof i&&(i=RegExp("^(?:"+i+")$")),i.test(t))},"Invalid format."),jQuery.validator.addMethod("require_from_group",function(t,e,i){var a=this,r=i[1],n=$(r,e.form).filter(function(){return a.elementValue(this)}).length>=i[0];if(!$(e).data("being_validated")){var s=$(r,e.form);s.data("being_validated",!0),s.valid(),s.data("being_validated",!1)}return n},jQuery.format("Please fill at least {0} of these fields.")),jQuery.validator.addMethod("skip_or_fill_minimum",function(t,e,i){var a=this,r=i[0],n=i[1],s=$(n,e.form).filter(function(){return a.elementValue(this)}).length,u=s>=r||0===s;if(!$(e).data("being_validated")){var d=$(n,e.form);d.data("being_validated",!0),d.valid(),d.data("being_validated",!1)}return u},jQuery.format("Please either skip these fields or fill at least {0} of them.")),jQuery.validator.addMethod("accept",function(t,e,i){var a,r,n="string"==typeof i?i.replace(/\s/g,"").replace(/,/g,"|"):"image/*",s=this.optional(e);if(s)return s;if("file"===$(e).attr("type")&&(n=n.replace(/\*/g,".*"),e.files&&e.files.length))for(a=0;e.files.length>a;a++)if(r=e.files[a],!r.type.match(RegExp(".?("+n+")$","i")))return!1;return!0},jQuery.format("Please enter a value with a valid mimetype.")),jQuery.validator.addMethod("extension",function(t,e,i){return i="string"==typeof i?i.replace(/,/g,"|"):"png|jpe?g|gif",this.optional(e)||t.match(RegExp(".("+i+")$","i"))},jQuery.format("Please enter a value with a valid extension.")); \ No newline at end of file
diff --git a/views/js/jquery-validation-1.11.1/dist/jquery.validate.js b/views/js/jquery-validation-1.11.1/dist/jquery.validate.js
new file mode 100644
index 0000000..ccbba7f
--- /dev/null
+++ b/views/js/jquery-validation-1.11.1/dist/jquery.validate.js
@@ -0,0 +1,1235 @@
+/*!
+ * jQuery Validation Plugin 1.11.1
+ *
+ * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
+ * http://docs.jquery.com/Plugins/Validation
+ *
+ * Copyright 2013 Jörn Zaefferer
+ * Released under the MIT license:
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+
+(function($) {
+
+$.extend($.fn, {
+ // http://docs.jquery.com/Plugins/Validation/validate
+ validate: function( options ) {
+
+ // if nothing is selected, return nothing; can't chain anyway
+ if ( !this.length ) {
+ if ( options && options.debug && window.console ) {
+ console.warn( "Nothing selected, can't validate, returning nothing." );
+ }
+ return;
+ }
+
+ // check if a validator for this form was already created
+ var validator = $.data( this[0], "validator" );
+ if ( validator ) {
+ return validator;
+ }
+
+ // Add novalidate tag if HTML5.
+ this.attr( "novalidate", "novalidate" );
+
+ validator = new $.validator( options, this[0] );
+ $.data( this[0], "validator", validator );
+
+ if ( validator.settings.onsubmit ) {
+
+ this.validateDelegate( ":submit", "click", function( event ) {
+ if ( validator.settings.submitHandler ) {
+ validator.submitButton = event.target;
+ }
+ // allow suppressing validation by adding a cancel class to the submit button
+ if ( $(event.target).hasClass("cancel") ) {
+ validator.cancelSubmit = true;
+ }
+
+ // allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
+ if ( $(event.target).attr("formnovalidate") !== undefined ) {
+ validator.cancelSubmit = true;
+ }
+ });
+
+ // validate the form on submit
+ this.submit( function( event ) {
+ if ( validator.settings.debug ) {
+ // prevent form submit to be able to see console output
+ event.preventDefault();
+ }
+ function handle() {
+ var hidden;
+ if ( validator.settings.submitHandler ) {
+ if ( validator.submitButton ) {
+ // insert a hidden input as a replacement for the missing submit button
+ hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val( $(validator.submitButton).val() ).appendTo(validator.currentForm);
+ }
+ validator.settings.submitHandler.call( validator, validator.currentForm, event );
+ if ( validator.submitButton ) {
+ // and clean up afterwards; thanks to no-block-scope, hidden can be referenced
+ hidden.remove();
+ }
+ return false;
+ }
+ return true;
+ }
+
+ // prevent submit for invalid forms or custom submit handlers
+ if ( validator.cancelSubmit ) {
+ validator.cancelSubmit = false;
+ return handle();
+ }
+ if ( validator.form() ) {
+ if ( validator.pendingRequest ) {
+ validator.formSubmitted = true;
+ return false;
+ }
+ return handle();
+ } else {
+ validator.focusInvalid();
+ return false;
+ }
+ });
+ }
+
+ return validator;
+ },
+ // http://docs.jquery.com/Plugins/Validation/valid
+ valid: function() {
+ if ( $(this[0]).is("form")) {
+ return this.validate().form();
+ } else {
+ var valid = true;
+ var validator = $(this[0].form).validate();
+ this.each(function() {
+ valid = valid && validator.element(this);
+ });
+ return valid;
+ }
+ },
+ // attributes: space seperated list of attributes to retrieve and remove
+ removeAttrs: function( attributes ) {
+ var result = {},
+ $element = this;
+ $.each(attributes.split(/\s/), function( index, value ) {
+ result[value] = $element.attr(value);
+ $element.removeAttr(value);
+ });
+ return result;
+ },
+ // http://docs.jquery.com/Plugins/Validation/rules
+ rules: function( command, argument ) {
+ var element = this[0];
+
+ if ( command ) {
+ var settings = $.data(element.form, "validator").settings;
+ var staticRules = settings.rules;
+ var existingRules = $.validator.staticRules(element);
+ switch(command) {
+ case "add":
+ $.extend(existingRules, $.validator.normalizeRule(argument));
+ // remove messages from rules, but allow them to be set separetely
+ delete existingRules.messages;
+ staticRules[element.name] = existingRules;
+ if ( argument.messages ) {
+ settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
+ }
+ break;
+ case "remove":
+ if ( !argument ) {
+ delete staticRules[element.name];
+ return existingRules;
+ }
+ var filtered = {};
+ $.each(argument.split(/\s/), function( index, method ) {
+ filtered[method] = existingRules[method];
+ delete existingRules[method];
+ });
+ return filtered;
+ }
+ }
+
+ var data = $.validator.normalizeRules(
+ $.extend(
+ {},
+ $.validator.classRules(element),
+ $.validator.attributeRules(element),
+ $.validator.dataRules(element),
+ $.validator.staticRules(element)
+ ), element);
+
+ // make sure required is at front
+ if ( data.required ) {
+ var param = data.required;
+ delete data.required;
+ data = $.extend({required: param}, data);
+ }
+
+ return data;
+ }
+});
+
+// Custom selectors
+$.extend($.expr[":"], {
+ // http://docs.jquery.com/Plugins/Validation/blank
+ blank: function( a ) { return !$.trim("" + $(a).val()); },
+ // http://docs.jquery.com/Plugins/Validation/filled
+ filled: function( a ) { return !!$.trim("" + $(a).val()); },
+ // http://docs.jquery.com/Plugins/Validation/unchecked
+ unchecked: function( a ) { return !$(a).prop("checked"); }
+});
+
+// constructor for validator
+$.validator = function( options, form ) {
+ this.settings = $.extend( true, {}, $.validator.defaults, options );
+ this.currentForm = form;
+ this.init();
+};
+
+$.validator.format = function( source, params ) {
+ if ( arguments.length === 1 ) {
+ return function() {
+ var args = $.makeArray(arguments);
+ args.unshift(source);
+ return $.validator.format.apply( this, args );
+ };
+ }
+ if ( arguments.length > 2 && params.constructor !== Array ) {
+ params = $.makeArray(arguments).slice(1);
+ }
+ if ( params.constructor !== Array ) {
+ params = [ params ];
+ }
+ $.each(params, function( i, n ) {
+ source = source.replace( new RegExp("\\{" + i + "\\}", "g"), function() {
+ return n;
+ });
+ });
+ return source;
+};
+
+$.extend($.validator, {
+
+ defaults: {
+ messages: {},
+ groups: {},
+ rules: {},
+ errorClass: "error",
+ validClass: "valid",
+ errorElement: "label",
+ focusInvalid: true,
+ errorContainer: $([]),
+ errorLabelContainer: $([]),
+ onsubmit: true,
+ ignore: ":hidden",
+ ignoreTitle: false,
+ onfocusin: function( element, event ) {
+ this.lastActive = element;
+
+ // hide error label and remove error class on focus if enabled
+ if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
+ if ( this.settings.unhighlight ) {
+ this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
+ }
+ this.addWrapper(this.errorsFor(element)).hide();
+ }
+ },
+ onfocusout: function( element, event ) {
+ if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
+ this.element(element);
+ }
+ },
+ onkeyup: function( element, event ) {
+ if ( event.which === 9 && this.elementValue(element) === "" ) {
+ return;
+ } else if ( element.name in this.submitted || element === this.lastElement ) {
+ this.element(element);
+ }
+ },
+ onclick: function( element, event ) {
+ // click on selects, radiobuttons and checkboxes
+ if ( element.name in this.submitted ) {
+ this.element(element);
+ }
+ // or option elements, check parent select in that case
+ else if ( element.parentNode.name in this.submitted ) {
+ this.element(element.parentNode);
+ }
+ },
+ highlight: function( element, errorClass, validClass ) {
+ if ( element.type === "radio" ) {
+ this.findByName(element.name).addClass(errorClass).removeClass(validClass);
+ } else {
+ $(element).addClass(errorClass).removeClass(validClass);
+ }
+ },
+ unhighlight: function( element, errorClass, validClass ) {
+ if ( element.type === "radio" ) {
+ this.findByName(element.name).removeClass(errorClass).addClass(validClass);
+ } else {
+ $(element).removeClass(errorClass).addClass(validClass);
+ }
+ }
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
+ setDefaults: function( settings ) {
+ $.extend( $.validator.defaults, settings );
+ },
+
+ messages: {
+ required: "This field is required.",
+ remote: "Please fix this field.",
+ email: "Please enter a valid email address.",
+ url: "Please enter a valid URL.",
+ date: "Please enter a valid date.",
+ dateISO: "Please enter a valid date (ISO).",
+ number: "Please enter a valid number.",
+ digits: "Please enter only digits.",
+ creditcard: "Please enter a valid credit card number.",
+ equalTo: "Please enter the same value again.",
+ maxlength: $.validator.format("Please enter no more than {0} characters."),
+ minlength: $.validator.format("Please enter at least {0} characters."),
+ rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
+ range: $.validator.format("Please enter a value between {0} and {1}."),
+ max: $.validator.format("Please enter a value less than or equal to {0}."),
+ min: $.validator.format("Please enter a value greater than or equal to {0}.")
+ },
+
+ autoCreateRanges: false,
+
+ prototype: {
+
+ init: function() {
+ this.labelContainer = $(this.settings.errorLabelContainer);
+ this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
+ this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
+ this.submitted = {};
+ this.valueCache = {};
+ this.pendingRequest = 0;
+ this.pending = {};
+ this.invalid = {};
+ this.reset();
+
+ var groups = (this.groups = {});
+ $.each(this.settings.groups, function( key, value ) {
+ if ( typeof value === "string" ) {
+ value = value.split(/\s/);
+ }
+ $.each(value, function( index, name ) {
+ groups[name] = key;
+ });
+ });
+ var rules = this.settings.rules;
+ $.each(rules, function( key, value ) {
+ rules[key] = $.validator.normalizeRule(value);
+ });
+
+ function delegate(event) {
+ var validator = $.data(this[0].form, "validator"),
+ eventType = "on" + event.type.replace(/^validate/, "");
+ if ( validator.settings[eventType] ) {
+ validator.settings[eventType].call(validator, this[0], event);
+ }
+ }
+ $(this.currentForm)
+ .validateDelegate(":text, [type='password'], [type='file'], select, textarea, " +
+ "[type='number'], [type='search'] ,[type='tel'], [type='url'], " +
+ "[type='email'], [type='datetime'], [type='date'], [type='month'], " +
+ "[type='week'], [type='time'], [type='datetime-local'], " +
+ "[type='range'], [type='color'] ",
+ "focusin focusout keyup", delegate)
+ .validateDelegate("[type='radio'], [type='checkbox'], select, option", "click", delegate);
+
+ if ( this.settings.invalidHandler ) {
+ $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
+ }
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/form
+ form: function() {
+ this.checkForm();
+ $.extend(this.submitted, this.errorMap);
+ this.invalid = $.extend({}, this.errorMap);
+ if ( !this.valid() ) {
+ $(this.currentForm).triggerHandler("invalid-form", [this]);
+ }
+ this.showErrors();
+ return this.valid();
+ },
+
+ checkForm: function() {
+ this.prepareForm();
+ for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
+ this.check( elements[i] );
+ }
+ return this.valid();
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/element
+ element: function( element ) {
+ element = this.validationTargetFor( this.clean( element ) );
+ this.lastElement = element;
+ this.prepareElement( element );
+ this.currentElements = $(element);
+ var result = this.check( element ) !== false;
+ if ( result ) {
+ delete this.invalid[element.name];
+ } else {
+ this.invalid[element.name] = true;
+ }
+ if ( !this.numberOfInvalids() ) {
+ // Hide error containers on last error
+ this.toHide = this.toHide.add( this.containers );
+ }
+ this.showErrors();
+ return result;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/showErrors
+ showErrors: function( errors ) {
+ if ( errors ) {
+ // add items to error list and map
+ $.extend( this.errorMap, errors );
+ this.errorList = [];
+ for ( var name in errors ) {
+ this.errorList.push({
+ message: errors[name],
+ element: this.findByName(name)[0]
+ });
+ }
+ // remove items from success list
+ this.successList = $.grep( this.successList, function( element ) {
+ return !(element.name in errors);
+ });
+ }
+ if ( this.settings.showErrors ) {
+ this.settings.showErrors.call( this, this.errorMap, this.errorList );
+ } else {
+ this.defaultShowErrors();
+ }
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/resetForm
+ resetForm: function() {
+ if ( $.fn.resetForm ) {
+ $(this.currentForm).resetForm();
+ }
+ this.submitted = {};
+ this.lastElement = null;
+ this.prepareForm();
+ this.hideErrors();
+ this.elements().removeClass( this.settings.errorClass ).removeData( "previousValue" );
+ },
+
+ numberOfInvalids: function() {
+ return this.objectLength(this.invalid);
+ },
+
+ objectLength: function( obj ) {
+ var count = 0;
+ for ( var i in obj ) {
+ count++;
+ }
+ return count;
+ },
+
+ hideErrors: function() {
+ this.addWrapper( this.toHide ).hide();
+ },
+
+ valid: function() {
+ return this.size() === 0;
+ },
+
+ size: function() {
+ return this.errorList.length;
+ },
+
+ focusInvalid: function() {
+ if ( this.settings.focusInvalid ) {
+ try {
+ $(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
+ .filter(":visible")
+ .focus()
+ // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
+ .trigger("focusin");
+ } catch(e) {
+ // ignore IE throwing errors when focusing hidden elements
+ }
+ }
+ },
+
+ findLastActive: function() {
+ var lastActive = this.lastActive;
+ return lastActive && $.grep(this.errorList, function( n ) {
+ return n.element.name === lastActive.name;
+ }).length === 1 && lastActive;
+ },
+
+ elements: function() {
+ var validator = this,
+ rulesCache = {};
+
+ // select all valid inputs inside the form (no submit or reset buttons)
+ return $(this.currentForm)
+ .find("input, select, textarea")
+ .not(":submit, :reset, :image, [disabled]")
+ .not( this.settings.ignore )
+ .filter(function() {
+ if ( !this.name && validator.settings.debug && window.console ) {
+ console.error( "%o has no name assigned", this);
+ }
+
+ // select only the first element for each name, and only those with rules specified
+ if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) {
+ return false;
+ }
+
+ rulesCache[this.name] = true;
+ return true;
+ });
+ },
+
+ clean: function( selector ) {
+ return $(selector)[0];
+ },
+
+ errors: function() {
+ var errorClass = this.settings.errorClass.replace(" ", ".");
+ return $(this.settings.errorElement + "." + errorClass, this.errorContext);
+ },
+
+ reset: function() {
+ this.successList = [];
+ this.errorList = [];
+ this.errorMap = {};
+ this.toShow = $([]);
+ this.toHide = $([]);
+ this.currentElements = $([]);
+ },
+
+ prepareForm: function() {
+ this.reset();
+ this.toHide = this.errors().add( this.containers );
+ },
+
+ prepareElement: function( element ) {
+ this.reset();
+ this.toHide = this.errorsFor(element);
+ },
+
+ elementValue: function( element ) {
+ var type = $(element).attr("type"),
+ val = $(element).val();
+
+ if ( type === "radio" || type === "checkbox" ) {
+ return $("input[name='" + $(element).attr("name") + "']:checked").val();
+ }
+
+ if ( typeof val === "string" ) {
+ return val.replace(/\r/g, "");
+ }
+ return val;
+ },
+
+ check: function( element ) {
+ element = this.validationTargetFor( this.clean( element ) );
+
+ var rules = $(element).rules();
+ var dependencyMismatch = false;
+ var val = this.elementValue(element);
+ var result;
+
+ for (var method in rules ) {
+ var rule = { method: method, parameters: rules[method] };
+ try {
+
+ result = $.validator.methods[method].call( this, val, element, rule.parameters );
+
+ // if a method indicates that the field is optional and therefore valid,
+ // don't mark it as valid when there are no other rules
+ if ( result === "dependency-mismatch" ) {
+ dependencyMismatch = true;
+ continue;
+ }
+ dependencyMismatch = false;
+
+ if ( result === "pending" ) {
+ this.toHide = this.toHide.not( this.errorsFor(element) );
+ return;
+ }
+
+ if ( !result ) {
+ this.formatAndAdd( element, rule );
+ return false;
+ }
+ } catch(e) {
+ if ( this.settings.debug && window.console ) {
+ console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e );
+ }
+ throw e;
+ }
+ }
+ if ( dependencyMismatch ) {
+ return;
+ }
+ if ( this.objectLength(rules) ) {
+ this.successList.push(element);
+ }
+ return true;
+ },
+
+ // return the custom message for the given element and validation method
+ // specified in the element's HTML5 data attribute
+ customDataMessage: function( element, method ) {
+ return $(element).data("msg-" + method.toLowerCase()) || (element.attributes && $(element).attr("data-msg-" + method.toLowerCase()));
+ },
+
+ // return the custom message for the given element name and validation method
+ customMessage: function( name, method ) {
+ var m = this.settings.messages[name];
+ return m && (m.constructor === String ? m : m[method]);
+ },
+
+ // return the first defined argument, allowing empty strings
+ findDefined: function() {
+ for(var i = 0; i < arguments.length; i++) {
+ if ( arguments[i] !== undefined ) {
+ return arguments[i];
+ }
+ }
+ return undefined;
+ },
+
+ defaultMessage: function( element, method ) {
+ return this.findDefined(
+ this.customMessage( element.name, method ),
+ this.customDataMessage( element, method ),
+ // title is never undefined, so handle empty string as undefined
+ !this.settings.ignoreTitle && element.title || undefined,
+ $.validator.messages[method],
+ "<strong>Warning: No message defined for " + element.name + "</strong>"
+ );
+ },
+
+ formatAndAdd: function( element, rule ) {
+ var message = this.defaultMessage( element, rule.method ),
+ theregex = /\$?\{(\d+)\}/g;
+ if ( typeof message === "function" ) {
+ message = message.call(this, rule.parameters, element);
+ } else if (theregex.test(message)) {
+ message = $.validator.format(message.replace(theregex, "{$1}"), rule.parameters);
+ }
+ this.errorList.push({
+ message: message,
+ element: element
+ });
+
+ this.errorMap[element.name] = message;
+ this.submitted[element.name] = message;
+ },
+
+ addWrapper: function( toToggle ) {
+ if ( this.settings.wrapper ) {
+ toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
+ }
+ return toToggle;
+ },
+
+ defaultShowErrors: function() {
+ var i, elements;
+ for ( i = 0; this.errorList[i]; i++ ) {
+ var error = this.errorList[i];
+ if ( this.settings.highlight ) {
+ this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
+ }
+ this.showLabel( error.element, error.message );
+ }
+ if ( this.errorList.length ) {
+ this.toShow = this.toShow.add( this.containers );
+ }
+ if ( this.settings.success ) {
+ for ( i = 0; this.successList[i]; i++ ) {
+ this.showLabel( this.successList[i] );
+ }
+ }
+ if ( this.settings.unhighlight ) {
+ for ( i = 0, elements = this.validElements(); elements[i]; i++ ) {
+ this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
+ }
+ }
+ this.toHide = this.toHide.not( this.toShow );
+ this.hideErrors();
+ this.addWrapper( this.toShow ).show();
+ },
+
+ validElements: function() {
+ return this.currentElements.not(this.invalidElements());
+ },
+
+ invalidElements: function() {
+ return $(this.errorList).map(function() {
+ return this.element;
+ });
+ },
+
+ showLabel: function( element, message ) {
+ var label = this.errorsFor( element );
+ if ( label.length ) {
+ // refresh error/success class
+ label.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );
+ // replace message on existing label
+ label.html(message);
+ } else {
+ // create label
+ label = $("<" + this.settings.errorElement + ">")
+ .attr("for", this.idOrName(element))
+ .addClass(this.settings.errorClass)
+ .html(message || "");
+ if ( this.settings.wrapper ) {
+ // make sure the element is visible, even in IE
+ // actually showing the wrapped element is handled elsewhere
+ label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
+ }
+ if ( !this.labelContainer.append(label).length ) {
+ if ( this.settings.errorPlacement ) {
+ this.settings.errorPlacement(label, $(element) );
+ } else {
+ label.insertAfter(element);
+ }
+ }
+ }
+ if ( !message && this.settings.success ) {
+ label.text("");
+ if ( typeof this.settings.success === "string" ) {
+ label.addClass( this.settings.success );
+ } else {
+ this.settings.success( label, element );
+ }
+ }
+ this.toShow = this.toShow.add(label);
+ },
+
+ errorsFor: function( element ) {
+ var name = this.idOrName(element);
+ return this.errors().filter(function() {
+ return $(this).attr("for") === name;
+ });
+ },
+
+ idOrName: function( element ) {
+ return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
+ },
+
+ validationTargetFor: function( element ) {
+ // if radio/checkbox, validate first element in group instead
+ if ( this.checkable(element) ) {
+ element = this.findByName( element.name ).not(this.settings.ignore)[0];
+ }
+ return element;
+ },
+
+ checkable: function( element ) {
+ return (/radio|checkbox/i).test(element.type);
+ },
+
+ findByName: function( name ) {
+ return $(this.currentForm).find("[name='" + name + "']");
+ },
+
+ getLength: function( value, element ) {
+ switch( element.nodeName.toLowerCase() ) {
+ case "select":
+ return $("option:selected", element).length;
+ case "input":
+ if ( this.checkable( element) ) {
+ return this.findByName(element.name).filter(":checked").length;
+ }
+ }
+ return value.length;
+ },
+
+ depend: function( param, element ) {
+ return this.dependTypes[typeof param] ? this.dependTypes[typeof param](param, element) : true;
+ },
+
+ dependTypes: {
+ "boolean": function( param, element ) {
+ return param;
+ },
+ "string": function( param, element ) {
+ return !!$(param, element.form).length;
+ },
+ "function": function( param, element ) {
+ return param(element);
+ }
+ },
+
+ optional: function( element ) {
+ var val = this.elementValue(element);
+ return !$.validator.methods.required.call(this, val, element) && "dependency-mismatch";
+ },
+
+ startRequest: function( element ) {
+ if ( !this.pending[element.name] ) {
+ this.pendingRequest++;
+ this.pending[element.name] = true;
+ }
+ },
+
+ stopRequest: function( element, valid ) {
+ this.pendingRequest--;
+ // sometimes synchronization fails, make sure pendingRequest is never < 0
+ if ( this.pendingRequest < 0 ) {
+ this.pendingRequest = 0;
+ }
+ delete this.pending[element.name];
+ if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {
+ $(this.currentForm).submit();
+ this.formSubmitted = false;
+ } else if (!valid && this.pendingRequest === 0 && this.formSubmitted) {
+ $(this.currentForm).triggerHandler("invalid-form", [this]);
+ this.formSubmitted = false;
+ }
+ },
+
+ previousValue: function( element ) {
+ return $.data(element, "previousValue") || $.data(element, "previousValue", {
+ old: null,
+ valid: true,
+ message: this.defaultMessage( element, "remote" )
+ });
+ }
+
+ },
+
+ classRuleSettings: {
+ required: {required: true},
+ email: {email: true},
+ url: {url: true},
+ date: {date: true},
+ dateISO: {dateISO: true},
+ number: {number: true},
+ digits: {digits: true},
+ creditcard: {creditcard: true}
+ },
+
+ addClassRules: function( className, rules ) {
+ if ( className.constructor === String ) {
+ this.classRuleSettings[className] = rules;
+ } else {
+ $.extend(this.classRuleSettings, className);
+ }
+ },
+
+ removeClassRules: function( className, rules) {
+ this.classRuleSettings[className] = null;
+ },
+
+ classRules: function( element ) {
+ var rules = {};
+ var classes = $(element).attr("class");
+ if ( classes ) {
+ $.each(classes.split(" "), function() {
+ if ( this in $.validator.classRuleSettings ) {
+ $.extend(rules, $.validator.classRuleSettings[this]);
+ }
+ });
+ }
+ return rules;
+ },
+
+ attributeRules: function( element ) {
+ var rules = {};
+ var $element = $(element);
+ var type = $element[0].getAttribute("type");
+
+ for (var method in $.validator.methods) {
+ var value;
+
+ // support for <input required> in both html5 and older browsers
+ if ( method === "required" ) {
+ value = $element.get(0).getAttribute(method);
+ // Some browsers return an empty string for the required attribute
+ // and non-HTML5 browsers might have required="" markup
+ if ( value === "" || value === "-1") {
+ value = true;
+ }
+ // force non-HTML5 browsers to return bool
+ value = !!value;
+ } else {
+ value = $element.attr(method);
+ }
+
+ // convert the value to a number for number inputs, and for text for backwards compability
+ // allows type="date" and others to be compared as strings
+ if ( /min|max/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {
+ value = Number(value);
+ }
+
+ if ( value ) {
+ rules[method] = value;
+ } else if ( type === method && type !== 'range' ) {
+ // exception: the jquery validate 'range' method
+ // does not test for the html5 'range' type
+ rules[method] = true;
+ }
+ }
+
+ // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
+ if ( rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength) ) {
+ delete rules.maxlength;
+ }
+
+ return rules;
+ },
+
+ dataRules: function( element ) {
+ var method, value,
+ rules = {}, $element = $(element);
+ for (method in $.validator.methods) {
+ value = $element.data("rule-" + method.toLowerCase());
+ if ( value !== undefined ) {
+ rules[method] = value;
+ }
+ }
+ return rules;
+ },
+
+ staticRules: function( element ) {
+ var rules = {};
+ var validator = $.data(element.form, "validator");
+ if ( validator.settings.rules ) {
+ rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
+ }
+ return rules;
+ },
+
+ normalizeRules: function( rules, element ) {
+ // handle dependency check
+ $.each(rules, function( prop, val ) {
+ // ignore rule when param is explicitly false, eg. required:false
+ if ( val === false ) {
+ delete rules[prop];
+ return;
+ }
+ if ( val.param || val.depends ) {
+ var keepRule = true;
+ switch (typeof val.depends) {
+ case "string":
+ keepRule = !!$(val.depends, element.form).length;
+ break;
+ case "function":
+ keepRule = val.depends.call(element, element);
+ break;
+ }
+ if ( keepRule ) {
+ rules[prop] = val.param !== undefined ? val.param : true;
+ } else {
+ delete rules[prop];
+ }
+ }
+ });
+
+ // evaluate parameters
+ $.each(rules, function( rule, parameter ) {
+ rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
+ });
+
+ // clean number parameters
+ $.each(['minlength', 'maxlength'], function() {
+ if ( rules[this] ) {
+ rules[this] = Number(rules[this]);
+ }
+ });
+ $.each(['rangelength', 'range'], function() {
+ var parts;
+ if ( rules[this] ) {
+ if ( $.isArray(rules[this]) ) {
+ rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
+ } else if ( typeof rules[this] === "string" ) {
+ parts = rules[this].split(/[\s,]+/);
+ rules[this] = [Number(parts[0]), Number(parts[1])];
+ }
+ }
+ });
+
+ if ( $.validator.autoCreateRanges ) {
+ // auto-create ranges
+ if ( rules.min && rules.max ) {
+ rules.range = [rules.min, rules.max];
+ delete rules.min;
+ delete rules.max;
+ }
+ if ( rules.minlength && rules.maxlength ) {
+ rules.rangelength = [rules.minlength, rules.maxlength];
+ delete rules.minlength;
+ delete rules.maxlength;
+ }
+ }
+
+ return rules;
+ },
+
+ // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
+ normalizeRule: function( data ) {
+ if ( typeof data === "string" ) {
+ var transformed = {};
+ $.each(data.split(/\s/), function() {
+ transformed[this] = true;
+ });
+ data = transformed;
+ }
+ return data;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/addMethod
+ addMethod: function( name, method, message ) {
+ $.validator.methods[name] = method;
+ $.validator.messages[name] = message !== undefined ? message : $.validator.messages[name];
+ if ( method.length < 3 ) {
+ $.validator.addClassRules(name, $.validator.normalizeRule(name));
+ }
+ },
+
+ methods: {
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/required
+ required: function( value, element, param ) {
+ // check if dependency is met
+ if ( !this.depend(param, element) ) {
+ return "dependency-mismatch";
+ }
+ if ( element.nodeName.toLowerCase() === "select" ) {
+ // could be an array for select-multiple or a string, both are fine this way
+ var val = $(element).val();
+ return val && val.length > 0;
+ }
+ if ( this.checkable(element) ) {
+ return this.getLength(value, element) > 0;
+ }
+ return $.trim(value).length > 0;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/email
+ email: function( value, element ) {
+ // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
+ return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/url
+ url: function( value, element ) {
+ // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
+ return this.optional(element) || /^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/date
+ date: function( value, element ) {
+ return this.optional(element) || !/Invalid|NaN/.test(new Date(value).toString());
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/dateISO
+ dateISO: function( value, element ) {
+ return this.optional(element) || /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/number
+ number: function( value, element ) {
+ return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/digits
+ digits: function( value, element ) {
+ return this.optional(element) || /^\d+$/.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/creditcard
+ // based on http://en.wikipedia.org/wiki/Luhn
+ creditcard: function( value, element ) {
+ if ( this.optional(element) ) {
+ return "dependency-mismatch";
+ }
+ // accept only spaces, digits and dashes
+ if ( /[^0-9 \-]+/.test(value) ) {
+ return false;
+ }
+ var nCheck = 0,
+ nDigit = 0,
+ bEven = false;
+
+ value = value.replace(/\D/g, "");
+
+ for (var n = value.length - 1; n >= 0; n--) {
+ var cDigit = value.charAt(n);
+ nDigit = parseInt(cDigit, 10);
+ if ( bEven ) {
+ if ( (nDigit *= 2) > 9 ) {
+ nDigit -= 9;
+ }
+ }
+ nCheck += nDigit;
+ bEven = !bEven;
+ }
+
+ return (nCheck % 10) === 0;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/minlength
+ minlength: function( value, element, param ) {
+ var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);
+ return this.optional(element) || length >= param;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/maxlength
+ maxlength: function( value, element, param ) {
+ var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);
+ return this.optional(element) || length <= param;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/rangelength
+ rangelength: function( value, element, param ) {
+ var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);
+ return this.optional(element) || ( length >= param[0] && length <= param[1] );
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/min
+ min: function( value, element, param ) {
+ return this.optional(element) || value >= param;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/max
+ max: function( value, element, param ) {
+ return this.optional(element) || value <= param;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/range
+ range: function( value, element, param ) {
+ return this.optional(element) || ( value >= param[0] && value <= param[1] );
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/equalTo
+ equalTo: function( value, element, param ) {
+ // bind to the blur event of the target in order to revalidate whenever the target field is updated
+ // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
+ var target = $(param);
+ if ( this.settings.onfocusout ) {
+ target.unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
+ $(element).valid();
+ });
+ }
+ return value === target.val();
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/remote
+ remote: function( value, element, param ) {
+ if ( this.optional(element) ) {
+ return "dependency-mismatch";
+ }
+
+ var previous = this.previousValue(element);
+ if (!this.settings.messages[element.name] ) {
+ this.settings.messages[element.name] = {};
+ }
+ previous.originalMessage = this.settings.messages[element.name].remote;
+ this.settings.messages[element.name].remote = previous.message;
+
+ param = typeof param === "string" && {url:param} || param;
+
+ if ( previous.old === value ) {
+ return previous.valid;
+ }
+
+ previous.old = value;
+ var validator = this;
+ this.startRequest(element);
+ var data = {};
+ data[element.name] = value;
+ $.ajax($.extend(true, {
+ url: param,
+ mode: "abort",
+ port: "validate" + element.name,
+ dataType: "json",
+ data: data,
+ success: function( response ) {
+ validator.settings.messages[element.name].remote = previous.originalMessage;
+ var valid = response === true || response === "true";
+ if ( valid ) {
+ var submitted = validator.formSubmitted;
+ validator.prepareElement(element);
+ validator.formSubmitted = submitted;
+ validator.successList.push(element);
+ delete validator.invalid[element.name];
+ validator.showErrors();
+ } else {
+ var errors = {};
+ var message = response || validator.defaultMessage( element, "remote" );
+ errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
+ validator.invalid[element.name] = true;
+ validator.showErrors(errors);
+ }
+ previous.valid = valid;
+ validator.stopRequest(element, valid);
+ }
+ }, param));
+ return "pending";
+ }
+
+ }
+
+});
+
+// deprecated, use $.validator.format instead
+$.format = $.validator.format;
+
+}(jQuery));
+
+// ajax mode: abort
+// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
+// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
+(function($) {
+ var pendingRequests = {};
+ // Use a prefilter if available (1.5+)
+ if ( $.ajaxPrefilter ) {
+ $.ajaxPrefilter(function( settings, _, xhr ) {
+ var port = settings.port;
+ if ( settings.mode === "abort" ) {
+ if ( pendingRequests[port] ) {
+ pendingRequests[port].abort();
+ }
+ pendingRequests[port] = xhr;
+ }
+ });
+ } else {
+ // Proxy ajax
+ var ajax = $.ajax;
+ $.ajax = function( settings ) {
+ var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
+ port = ( "port" in settings ? settings : $.ajaxSettings ).port;
+ if ( mode === "abort" ) {
+ if ( pendingRequests[port] ) {
+ pendingRequests[port].abort();
+ }
+ pendingRequests[port] = ajax.apply(this, arguments);
+ return pendingRequests[port];
+ }
+ return ajax.apply(this, arguments);
+ };
+ }
+}(jQuery));
+
+// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
+// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
+(function($) {
+ $.extend($.fn, {
+ validateDelegate: function( delegate, type, handler ) {
+ return this.bind(type, function( event ) {
+ var target = $(event.target);
+ if ( target.is(delegate) ) {
+ return handler.apply(target, arguments);
+ }
+ });
+ }
+ });
+}(jQuery));
diff --git a/views/js/jquery-validation-1.11.1/dist/jquery.validate.min.js b/views/js/jquery-validation-1.11.1/dist/jquery.validate.min.js
new file mode 100644
index 0000000..59ee8d5
--- /dev/null
+++ b/views/js/jquery-validation-1.11.1/dist/jquery.validate.min.js
@@ -0,0 +1,1237 @@
+/*!
+ * jQuery Validation Plugin 1.11.1
+ *
+ * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
+ * http://docs.jquery.com/Plugins/Validation
+ *
+ * Copyright 2013 Jörn Zaefferer
+ * Released under the MIT license:
+ * http://www.opensource.org/licenses/mit-license.php
+ */
+(function($) {
+
+$.extend($.fn, {
+ // http://docs.jquery.com/Plugins/Validation/validate
+ validate: function( options ) {
+
+ // if nothing is selected, return nothing; can't chain anyway
+ if ( !this.length ) {
+ if ( options && options.debug && window.console ) {
+ console.warn( "Nothing selected, can't validate, returning nothing." );
+ }
+ return;
+ }
+
+ // check if a validator for this form was already created
+ var validator = $.data( this[0], "validator" );
+ if ( validator ) {
+ return validator;
+ }
+
+ // Add novalidate tag if HTML5.
+ this.attr( "novalidate", "novalidate" );
+
+ validator = new $.validator( options, this[0] );
+ $.data( this[0], "validator", validator );
+
+ if ( validator.settings.onsubmit ) {
+
+ this.validateDelegate( ":submit", "click", function( event ) {
+ if ( validator.settings.submitHandler ) {
+ validator.submitButton = event.target;
+ }
+ // allow suppressing validation by adding a cancel class to the submit button
+ if ( $(event.target).hasClass("cancel") ) {
+ validator.cancelSubmit = true;
+ }
+
+ // allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
+ if ( $(event.target).attr("formnovalidate") !== undefined ) {
+ validator.cancelSubmit = true;
+ }
+ });
+
+ // validate the form on submit
+ this.submit( function( event ) {
+ if ( validator.settings.debug ) {
+ // prevent form submit to be able to see console output
+ event.preventDefault();
+ }
+ function handle() {
+ var hidden;
+ if ( validator.settings.submitHandler ) {
+ if ( validator.submitButton ) {
+ // insert a hidden input as a replacement for the missing submit button
+ hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val( $(validator.submitButton).val() ).appendTo(validator.currentForm);
+ }
+ validator.settings.submitHandler.call( validator, validator.currentForm, event );
+ if ( validator.submitButton ) {
+ // and clean up afterwards; thanks to no-block-scope, hidden can be referenced
+ hidden.remove();
+ }
+ return false;
+ }
+ return true;
+ }
+
+ // prevent submit for invalid forms or custom submit handlers
+ if ( validator.cancelSubmit ) {
+ validator.cancelSubmit = false;
+ return handle();
+ }
+ if ( validator.form() ) {
+ if ( validator.pendingRequest ) {
+ validator.formSubmitted = true;
+ return false;
+ }
+ return handle();
+ } else {
+ validator.focusInvalid();
+ return false;
+ }
+ });
+ }
+
+ return validator;
+ },
+ // http://docs.jquery.com/Plugins/Validation/valid
+ valid: function() {
+ if ( $(this[0]).is("form")) {
+ return this.validate().form();
+ } else {
+ var valid = true;
+ var validator = $(this[0].form).validate();
+ this.each(function() {
+ valid = valid && validator.element(this);
+ });
+ return valid;
+ }
+ },
+ // attributes: space seperated list of attributes to retrieve and remove
+ removeAttrs: function( attributes ) {
+ var result = {},
+ $element = this;
+ $.each(attributes.split(/\s/), function( index, value ) {
+ result[value] = $element.attr(value);
+ $element.removeAttr(value);
+ });
+ return result;
+ },
+ // http://docs.jquery.com/Plugins/Validation/rules
+ rules: function( command, argument ) {
+ var element = this[0];
+
+ if ( command ) {
+ var settings = $.data(element.form, "validator").settings;
+ var staticRules = settings.rules;
+ var existingRules = $.validator.staticRules(element);
+ switch(command) {
+ case "add":
+ $.extend(existingRules, $.validator.normalizeRule(argument));
+ // remove messages from rules, but allow them to be set separetely
+ delete existingRules.messages;
+ staticRules[element.name] = existingRules;
+ if ( argument.messages ) {
+ settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages );
+ }
+ break;
+ case "remove":
+ if ( !argument ) {
+ delete staticRules[element.name];
+ return existingRules;
+ }
+ var filtered = {};
+ $.each(argument.split(/\s/), function( index, method ) {
+ filtered[method] = existingRules[method];
+ delete existingRules[method];
+ });
+ return filtered;
+ }
+ }
+
+ var data = $.validator.normalizeRules(
+ $.extend(
+ {},
+ $.validator.classRules(element),
+ $.validator.attributeRules(element),
+ $.validator.dataRules(element),
+ $.validator.staticRules(element)
+ ), element);
+
+ // make sure required is at front
+ if ( data.required ) {
+ var param = data.required;
+ delete data.required;
+ data = $.extend({required: param}, data);
+ }
+
+ return data;
+ }
+});
+
+// Custom selectors
+$.extend($.expr[":"], {
+ // http://docs.jquery.com/Plugins/Validation/blank
+ blank: function( a ) { return !$.trim("" + $(a).val()); },
+ // http://docs.jquery.com/Plugins/Validation/filled
+ filled: function( a ) { return !!$.trim("" + $(a).val()); },
+ // http://docs.jquery.com/Plugins/Validation/unchecked
+ unchecked: function( a ) { return !$(a).prop("checked"); }
+});
+
+// constructor for validator
+$.validator = function( options, form ) {
+ this.settings = $.extend( true, {}, $.validator.defaults, options );
+ this.currentForm = form;
+ this.init();
+};
+
+$.validator.format = function( source, params ) {
+ if ( arguments.length === 1 ) {
+ return function() {
+ var args = $.makeArray(arguments);
+ args.unshift(source);
+ return $.validator.format.apply( this, args );
+ };
+ }
+ if ( arguments.length > 2 && params.constructor !== Array ) {
+ params = $.makeArray(arguments).slice(1);
+ }
+ if ( params.constructor !== Array ) {
+ params = [ params ];
+ }
+ $.each(params, function( i, n ) {
+ source = source.replace( new RegExp("\\{" + i + "\\}", "g"), function() {
+ return n;
+ });
+ });
+ return source;
+};
+
+$.extend($.validator, {
+
+ defaults: {
+ messages: {},
+ groups: {},
+ rules: {},
+ errorClass: "error",
+ validClass: "valid",
+ errorElement: "label",
+ focusInvalid: true,
+ errorContainer: $([]),
+ errorLabelContainer: $([]),
+ onsubmit: true,
+ ignore: ":hidden",
+ ignoreTitle: false,
+ onfocusin: function( element, event ) {
+ this.lastActive = element;
+
+ // hide error label and remove error class on focus if enabled
+ if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
+ if ( this.settings.unhighlight ) {
+ this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
+ }
+ this.addWrapper(this.errorsFor(element)).hide();
+ }
+ },
+ onfocusout: function( element, event ) {
+ if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
+ this.element(element);
+ }
+ },
+ onkeyup: function( element, event ) {
+ if ( event.which === 9 && this.elementValue(element) === "" ) {
+ return;
+ } else if ( element.name in this.submitted || element === this.lastElement ) {
+ this.element(element);
+ }
+ },
+ onclick: function( element, event ) {
+ // click on selects, radiobuttons and checkboxes
+ if ( element.name in this.submitted ) {
+ this.element(element);
+ }
+ // or option elements, check parent select in that case
+ else if ( element.parentNode.name in this.submitted ) {
+ this.element(element.parentNode);
+ }
+ },
+ highlight: function( element, errorClass, validClass ) {
+ if ( element.type === "radio" ) {
+ this.findByName(element.name).addClass(errorClass).removeClass(validClass);
+ } else {
+ $(element).addClass(errorClass).removeClass(validClass);
+ }
+ },
+ unhighlight: function( element, errorClass, validClass ) {
+ if ( element.type === "radio" ) {
+ this.findByName(element.name).removeClass(errorClass).addClass(validClass);
+ } else {
+ $(element).removeClass(errorClass).addClass(validClass);
+ }
+ }
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
+ setDefaults: function( settings ) {
+ $.extend( $.validator.defaults, settings );
+ },
+
+ messages: {
+ required: wpsg_trans_v2.required,
+ remote: wpsg_trans_v2.remote,
+ email: wpsg_trans_v2.email,
+ url: wpsg_trans_v2.url,
+ date: wpsg_trans_v2.date,
+ dateISO: wpsg_trans_v2.dateISO,
+ number: wpsg_trans_v2.number,
+ digits: wpsg_trans_v2.digits,
+ creditcard: wpsg_trans_v2.creditcard,
+ equalTo: wpsg_trans_v2.equalTo,
+ maxlength: $.validator.format(wpsg_trans_v2.maxlength),
+ minlength: $.validator.format(wpsg_trans_v2.minlength),
+ rangelength: $.validator.format(wpsg_trans_v2.rangelength),
+ range: $.validator.format(wpsg_trans_v2.range),
+ max: $.validator.format(wpsg_trans_v2.max),
+ min: $.validator.format(wpsg_trans_v2.min)
+ },
+
+ autoCreateRanges: false,
+
+ prototype: {
+
+ init: function() {
+ this.labelContainer = $(this.settings.errorLabelContainer);
+ this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
+ this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
+ this.submitted = {};
+ this.valueCache = {};
+ this.pendingRequest = 0;
+ this.pending = {};
+ this.invalid = {};
+ this.reset();
+
+ var groups = (this.groups = {});
+ $.each(this.settings.groups, function( key, value ) {
+ if ( typeof value === "string" ) {
+ value = value.split(/\s/);
+ }
+ $.each(value, function( index, name ) {
+ groups[name] = key;
+ });
+ });
+ var rules = this.settings.rules;
+ $.each(rules, function( key, value ) {
+ rules[key] = $.validator.normalizeRule(value);
+ });
+
+ function delegate(event) {
+ var validator = $.data(this[0].form, "validator"),
+ eventType = "on" + event.type.replace(/^validate/, "");
+ if ( validator.settings[eventType] ) {
+ validator.settings[eventType].call(validator, this[0], event);
+ }
+ }
+ $(this.currentForm)
+ .validateDelegate(":text, [type='password'], [type='file'], select, textarea, " +
+ "[type='number'], [type='search'] ,[type='tel'], [type='url'], " +
+ "[type='email'], [type='datetime'], [type='date'], [type='month'], " +
+ "[type='week'], [type='time'], [type='datetime-local'], " +
+ "[type='range'], [type='color'] ",
+ "focusin focusout keyup", delegate)
+ .validateDelegate("[type='radio'], [type='checkbox'], select, option", "click", delegate);
+
+ if ( this.settings.invalidHandler ) {
+ $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
+ }
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/form
+ form: function() {
+ this.checkForm();
+ $.extend(this.submitted, this.errorMap);
+ this.invalid = $.extend({}, this.errorMap);
+ if ( !this.valid() ) {
+ $(this.currentForm).triggerHandler("invalid-form", [this]);
+ }
+ this.showErrors();
+ return this.valid();
+ },
+
+ checkForm: function() {
+ this.prepareForm();
+ for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
+ this.check( elements[i] );
+ }
+ return this.valid();
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/element
+ element: function( element ) {
+ element = this.validationTargetFor( this.clean( element ) );
+ this.lastElement = element;
+ this.prepareElement( element );
+ this.currentElements = $(element);
+ var result = this.check( element ) !== false;
+ if ( result ) {
+ delete this.invalid[element.name];
+ } else {
+ this.invalid[element.name] = true;
+ }
+ if ( !this.numberOfInvalids() ) {
+ // Hide error containers on last error
+ this.toHide = this.toHide.add( this.containers );
+ }
+ this.showErrors();
+ return result;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/showErrors
+ showErrors: function( errors ) {
+ if ( errors ) {
+ // add items to error list and map
+ $.extend( this.errorMap, errors );
+ this.errorList = [];
+ for ( var name in errors ) {
+ this.errorList.push({
+ message: errors[name],
+ element: this.findByName(name)[0]
+ });
+ }
+ // remove items from success list
+ this.successList = $.grep( this.successList, function( element ) {
+ return !(element.name in errors);
+ });
+ }
+ if ( this.settings.showErrors ) {
+ this.settings.showErrors.call( this, this.errorMap, this.errorList );
+ } else {
+ this.defaultShowErrors();
+ }
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/resetForm
+ resetForm: function() {
+ if ( $.fn.resetForm ) {
+ $(this.currentForm).resetForm();
+ }
+ this.submitted = {};
+ this.lastElement = null;
+ this.prepareForm();
+ this.hideErrors();
+ this.elements().removeClass( this.settings.errorClass ).removeData( "previousValue" );
+ },
+
+ numberOfInvalids: function() {
+ return this.objectLength(this.invalid);
+ },
+
+ objectLength: function( obj ) {
+ var count = 0;
+ for ( var i in obj ) {
+ count++;
+ }
+ return count;
+ },
+
+ hideErrors: function() {
+ this.addWrapper( this.toHide ).hide();
+ },
+
+ valid: function() {
+ return this.size() === 0;
+ },
+
+ size: function() {
+ return this.errorList.length;
+ },
+
+ focusInvalid: function() {
+ if ( this.settings.focusInvalid ) {
+ try {
+ $(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
+ .filter(":visible")
+ .focus()
+ // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
+ .trigger("focusin");
+ } catch(e) {
+ // ignore IE throwing errors when focusing hidden elements
+ }
+ }
+ },
+
+ findLastActive: function() {
+ var lastActive = this.lastActive;
+ return lastActive && $.grep(this.errorList, function( n ) {
+ return n.element.name === lastActive.name;
+ }).length === 1 && lastActive;
+ },
+
+ elements: function() {
+ var validator = this,
+ rulesCache = {};
+
+ // select all valid inputs inside the form (no submit or reset buttons)
+ return $(this.currentForm)
+ .find("input, select, textarea")
+ .not(":submit, :reset, :image, [disabled]")
+
+ .filter(function() {
+ if ( !this.name && validator.settings.debug && window.console ) {
+ console.error( "%o has no name assigned", this);
+ }
+
+ // select only the first element for each name, and only those with rules specified
+ if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) {
+ return false;
+ }
+
+ rulesCache[this.name] = true;
+ return true;
+ });
+ },
+
+ clean: function( selector ) {
+ return $(selector)[0];
+ },
+
+ errors: function() {
+ var errorClass = this.settings.errorClass.replace(" ", ".");
+ return $(this.settings.errorElement + "." + errorClass, this.errorContext);
+ },
+
+ reset: function() {
+ this.successList = [];
+ this.errorList = [];
+ this.errorMap = {};
+ this.toShow = $([]);
+ this.toHide = $([]);
+ this.currentElements = $([]);
+ },
+
+ prepareForm: function() {
+ this.reset();
+ this.toHide = this.errors().add( this.containers );
+ },
+
+ prepareElement: function( element ) {
+ this.reset();
+ this.toHide = this.errorsFor(element);
+ },
+
+ elementValue: function( element ) {
+ var type = $(element).attr("type"),
+ val = $(element).val();
+
+ if ( type === "radio" || type === "checkbox" ) {
+ return $("input[name='" + $(element).attr("name") + "']:checked").val();
+ }
+
+ if ( typeof val === "string" ) {
+ return val.replace(/\r/g, "");
+ }
+ return val;
+ },
+
+ check: function( element ) {
+ element = this.validationTargetFor( this.clean( element ) );
+
+ var rules = $(element).rules();
+ var dependencyMismatch = false;
+ var val = this.elementValue(element);
+ var result;
+
+ for (var method in rules ) {
+ var rule = { method: method, parameters: rules[method] };
+ try {
+
+ result = $.validator.methods[method].call( this, val, element, rule.parameters );
+
+ // if a method indicates that the field is optional and therefore valid,
+ // don't mark it as valid when there are no other rules
+ if ( result === "dependency-mismatch" ) {
+ dependencyMismatch = true;
+ continue;
+ }
+ dependencyMismatch = false;
+
+ if ( result === "pending" ) {
+ this.toHide = this.toHide.not( this.errorsFor(element) );
+ return;
+ }
+
+ if ( !result ) {
+ this.formatAndAdd( element, rule );
+ return false;
+ }
+ } catch(e) {
+ if ( this.settings.debug && window.console ) {
+ console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e );
+ }
+ throw e;
+ }
+ }
+ if ( dependencyMismatch ) {
+ return;
+ }
+ if ( this.objectLength(rules) ) {
+ this.successList.push(element);
+ }
+ return true;
+ },
+
+ // return the custom message for the given element and validation method
+ // specified in the element's HTML5 data attribute
+ customDataMessage: function( element, method ) {
+ return $(element).data("msg-" + method.toLowerCase()) || (element.attributes && $(element).attr("data-msg-" + method.toLowerCase()));
+ },
+
+ // return the custom message for the given element name and validation method
+ customMessage: function( name, method ) {
+ var m = this.settings.messages[name];
+ return m && (m.constructor === String ? m : m[method]);
+ },
+
+ // return the first defined argument, allowing empty strings
+ findDefined: function() {
+ for(var i = 0; i < arguments.length; i++) {
+ if ( arguments[i] !== undefined ) {
+ return arguments[i];
+ }
+ }
+ return undefined;
+ },
+
+ defaultMessage: function( element, method ) {
+ return this.findDefined(
+ this.customMessage( element.name, method ),
+ this.customDataMessage( element, method ),
+ // title is never undefined, so handle empty string as undefined
+ !this.settings.ignoreTitle && element.title || undefined,
+ $.validator.messages[method],
+ "<strong>Warning: No message defined for " + element.name + "</strong>"
+ );
+ },
+
+ formatAndAdd: function( element, rule ) {
+ var message = this.defaultMessage( element, rule.method ),
+ theregex = /\$?\{(\d+)\}/g;
+ if ( typeof message === "function" ) {
+ message = message.call(this, rule.parameters, element);
+ } else if (theregex.test(message)) {
+ message = $.validator.format(message.replace(theregex, "{$1}"), rule.parameters);
+ }
+ this.errorList.push({
+ message: message,
+ element: element
+ });
+
+ this.errorMap[element.name] = message;
+ this.submitted[element.name] = message;
+ },
+
+ addWrapper: function( toToggle ) {
+ if ( this.settings.wrapper ) {
+ toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
+ }
+ return toToggle;
+ },
+
+ defaultShowErrors: function() {
+ var i, elements;
+ for ( i = 0; this.errorList[i]; i++ ) {
+ var error = this.errorList[i];
+ if ( this.settings.highlight ) {
+ this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
+ }
+ this.showLabel( error.element, error.message );
+ }
+ if ( this.errorList.length ) {
+ this.toShow = this.toShow.add( this.containers );
+ }
+ if ( this.settings.success ) {
+ for ( i = 0; this.successList[i]; i++ ) {
+ this.showLabel( this.successList[i] );
+ }
+ }
+ if ( this.settings.unhighlight ) {
+ for ( i = 0, elements = this.validElements(); elements[i]; i++ ) {
+ this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
+ }
+ }
+ this.toHide = this.toHide.not( this.toShow );
+ this.hideErrors();
+ this.addWrapper( this.toShow ).show();
+ },
+
+ validElements: function() {
+ return this.currentElements.not(this.invalidElements());
+ },
+
+ invalidElements: function() {
+ return $(this.errorList).map(function() {
+ return this.element;
+ });
+ },
+
+ showLabel: function( element, message ) {
+ var label = this.errorsFor( element );
+ if ( label.length ) {
+ // refresh error/success class
+ label.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );
+ // replace message on existing label
+ label.html(message);
+ } else {
+ // create label
+ label = $("<" + this.settings.errorElement + ">")
+ .attr("for", this.idOrName(element))
+ .addClass(this.settings.errorClass)
+ .html(message || "");
+ if ( this.settings.wrapper ) {
+ // make sure the element is visible, even in IE
+ // actually showing the wrapped element is handled elsewhere
+ label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
+ }
+ if ( !this.labelContainer.append(label).length ) {
+ if ( this.settings.errorPlacement ) {
+ this.settings.errorPlacement(label, $(element) );
+ } else {
+ label.insertAfter(element);
+ }
+ }
+ }
+ if ( !message && this.settings.success ) {
+ label.text("");
+ if ( typeof this.settings.success === "string" ) {
+ label.addClass( this.settings.success );
+ } else {
+ this.settings.success( label, element );
+ }
+ }
+ this.toShow = this.toShow.add(label);
+ },
+
+ errorsFor: function( element ) {
+ var name = this.idOrName(element);
+ return this.errors().filter(function() {
+ return $(this).attr("for") === name;
+ });
+ },
+
+ idOrName: function( element ) {
+ return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
+ },
+
+ validationTargetFor: function( element ) {
+ // if radio/checkbox, validate first element in group instead
+ if ( this.checkable(element) ) {
+ element = this.findByName( element.name ).not(this.settings.ignore)[0];
+ }
+ return element;
+ },
+
+ checkable: function( element ) {
+ return (/radio|checkbox/i).test(element.type);
+ },
+
+ findByName: function( name ) {
+ return $(this.currentForm).find("[name='" + name + "']");
+ },
+
+ getLength: function( value, element ) {
+ switch( element.nodeName.toLowerCase() ) {
+ case "select":
+ return $("option:selected", element).length;
+ case "input":
+ if ( this.checkable( element) ) {
+ return this.findByName(element.name).filter(":checked").length;
+ }
+ }
+ return value.length;
+ },
+
+ depend: function( param, element ) {
+ return this.dependTypes[typeof param] ? this.dependTypes[typeof param](param, element) : true;
+ },
+
+ dependTypes: {
+ "boolean": function( param, element ) {
+ return param;
+ },
+ "string": function( param, element ) {
+ return !!$(param, element.form).length;
+ },
+ "function": function( param, element ) {
+ return param(element);
+ }
+ },
+
+ optional: function( element ) {
+ var val = this.elementValue(element);
+ return !$.validator.methods.required.call(this, val, element) && "dependency-mismatch";
+ },
+
+ startRequest: function( element ) {
+ if ( !this.pending[element.name] ) {
+ this.pendingRequest++;
+ this.pending[element.name] = true;
+ }
+ },
+
+ stopRequest: function( element, valid ) {
+ this.pendingRequest--;
+ // sometimes synchronization fails, make sure pendingRequest is never < 0
+ if ( this.pendingRequest < 0 ) {
+ this.pendingRequest = 0;
+ }
+ delete this.pending[element.name];
+ if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {
+ $(this.currentForm).submit();
+ this.formSubmitted = false;
+ } else if (!valid && this.pendingRequest === 0 && this.formSubmitted) {
+ $(this.currentForm).triggerHandler("invalid-form", [this]);
+ this.formSubmitted = false;
+ }
+ },
+
+ previousValue: function( element ) {
+ return $.data(element, "previousValue") || $.data(element, "previousValue", {
+ old: null,
+ valid: true,
+ message: this.defaultMessage( element, "remote" )
+ });
+ }
+
+ },
+
+ classRuleSettings: {
+ required: {required: true},
+ email: {email: true},
+ url: {url: true},
+ date: {date: true},
+ dateISO: {dateISO: true},
+ number: {number: true},
+ digits: {digits: true},
+ creditcard: {creditcard: true}
+ },
+
+ addClassRules: function( className, rules ) {
+ if ( className.constructor === String ) {
+ this.classRuleSettings[className] = rules;
+ } else {
+ $.extend(this.classRuleSettings, className);
+ }
+ },
+
+ removeClassRules: function( className, rules) {
+ this.classRuleSettings[className] = null;
+ },
+
+ classRules: function( element ) {
+ var rules = {};
+ var classes = $(element).attr("class");
+ if ( classes ) {
+ $.each(classes.split(" "), function() {
+ if ( this in $.validator.classRuleSettings ) {
+ $.extend(rules, $.validator.classRuleSettings[this]);
+ }
+ });
+ }
+ return rules;
+ },
+
+ attributeRules: function( element ) {
+ var rules = {};
+ var $element = $(element);
+ var type = $element[0].getAttribute("type");
+
+ for (var method in $.validator.methods) {
+ var value;
+
+ // support for <input required> in both html5 and older browsers
+ if ( method === "required" ) {
+ value = $element.get(0).getAttribute(method);
+ // Some browsers return an empty string for the required attribute
+ // and non-HTML5 browsers might have required="" markup
+ if ( value === "" || value === "-1") {
+ value = true;
+ }
+ // force non-HTML5 browsers to return bool
+ value = !!value;
+ } else {
+ value = $element.attr(method);
+ }
+
+ // convert the value to a number for number inputs, and for text for backwards compability
+ // allows type="date" and others to be compared as strings
+ if ( /min|max/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {
+ value = Number(value);
+ }
+
+ if ( value ) {
+ rules[method] = value;
+ } else if ( type === method && type !== 'range' ) {
+ // exception: the jquery validate 'range' method
+ // does not test for the html5 'range' type
+ rules[method] = true;
+ }
+ }
+
+ // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
+ if ( rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength) ) {
+ delete rules.maxlength;
+ }
+
+ return rules;
+ },
+
+ dataRules: function( element ) {
+ var method, value,
+ rules = {}, $element = $(element);
+ for (method in $.validator.methods) {
+ value = $element.data("rule-" + method.toLowerCase());
+ if ( value !== undefined ) {
+ rules[method] = value;
+ }
+ }
+ return rules;
+ },
+
+ staticRules: function( element ) {
+ var rules = {};
+ var validator = $.data(element.form, "validator");
+ if ( validator.settings.rules ) {
+ rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
+ }
+ return rules;
+ },
+
+ normalizeRules: function( rules, element ) {
+ // handle dependency check
+ $.each(rules, function( prop, val ) {
+ // ignore rule when param is explicitly false, eg. required:false
+ if ( val === false ) {
+ delete rules[prop];
+ return;
+ }
+ if ( val.param || val.depends ) {
+ var keepRule = true;
+ switch (typeof val.depends) {
+ case "string":
+ keepRule = !!$(val.depends, element.form).length;
+ break;
+ case "function":
+ keepRule = val.depends.call(element, element);
+ break;
+ }
+ if ( keepRule ) {
+ rules[prop] = val.param !== undefined ? val.param : true;
+ } else {
+ delete rules[prop];
+ }
+ }
+ });
+
+ // evaluate parameters
+ $.each(rules, function( rule, parameter ) {
+ rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
+ });
+
+ // clean number parameters
+ $.each(['minlength', 'maxlength'], function() {
+ if ( rules[this] ) {
+ rules[this] = Number(rules[this]);
+ }
+ });
+ $.each(['rangelength', 'range'], function() {
+ var parts;
+ if ( rules[this] ) {
+ if ( $.isArray(rules[this]) ) {
+ rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
+ } else if ( typeof rules[this] === "string" ) {
+ parts = rules[this].split(/[\s,]+/);
+ rules[this] = [Number(parts[0]), Number(parts[1])];
+ }
+ }
+ });
+
+ if ( $.validator.autoCreateRanges ) {
+ // auto-create ranges
+ if ( rules.min && rules.max ) {
+ rules.range = [rules.min, rules.max];
+ delete rules.min;
+ delete rules.max;
+ }
+ if ( rules.minlength && rules.maxlength ) {
+ rules.rangelength = [rules.minlength, rules.maxlength];
+ delete rules.minlength;
+ delete rules.maxlength;
+ }
+ }
+
+ return rules;
+ },
+
+ // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
+ normalizeRule: function( data ) {
+ if ( typeof data === "string" ) {
+ var transformed = {};
+ $.each(data.split(/\s/), function() {
+ transformed[this] = true;
+ });
+ data = transformed;
+ }
+ return data;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Validator/addMethod
+ addMethod: function( name, method, message ) {
+ $.validator.methods[name] = method;
+ $.validator.messages[name] = message !== undefined ? message : $.validator.messages[name];
+ if ( method.length < 3 ) {
+ $.validator.addClassRules(name, $.validator.normalizeRule(name));
+ }
+ },
+
+ methods: {
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/required
+ required: function( value, element, param ) {
+ // check if dependency is met
+ if ( !this.depend(param, element) ) {
+ return "dependency-mismatch";
+ }
+ if ( element.nodeName.toLowerCase() === "select" ) {
+ // could be an array for select-multiple or a string, both are fine this way
+ var val = $(element).val();
+ return val && val.length > 0;
+ }
+ if ( this.checkable(element) ) {
+ return this.getLength(value, element) > 0;
+ }
+ return $.trim(value).length > 0;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/email
+ email: function( value, element ) {
+ // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
+ return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/url
+ url: function( value, element ) {
+ // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
+ return this.optional(element) || /^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/date
+ date: function( value, element ) {
+
+ console.log("BOOL1: " + this.optional(element) + " / " + value);
+
+ return this.optional(element) || /\d{1,2}\.\d{1,2}\.\d{4}/.test(value) || /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/dateISO
+ dateISO: function( value, element ) {
+ return this.optional(element) || /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/number
+ number: function( value, element ) {
+ return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/digits
+ digits: function( value, element ) {
+ return this.optional(element) || /^\d+$/.test(value);
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/creditcard
+ // based on http://en.wikipedia.org/wiki/Luhn
+ creditcard: function( value, element ) {
+ if ( this.optional(element) ) {
+ return "dependency-mismatch";
+ }
+ // accept only spaces, digits and dashes
+ if ( /[^0-9 \-]+/.test(value) ) {
+ return false;
+ }
+ var nCheck = 0,
+ nDigit = 0,
+ bEven = false;
+
+ value = value.replace(/\D/g, "");
+
+ for (var n = value.length - 1; n >= 0; n--) {
+ var cDigit = value.charAt(n);
+ nDigit = parseInt(cDigit, 10);
+ if ( bEven ) {
+ if ( (nDigit *= 2) > 9 ) {
+ nDigit -= 9;
+ }
+ }
+ nCheck += nDigit;
+ bEven = !bEven;
+ }
+
+ return (nCheck % 10) === 0;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/minlength
+ minlength: function( value, element, param ) {
+ var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);
+ return this.optional(element) || length >= param;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/maxlength
+ maxlength: function( value, element, param ) {
+ var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);
+ return this.optional(element) || length <= param;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/rangelength
+ rangelength: function( value, element, param ) {
+ var length = $.isArray( value ) ? value.length : this.getLength($.trim(value), element);
+ return this.optional(element) || ( length >= param[0] && length <= param[1] );
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/min
+ min: function( value, element, param ) {
+ return this.optional(element) || value >= param;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/max
+ max: function( value, element, param ) {
+ return this.optional(element) || value <= param;
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/range
+ range: function( value, element, param ) {
+ return this.optional(element) || ( value >= param[0] && value <= param[1] );
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/equalTo
+ equalTo: function( value, element, param ) {
+ // bind to the blur event of the target in order to revalidate whenever the target field is updated
+ // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
+ var target = $(param);
+ if ( this.settings.onfocusout ) {
+ target.unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
+ $(element).valid();
+ });
+ }
+ return value === target.val();
+ },
+
+ // http://docs.jquery.com/Plugins/Validation/Methods/remote
+ remote: function( value, element, param ) {
+ if ( this.optional(element) ) {
+ return "dependency-mismatch";
+ }
+
+ var previous = this.previousValue(element);
+ if (!this.settings.messages[element.name] ) {
+ this.settings.messages[element.name] = {};
+ }
+ previous.originalMessage = this.settings.messages[element.name].remote;
+ this.settings.messages[element.name].remote = previous.message;
+
+ param = typeof param === "string" && {url:param} || param;
+
+ if ( previous.old === value ) {
+ return previous.valid;
+ }
+
+ previous.old = value;
+ var validator = this;
+ this.startRequest(element);
+ var data = {};
+ data[element.name] = value;
+ $.ajax($.extend(true, {
+ url: param,
+ mode: "abort",
+ port: "validate" + element.name,
+ dataType: "json",
+ data: data,
+ success: function( response ) {
+ validator.settings.messages[element.name].remote = previous.originalMessage;
+ var valid = response === true || response === "true";
+ if ( valid ) {
+ var submitted = validator.formSubmitted;
+ validator.prepareElement(element);
+ validator.formSubmitted = submitted;
+ validator.successList.push(element);
+ delete validator.invalid[element.name];
+ validator.showErrors();
+ } else {
+ var errors = {};
+ var message = response || validator.defaultMessage( element, "remote" );
+ errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
+ validator.invalid[element.name] = true;
+ validator.showErrors(errors);
+ }
+ previous.valid = valid;
+ validator.stopRequest(element, valid);
+ }
+ }, param));
+ return "pending";
+ }
+
+ }
+
+});
+
+// deprecated, use $.validator.format instead
+$.format = $.validator.format;
+
+}(jQuery));
+
+// ajax mode: abort
+// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
+// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
+(function($) {
+ var pendingRequests = {};
+ // Use a prefilter if available (1.5+)
+ if ( $.ajaxPrefilter ) {
+ $.ajaxPrefilter(function( settings, _, xhr ) {
+ var port = settings.port;
+ if ( settings.mode === "abort" ) {
+ if ( pendingRequests[port] ) {
+ pendingRequests[port].abort();
+ }
+ pendingRequests[port] = xhr;
+ }
+ });
+ } else {
+ // Proxy ajax
+ var ajax = $.ajax;
+ $.ajax = function( settings ) {
+ var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
+ port = ( "port" in settings ? settings : $.ajaxSettings ).port;
+ if ( mode === "abort" ) {
+ if ( pendingRequests[port] ) {
+ pendingRequests[port].abort();
+ }
+ pendingRequests[port] = ajax.apply(this, arguments);
+ return pendingRequests[port];
+ }
+ return ajax.apply(this, arguments);
+ };
+ }
+}(jQuery));
+
+// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
+// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
+(function($) {
+ $.extend($.fn, {
+ validateDelegate: function( delegate, type, handler ) {
+ return this.bind(type, function( event ) {
+ var target = $(event.target);
+ if ( target.is(delegate) ) {
+ return handler.apply(target, arguments);
+ }
+ });
+ }
+ });
+}(jQuery));
diff --git a/views/js/jquery.cookie.js b/views/js/jquery.cookie.js
new file mode 100644
index 0000000..f941a69
--- /dev/null
+++ b/views/js/jquery.cookie.js
@@ -0,0 +1,117 @@
+/*!
+ * jQuery Cookie Plugin v1.4.1
+ * https://github.com/carhartl/jquery-cookie
+ *
+ * Copyright 2006, 2014 Klaus Hartl
+ * Released under the MIT license
+ */
+(function (factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+}(function ($) {
+
+ var pluses = /\+/g;
+
+ function encode(s) {
+ return config.raw ? s : encodeURIComponent(s);
+ }
+
+ function decode(s) {
+ return config.raw ? s : decodeURIComponent(s);
+ }
+
+ function stringifyCookieValue(value) {
+ return encode(config.json ? JSON.stringify(value) : String(value));
+ }
+
+ function parseCookieValue(s) {
+ if (s.indexOf('"') === 0) {
+ // This is a quoted cookie as according to RFC2068, unescape...
+ s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
+ }
+
+ try {
+ // Replace server-side written pluses with spaces.
+ // If we can't decode the cookie, ignore it, it's unusable.
+ // If we can't parse the cookie, ignore it, it's unusable.
+ s = decodeURIComponent(s.replace(pluses, ' '));
+ return config.json ? JSON.parse(s) : s;
+ } catch(e) {}
+ }
+
+ function read(s, converter) {
+ var value = config.raw ? s : parseCookieValue(s);
+ return $.isFunction(converter) ? converter(value) : value;
+ }
+
+ var config = $.cookie = function (key, value, options) {
+
+ // Write
+
+ if (arguments.length > 1 && !$.isFunction(value)) {
+ options = $.extend({}, config.defaults, options);
+
+ if (typeof options.expires === 'number') {
+ var days = options.expires, t = options.expires = new Date();
+ t.setTime(+t + days * 864e+5);
+ }
+
+ return (document.cookie = [
+ encode(key), '=', stringifyCookieValue(value),
+ options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
+ options.path ? '; path=' + options.path : '',
+ options.domain ? '; domain=' + options.domain : '',
+ options.secure ? '; secure' : ''
+ ].join(''));
+ }
+
+ // Read
+
+ var result = key ? undefined : {};
+
+ // To prevent the for loop in the first place assign an empty array
+ // in case there are no cookies at all. Also prevents odd result when
+ // calling $.cookie().
+ var cookies = document.cookie ? document.cookie.split('; ') : [];
+
+ for (var i = 0, l = cookies.length; i < l; i++) {
+ var parts = cookies[i].split('=');
+ var name = decode(parts.shift());
+ var cookie = parts.join('=');
+
+ if (key && key === name) {
+ // If second argument (value) is a function it's a converter...
+ result = read(cookie, value);
+ break;
+ }
+
+ // Prevent storing a cookie that we couldn't decode.
+ if (!key && (cookie = read(cookie)) !== undefined) {
+ result[name] = cookie;
+ }
+ }
+
+ return result;
+ };
+
+ config.defaults = {};
+
+ $.removeCookie = function (key, options) {
+ if ($.cookie(key) === undefined) {
+ return false;
+ }
+
+ // Must not alter options, thus extending a fresh object...
+ $.cookie(key, '', $.extend({}, options, { expires: -1 }));
+ return !$.cookie(key);
+ };
+
+}));
diff --git a/views/js/jquery.validationEngine-de.js b/views/js/jquery.validationEngine-de.js
new file mode 100644
index 0000000..1da6342
--- /dev/null
+++ b/views/js/jquery.validationEngine-de.js
@@ -0,0 +1,131 @@
+
+(function($){
+ $.fn.validationEngineLanguage = function(){
+ };
+ $.validationEngineLanguage = {
+ newLang: function(){
+ $.validationEngineLanguage.allRules = {
+ "required": { // Add your regex rules here, you can take telephone as an example
+ "regex": "none",
+ "alertText": wpsg_trans_v1.required_alertText,
+ "alertTextCheckboxMultiple": wpsg_trans_v1.required_alertTextCheckboxMultiple,
+ "alertTextCheckboxe": wpsg_trans_v1.required_alertTextCheckboxe
+ },
+ "minSize": {
+ "regex": "none",
+ "alertText": wpsg_trans_v1.minSize_alertText,
+ "alertText2": wpsg_trans_v1.minSize_alertText2
+ },
+ "maxSize": {
+ "regex": "none",
+ "alertText": wpsg_trans_v1.maxSize_alertText,
+ "alertText2": wpsg_trans_v1.maxSize_alertText
+ },
+ "groupRequired": {
+ "regex": "none",
+ "alertText": wpsg_trans_v1.groupRequired_alertText
+ },
+ "min": {
+ "regex": "none",
+ "alertText": wpsg_trans_v1.min_alertText
+ },
+ "max": {
+ "regex": "none",
+ "alertText": wpsg_trans_v1.max_alertText
+ },
+ "past": {
+ "regex": "none",
+ "alertText": wpsg_trans_v1.past_alertText
+ },
+ "future": {
+ "regex": "none",
+ "alertText": wpsg_trans_v1.future_alertText
+ },
+ "maxCheckbox": {
+ "regex": "none",
+ "alertText": wpsg_trans_v1.maxCheckbox_alertText
+ },
+ "minCheckbox": {
+ "regex": "none",
+ "alertText": wpsg_trans_v1.minCheckbox_alertText,
+ "alertText2": wpsg_trans_v1.minCheckbox_alertText2
+ },
+ "equals": {
+ "regex": "none",
+ "alertText": wpsg_trans_v1.equals_alertText
+ },
+ "creditCard": {
+ "regex": "none",
+ "alertText": wpsg_trans_v1.creditCard_alertText
+ },
+ "phone": {
+ // credit: jquery.h5validate.js / orefalo
+ "regex": /^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{1,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/,
+ "alertText": wpsg_trans_v1.phone_alertText
+ },
+ "email": {
+ // Shamelessly lifted from Scott Gonzalez via the Bassistance Validation plugin http://projects.scottsplayground.com/email_address_validation/
+ "regex": /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i,
+ "alertText": wpsg_trans_v1.email_alertText
+ },
+ "integer": {
+ "regex": /^[\-\+]?\d+$/,
+ "alertText": wpsg_trans_v1.integer_alertText
+ },
+ "number": {
+ // Number, including positive, negative, and floating decimal. credit: orefalo
+ "regex": /^[\-\+]?(([0-9]+)([\.,]([0-9]+))?|([\.,]([0-9]+))?)$/,
+ "alertText": wpsg_trans_v1.number_alertText
+ },
+ "date": {
+ // Date in ISO format. Credit: bassistance
+ "regex": /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/,
+ "alertText": wpsg_trans_v1.date_alertText
+ },
+ "ipv4": {
+ "regex": /^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$/,
+ "alertText": wpsg_trans_v1.ipv4_alertText
+ },
+ "url": {
+ "regex": /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,
+ "alertText": wpsg_trans_v1.url_alertText
+ },
+ "onlyLetterSp": {
+ "regex": /^[a-zA-ZäüöÄÜÖßs\ \\\']+$/,
+ "alertText": wpsg_trans_v1.onlyLetterSp_alertText
+ },
+ "onlyLetterNumber": {
+ "regex": /^[0-9a-zA-ZäüöÄÜÖßs-]+$/,
+ "alertText": wpsg_trans_v1.onlyLetterNumber_alertText
+ },
+ // --- CUSTOM RULES -- Those are specific to the demos, they can be removed or changed to your likings
+ "ajaxUserCall": {
+ "url": "ajaxValidateFieldUser",
+ // you may want to pass extra data on the ajax call
+ "extraData": "name=eric",
+ "alertText": wpsg_trans_v1.ajaxUserCall_alertText,
+ "alertTextLoad": wpsg_trans_v1.ajaxUserCall_alertTextLoad
+ },
+ "ajaxNameCall": {
+ // remote json service location
+ "url": "ajaxValidateFieldName",
+ // error
+ "alertText": wpsg_trans_v1.ajaxNameCall_alertText,
+ // if you provide an "alertTextOk", it will show as a green prompt when the field validates
+ "alertTextOk": wpsg_trans_v1.ajaxNameCall_alertTextOk,
+ // speaks by itself
+ "alertTextLoad": wpsg_trans_v1.ajaxNameCall_alertTextLoad
+ },
+ "validate2fields": {
+ "alertText": wpsg_trans_v1.validate2fields_alertText
+ },
+ "vname": {
+ "regex": "none",
+ "alertText": wpsg_trans_v1.vname_alertText
+ }
+ };
+
+ }
+ };
+ $.validationEngineLanguage.newLang();
+})(jQuery); \ No newline at end of file
diff --git a/views/js/jquery.validationEngine.js b/views/js/jquery.validationEngine.js
new file mode 100644
index 0000000..054553d
--- /dev/null
+++ b/views/js/jquery.validationEngine.js
@@ -0,0 +1,2077 @@
+/*
+ * Inline Form Validation Engine 2.6.2, jQuery plugin
+ *
+ * Copyright(c) 2010, Cedric Dugas
+ * http://www.position-absolute.com
+ *
+ * 2.0 Rewrite by Olivier Refalo
+ * http://www.crionics.com
+ *
+ * Form validation engine allowing custom regex rules to be added.
+ * Licensed under the MIT License
+ */
+ (function($) {
+
+ "use strict";
+
+ var methods = {
+
+ /**
+ * Kind of the constructor, called before any action
+ * @param {Map} user options
+ */
+ init: function(options) {
+ var form = this;
+ if (!form.data('jqv') || form.data('jqv') == null ) {
+ options = methods._saveOptions(form, options);
+ // bind all formError elements to close on click
+ $(document).on("click", ".formError", function() {
+ $(this).fadeOut(150, function() {
+ // remove prompt once invisible
+ $(this).parent('.formErrorOuter').remove();
+ $(this).remove();
+ });
+ });
+ }
+ return this;
+ },
+ /**
+ * Attachs jQuery.validationEngine to form.submit and field.blur events
+ * Takes an optional params: a list of options
+ * ie. jQuery("#formID1").validationEngine('attach', {promptPosition : "centerRight"});
+ */
+ attach: function(userOptions) {
+
+ var form = this;
+ var options;
+
+ if(userOptions)
+ options = methods._saveOptions(form, userOptions);
+ else
+ options = form.data('jqv');
+
+ options.validateAttribute = (form.find("[data-validation-engine*=validate]").length) ? "data-validation-engine" : "class";
+ if (options.binded) {
+
+ // delegate fields
+ form.on(options.validationEventTrigger, "["+options.validateAttribute+"*=validate]:not([type=checkbox]):not([type=radio]):not(.datepicker)", methods._onFieldEvent);
+ form.on("click", "["+options.validateAttribute+"*=validate][type=checkbox],["+options.validateAttribute+"*=validate][type=radio]", methods._onFieldEvent);
+ form.on(options.validationEventTrigger,"["+options.validateAttribute+"*=validate][class*=datepicker]", {"delay": 300}, methods._onFieldEvent);
+ }
+ if (options.autoPositionUpdate) {
+ $(window).bind("resize", {
+ "noAnimation": true,
+ "formElem": form
+ }, methods.updatePromptsPosition);
+ }
+ form.on("click","a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick);
+ form.removeData('jqv_submitButton');
+
+ // bind form.submit
+ form.on("submit", methods._onSubmitEvent);
+ return this;
+ },
+ /**
+ * Unregisters any bindings that may point to jQuery.validaitonEngine
+ */
+ detach: function() {
+
+ var form = this;
+ var options = form.data('jqv');
+
+ // unbind fields
+ form.find("["+options.validateAttribute+"*=validate]").not("[type=checkbox]").off(options.validationEventTrigger, methods._onFieldEvent);
+ form.find("["+options.validateAttribute+"*=validate][type=checkbox],[class*=validate][type=radio]").off("click", methods._onFieldEvent);
+
+ // unbind form.submit
+ form.off("submit", methods._onSubmitEvent);
+ form.removeData('jqv');
+
+ form.off("click", "a[data-validation-engine-skip], a[class*='validate-skip'], button[data-validation-engine-skip], button[class*='validate-skip'], input[data-validation-engine-skip], input[class*='validate-skip']", methods._submitButtonClick);
+ form.removeData('jqv_submitButton');
+
+ if (options.autoPositionUpdate)
+ $(window).off("resize", methods.updatePromptsPosition);
+
+ return this;
+ },
+ /**
+ * Validates either a form or a list of fields, shows prompts accordingly.
+ * Note: There is no ajax form validation with this method, only field ajax validation are evaluated
+ *
+ * @return true if the form validates, false if it fails
+ */
+ validate: function() {
+ var element = $(this);
+ var valid = null;
+
+ if (element.is("form") || element.hasClass("validationEngineContainer")) {
+ if (element.hasClass('validating')) {
+ // form is already validating.
+ // Should abort old validation and start new one. I don't know how to implement it.
+ return false;
+ } else {
+ element.addClass('validating');
+ var options = element.data('jqv');
+ var valid = methods._validateFields(this);
+
+ // If the form doesn't validate, clear the 'validating' class before the user has a chance to submit again
+ setTimeout(function(){
+ element.removeClass('validating');
+ }, 100);
+ if (valid && options.onSuccess) {
+ options.onSuccess();
+ } else if (!valid && options.onFailure) {
+ options.onFailure();
+ }
+ }
+ } else if (element.is('form') || element.hasClass('validationEngineContainer')) {
+ element.removeClass('validating');
+ } else {
+ // field validation
+ var form = element.closest('form, .validationEngineContainer'),
+ options = (form.data('jqv')) ? form.data('jqv') : $.validationEngine.defaults,
+ valid = methods._validateField(element, options);
+
+ if (valid && options.onFieldSuccess)
+ options.onFieldSuccess();
+ else if (options.onFieldFailure && options.InvalidFields.length > 0) {
+ options.onFieldFailure();
+ }
+ }
+ if(options.onValidationComplete) {
+ // !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing
+ return !!options.onValidationComplete(form, valid);
+ }
+ return valid;
+ },
+ /**
+ * Redraw prompts position, useful when you change the DOM state when validating
+ */
+ updatePromptsPosition: function(event) {
+
+ if (event && this == window) {
+ var form = event.data.formElem;
+ var noAnimation = event.data.noAnimation;
+ }
+ else
+ var form = $(this.closest('form, .validationEngineContainer'));
+
+ var options = form.data('jqv');
+ // No option, take default one
+ form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each(function(){
+ var field = $(this);
+ if (options.prettySelect && field.is(":hidden"))
+ field = form.find("#" + options.usePrefix + field.attr('id') + options.useSuffix);
+ var prompt = methods._getPrompt(field);
+ var promptText = $(prompt).find(".formErrorContent").html();
+
+ if(prompt)
+ methods._updatePrompt(field, $(prompt), promptText, undefined, false, options, noAnimation);
+ });
+ return this;
+ },
+ /**
+ * Displays a prompt on a element.
+ * Note that the element needs an id!
+ *
+ * @param {String} promptText html text to display type
+ * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
+ * @param {String} possible values topLeft, topRight, bottomLeft, centerRight, bottomRight
+ */
+ showPrompt: function(promptText, type, promptPosition, showArrow) {
+ var form = this.closest('form, .validationEngineContainer');
+ var options = form.data('jqv');
+ // No option, take default one
+ if(!options)
+ options = methods._saveOptions(this, options);
+ if(promptPosition)
+ options.promptPosition=promptPosition;
+ options.showArrow = showArrow==true;
+
+ methods._showPrompt(this, promptText, type, false, options);
+ return this;
+ },
+ /**
+ * Closes form error prompts, CAN be invidual
+ */
+ hide: function() {
+ var form = $(this).closest('form, .validationEngineContainer');
+ var options = form.data('jqv');
+ var fadeDuration = (options && options.fadeDuration) ? options.fadeDuration : 0.3;
+ var closingtag;
+
+ if($(this).is("form") || $(this).hasClass("validationEngineContainer")) {
+ closingtag = "parentForm"+methods._getClassName($(this).attr("id"));
+ } else {
+ closingtag = methods._getClassName($(this).attr("id")) +"formError";
+ }
+ $('.'+closingtag).fadeTo(fadeDuration, 0.3, function() {
+ $(this).parent('.formErrorOuter').remove();
+ $(this).remove();
+ });
+ return this;
+ },
+ /**
+ * Closes all error prompts on the page
+ */
+ hideAll: function() {
+
+ var form = this;
+ var options = form.data('jqv');
+ var duration = options ? options.fadeDuration:300;
+ $('.formError').fadeTo(duration, 300, function() {
+ $(this).parent('.formErrorOuter').remove();
+ $(this).remove();
+ });
+ return this;
+ },
+ /**
+ * Typically called when user exists a field using tab or a mouse click, triggers a field
+ * validation
+ */
+ _onFieldEvent: function(event) {
+ var field = $(this);
+ var form = field.closest('form, .validationEngineContainer');
+ var options = form.data('jqv');
+ options.eventTrigger = "field";
+ // validate the current field
+ window.setTimeout(function() {
+ methods._validateField(field, options);
+ if (options.InvalidFields.length == 0 && options.onFieldSuccess) {
+ options.onFieldSuccess();
+ } else if (options.InvalidFields.length > 0 && options.onFieldFailure) {
+ options.onFieldFailure();
+ }
+ }, (event.data) ? event.data.delay : 0);
+
+ },
+ /**
+ * Called when the form is submited, shows prompts accordingly
+ *
+ * @param {jqObject}
+ * form
+ * @return false if form submission needs to be cancelled
+ */
+ _onSubmitEvent: function() {
+ var form = $(this);
+ var options = form.data('jqv');
+
+ //check if it is trigger from skipped button
+ if (form.data("jqv_submitButton")){
+ var submitButton = $("#" + form.data("jqv_submitButton"));
+ if (submitButton){
+ if (submitButton.length > 0){
+ if (submitButton.hasClass("validate-skip") || submitButton.attr("data-validation-engine-skip") == "true")
+ return true;
+ }
+ }
+ }
+
+ options.eventTrigger = "submit";
+
+ // validate each field
+ // (- skip field ajax validation, not necessary IF we will perform an ajax form validation)
+ var r=methods._validateFields(form);
+
+ if (r && options.ajaxFormValidation) {
+ methods._validateFormWithAjax(form, options);
+ // cancel form auto-submission - process with async call onAjaxFormComplete
+ return false;
+ }
+
+ if(options.onValidationComplete) {
+ // !! ensures that an undefined return is interpreted as return false but allows a onValidationComplete() to possibly return true and have form continue processing
+ return !!options.onValidationComplete(form, r);
+ }
+ return r;
+ },
+ /**
+ * Return true if the ajax field validations passed so far
+ * @param {Object} options
+ * @return true, is all ajax validation passed so far (remember ajax is async)
+ */
+ _checkAjaxStatus: function(options) {
+ var status = true;
+ $.each(options.ajaxValidCache, function(key, value) {
+ if (!value) {
+ status = false;
+ // break the each
+ return false;
+ }
+ });
+ return status;
+ },
+
+ /**
+ * Return true if the ajax field is validated
+ * @param {String} fieldid
+ * @param {Object} options
+ * @return true, if validation passed, false if false or doesn't exist
+ */
+ _checkAjaxFieldStatus: function(fieldid, options) {
+ return options.ajaxValidCache[fieldid] == true;
+ },
+ /**
+ * Validates form fields, shows prompts accordingly
+ *
+ * @param {jqObject}
+ * form
+ * @param {skipAjaxFieldValidation}
+ * boolean - when set to true, ajax field validation is skipped, typically used when the submit button is clicked
+ *
+ * @return true if form is valid, false if not, undefined if ajax form validation is done
+ */
+ _validateFields: function(form) {
+ var options = form.data('jqv');
+
+ // this variable is set to true if an error is found
+ var errorFound = false;
+
+ // Trigger hook, start validation
+ form.trigger("jqv.form.validating");
+ // first, evaluate status of non ajax fields
+ var first_err=null;
+ form.find('['+options.validateAttribute+'*=validate]').not(":disabled").each( function() {
+ var field = $(this);
+ var names = [];
+ if ($.inArray(field.attr('name'), names) < 0) {
+ errorFound |= methods._validateField(field, options);
+ if (errorFound && first_err==null)
+ if (field.is(":hidden") && options.prettySelect)
+ first_err = field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix);
+ else {
+
+ //Check if we need to adjust what element to show the prompt on
+ //and and such scroll to instead
+ if(field.data('jqv-prompt-at') instanceof jQuery ){
+ field = field.data('jqv-prompt-at');
+ } else if(field.data('jqv-prompt-at')) {
+ field = $(field.data('jqv-prompt-at'));
+ }
+ first_err=field;
+ }
+ if (options.doNotShowAllErrosOnSubmit)
+ return false;
+ names.push(field.attr('name'));
+
+ //if option set, stop checking validation rules after one error is found
+ if(options.showOneMessage == true && errorFound){
+ return false;
+ }
+ }
+ });
+
+ // second, check to see if all ajax calls completed ok
+ // errorFound |= !methods._checkAjaxStatus(options);
+
+ // third, check status and scroll the container accordingly
+ form.trigger("jqv.form.result", [errorFound]);
+
+ if (errorFound) {
+ if (options.scroll) {
+ var destination=first_err.offset().top;
+ var fixleft = first_err.offset().left;
+
+ //prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10)
+ var positionType=options.promptPosition;
+ if (typeof(positionType)=='string' && positionType.indexOf(":")!=-1)
+ positionType=positionType.substring(0,positionType.indexOf(":"));
+
+ if (positionType!="bottomRight" && positionType!="bottomLeft") {
+ var prompt_err= methods._getPrompt(first_err);
+ if (prompt_err) {
+ destination=prompt_err.offset().top;
+ }
+ }
+
+ // Offset the amount the page scrolls by an amount in px to accomodate fixed elements at top of page
+ if (options.scrollOffset) {
+ destination -= options.scrollOffset;
+ }
+
+ // get the position of the first error, there should be at least one, no need to check this
+ //var destination = form.find(".formError:not('.greenPopup'):first").offset().top;
+ if (options.isOverflown) {
+ var overflowDIV = $(options.overflownDIV);
+ if(!overflowDIV.length) return false;
+ var scrollContainerScroll = overflowDIV.scrollTop();
+ var scrollContainerPos = -parseInt(overflowDIV.offset().top);
+
+ destination += scrollContainerScroll + scrollContainerPos - 5;
+ var scrollContainer = $(options.overflownDIV + ":not(:animated)");
+
+ scrollContainer.animate({ scrollTop: destination }, 1100, function(){
+ if(options.focusFirstField) first_err.focus();
+ });
+
+ } else {
+ $("html, body").animate({
+ scrollTop: destination
+ }, 1100, function(){
+ if(options.focusFirstField) first_err.focus();
+ });
+ $("html, body").animate({scrollLeft: fixleft},1100)
+ }
+
+ } else if(options.focusFirstField)
+ first_err.focus();
+ return false;
+ }
+ return true;
+ },
+ /**
+ * This method is called to perform an ajax form validation.
+ * During this process all the (field, value) pairs are sent to the server which returns a list of invalid fields or true
+ *
+ * @param {jqObject} form
+ * @param {Map} options
+ */
+ _validateFormWithAjax: function(form, options) {
+
+ var data = form.serialize();
+ var type = (options.ajaxFormValidationMethod) ? options.ajaxFormValidationMethod : "GET";
+ var url = (options.ajaxFormValidationURL) ? options.ajaxFormValidationURL : form.attr("action");
+ var dataType = (options.dataType) ? options.dataType : "json";
+ $.ajax({
+ type: type,
+ url: url,
+ cache: false,
+ dataType: dataType,
+ data: data,
+ form: form,
+ methods: methods,
+ options: options,
+ beforeSend: function() {
+ return options.onBeforeAjaxFormValidation(form, options);
+ },
+ error: function(data, transport) {
+ if (options.onFailure) {
+ options.onFailure(data, transport);
+ } else {
+ methods._ajaxError(data, transport);
+ }
+ },
+ success: function(json) {
+ if ((dataType == "json") && (json !== true)) {
+ // getting to this case doesn't necessary means that the form is invalid
+ // the server may return green or closing prompt actions
+ // this flag helps figuring it out
+ var errorInForm=false;
+ for (var i = 0; i < json.length; i++) {
+ var value = json[i];
+
+ var errorFieldId = value[0];
+ var errorField = $($("#" + errorFieldId)[0]);
+
+ // make sure we found the element
+ if (errorField.length == 1) {
+
+ // promptText or selector
+ var msg = value[2];
+ // if the field is valid
+ if (value[1] == true) {
+
+ if (msg == "" || !msg){
+ // if for some reason, status==true and error="", just close the prompt
+ methods._closePrompt(errorField);
+ } else {
+ // the field is valid, but we are displaying a green prompt
+ if (options.allrules[msg]) {
+ var txt = options.allrules[msg].alertTextOk;
+ if (txt)
+ msg = txt;
+ }
+ if (options.showPrompts) methods._showPrompt(errorField, msg, "pass", false, options, true);
+ }
+ } else {
+ // the field is invalid, show the red error prompt
+ errorInForm|=true;
+ if (options.allrules[msg]) {
+ var txt = options.allrules[msg].alertText;
+ if (txt)
+ msg = txt;
+ }
+ if(options.showPrompts) methods._showPrompt(errorField, msg, "", false, options, true);
+ }
+ }
+ }
+ options.onAjaxFormComplete(!errorInForm, form, json, options);
+ } else
+ options.onAjaxFormComplete(true, form, json, options);
+
+ }
+ });
+
+ },
+ /**
+ * Validates field, shows prompts accordingly
+ *
+ * @param {jqObject}
+ * field
+ * @param {Array[String]}
+ * field's validation rules
+ * @param {Map}
+ * user options
+ * @return false if field is valid (It is inversed for *fields*, it return false on validate and true on errors.)
+ */
+ _validateField: function(field, options, skipAjaxValidation) {
+ if (!field.attr("id")) {
+ field.attr("id", "form-validation-field-" + $.validationEngine.fieldIdCounter);
+ ++$.validationEngine.fieldIdCounter;
+ }
+
+ if (!options.validateNonVisibleFields && (field.is(":hidden") && !options.prettySelect || field.parent().is(":hidden")))
+ return false;
+
+ var rulesParsing = field.attr(options.validateAttribute);
+ var getRules = /validate\[(.*)\]/.exec(rulesParsing);
+
+ if (!getRules)
+ return false;
+ var str = getRules[1];
+ var rules = str.split(/\[|,|\]/);
+
+ // true if we ran the ajax validation, tells the logic to stop messing with prompts
+ var isAjaxValidator = false;
+ var fieldName = field.attr("name");
+ var promptText = "";
+ var promptType = "";
+ var required = false;
+ var limitErrors = false;
+ options.isError = false;
+ options.showArrow = true;
+
+ // If the programmer wants to limit the amount of error messages per field,
+ if (options.maxErrorsPerField > 0) {
+ limitErrors = true;
+ }
+
+ var form = $(field.closest("form, .validationEngineContainer"));
+ // Fix for adding spaces in the rules
+ for (var i = 0; i < rules.length; i++) {
+ rules[i] = rules[i].replace(" ", "");
+ // Remove any parsing errors
+ if (rules[i] === '') {
+ delete rules[i];
+ }
+ }
+
+ for (var i = 0, field_errors = 0; i < rules.length; i++) {
+
+ // If we are limiting errors, and have hit the max, break
+ if (limitErrors && field_errors >= options.maxErrorsPerField) {
+ // If we haven't hit a required yet, check to see if there is one in the validation rules for this
+ // field and that it's index is greater or equal to our current index
+ if (!required) {
+ var have_required = $.inArray('required', rules);
+ required = (have_required != -1 && have_required >= i);
+ }
+ break;
+ }
+
+
+ var errorMsg = undefined;
+ switch (rules[i]) {
+
+ case "required":
+ required = true;
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._required);
+ break;
+ case "custom":
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._custom);
+ break;
+ case "groupRequired":
+ // Check is its the first of group, if not, reload validation with first field
+ // AND continue normal validation on present field
+ var classGroup = "["+options.validateAttribute+"*=" +rules[i + 1] +"]";
+ var firstOfGroup = form.find(classGroup).eq(0);
+ if(firstOfGroup[0] != field[0]){
+
+ methods._validateField(firstOfGroup, options, skipAjaxValidation);
+ options.showArrow = true;
+
+ }
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._groupRequired);
+ if(errorMsg) required = true;
+ options.showArrow = false;
+ break;
+ case "ajax":
+ // AJAX defaults to returning it's loading message
+ errorMsg = methods._ajax(field, rules, i, options);
+ if (errorMsg) {
+ promptType = "load";
+ }
+ break;
+ case "minSize":
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minSize);
+ break;
+ case "maxSize":
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxSize);
+ break;
+ case "min":
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._min);
+ break;
+ case "max":
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._max);
+ break;
+ case "past":
+ errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._past);
+ break;
+ case "future":
+ errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._future);
+ break;
+ case "dateRange":
+ var classGroup = "["+options.validateAttribute+"*=" + rules[i + 1] + "]";
+ options.firstOfGroup = form.find(classGroup).eq(0);
+ options.secondOfGroup = form.find(classGroup).eq(1);
+
+ //if one entry out of the pair has value then proceed to run through validation
+ if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) {
+ errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._dateRange);
+ }
+ if (errorMsg) required = true;
+ options.showArrow = false;
+ break;
+
+ case "dateTimeRange":
+ var classGroup = "["+options.validateAttribute+"*=" + rules[i + 1] + "]";
+ options.firstOfGroup = form.find(classGroup).eq(0);
+ options.secondOfGroup = form.find(classGroup).eq(1);
+
+ //if one entry out of the pair has value then proceed to run through validation
+ if (options.firstOfGroup[0].value || options.secondOfGroup[0].value) {
+ errorMsg = methods._getErrorMessage(form, field,rules[i], rules, i, options, methods._dateTimeRange);
+ }
+ if (errorMsg) required = true;
+ options.showArrow = false;
+ break;
+ case "maxCheckbox":
+ field = $(form.find("input[name='" + fieldName + "']"));
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._maxCheckbox);
+ break;
+ case "minCheckbox":
+ field = $(form.find("input[name='" + fieldName + "']"));
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._minCheckbox);
+ break;
+ case "equals":
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._equals);
+ break;
+ case "funcCall":
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._funcCall);
+ break;
+ case "creditCard":
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._creditCard);
+ break;
+ case "condRequired":
+ errorMsg = methods._getErrorMessage(form, field, rules[i], rules, i, options, methods._condRequired);
+ if (errorMsg !== undefined) {
+ required = true;
+ }
+ break;
+
+ default:
+ }
+
+ var end_validation = false;
+
+ // If we were passed back an message object, check what the status was to determine what to do
+ if (typeof errorMsg == "object") {
+ switch (errorMsg.status) {
+ case "_break":
+ end_validation = true;
+ break;
+ // If we have an error message, set errorMsg to the error message
+ case "_error":
+ errorMsg = errorMsg.message;
+ break;
+ // If we want to throw an error, but not show a prompt, return early with true
+ case "_error_no_prompt":
+ return true;
+ break;
+ // Anything else we continue on
+ default:
+ break;
+ }
+ }
+
+ // If it has been specified that validation should end now, break
+ if (end_validation) {
+ break;
+ }
+
+ // If we have a string, that means that we have an error, so add it to the error message.
+ if (typeof errorMsg == 'string') {
+ promptText += errorMsg + "<br/>";
+ options.isError = true;
+ field_errors++;
+ }
+ }
+ // If the rules required is not added, an empty field is not validated
+ //the 3rd condition is added so that even empty password fields should be equal
+ //otherwise if one is filled and another left empty, the "equal" condition would fail
+ //which does not make any sense
+ if(!required && !(field.val()) && field.val().length < 1 && rules.indexOf("equals") < 0) options.isError = false;
+
+ // Hack for radio/checkbox group button, the validation go into the
+ // first radio/checkbox of the group
+ var fieldType = field.prop("type");
+ var positionType=field.data("promptPosition") || options.promptPosition;
+
+ if ((fieldType == "radio" || fieldType == "checkbox") && form.find("input[name='" + fieldName + "']").size() > 1) {
+ if(positionType === 'inline') {
+ field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:last"));
+ } else {
+ field = $(form.find("input[name='" + fieldName + "'][type!=hidden]:first"));
+ }
+ options.showArrow = false;
+ }
+
+ if(field.is(":hidden") && options.prettySelect) {
+ field = form.find("#" + options.usePrefix + methods._jqSelector(field.attr('id')) + options.useSuffix);
+ }
+
+ if (options.isError && options.showPrompts){
+ methods._showPrompt(field, promptText, promptType, false, options);
+ }else{
+ if (!isAjaxValidator) methods._closePrompt(field);
+ }
+
+ if (!isAjaxValidator) {
+ field.trigger("jqv.field.result", [field, options.isError, promptText]);
+ }
+
+ /* Record error */
+ var errindex = $.inArray(field[0], options.InvalidFields);
+ if (errindex == -1) {
+ if (options.isError)
+ options.InvalidFields.push(field[0]);
+ } else if (!options.isError) {
+ options.InvalidFields.splice(errindex, 1);
+ }
+
+ methods._handleStatusCssClasses(field, options);
+
+ /* run callback function for each field */
+ if (options.isError && options.onFieldFailure)
+ options.onFieldFailure(field);
+
+ if (!options.isError && options.onFieldSuccess)
+ options.onFieldSuccess(field);
+
+ return options.isError;
+ },
+ /**
+ * Handling css classes of fields indicating result of validation
+ *
+ * @param {jqObject}
+ * field
+ * @param {Array[String]}
+ * field's validation rules
+ * @private
+ */
+ _handleStatusCssClasses: function(field, options) {
+ /* remove all classes */
+ if(options.addSuccessCssClassToField)
+ field.removeClass(options.addSuccessCssClassToField);
+
+ if(options.addFailureCssClassToField)
+ field.removeClass(options.addFailureCssClassToField);
+
+ /* Add classes */
+ if (options.addSuccessCssClassToField && !options.isError)
+ field.addClass(options.addSuccessCssClassToField);
+
+ if (options.addFailureCssClassToField && options.isError)
+ field.addClass(options.addFailureCssClassToField);
+ },
+
+ /********************
+ * _getErrorMessage
+ *
+ * @param form
+ * @param field
+ * @param rule
+ * @param rules
+ * @param i
+ * @param options
+ * @param originalValidationMethod
+ * @return {*}
+ * @private
+ */
+ _getErrorMessage:function (form, field, rule, rules, i, options, originalValidationMethod) {
+ // If we are using the custon validation type, build the index for the rule.
+ // Otherwise if we are doing a function call, make the call and return the object
+ // that is passed back.
+ var rule_index = jQuery.inArray(rule, rules);
+ if (rule === "custom" || rule === "funcCall") {
+ var custom_validation_type = rules[rule_index + 1];
+ rule = rule + "[" + custom_validation_type + "]";
+ // Delete the rule from the rules array so that it doesn't try to call the
+ // same rule over again
+ delete(rules[rule_index]);
+ }
+ // Change the rule to the composite rule, if it was different from the original
+ var alteredRule = rule;
+
+
+ var element_classes = (field.attr("data-validation-engine")) ? field.attr("data-validation-engine") : field.attr("class");
+ var element_classes_array = element_classes.split(" ");
+
+ // Call the original validation method. If we are dealing with dates or checkboxes, also pass the form
+ var errorMsg;
+ if (rule == "future" || rule == "past" || rule == "maxCheckbox" || rule == "minCheckbox") {
+ errorMsg = originalValidationMethod(form, field, rules, i, options);
+ } else {
+ errorMsg = originalValidationMethod(field, rules, i, options);
+ }
+
+ // If the original validation method returned an error and we have a custom error message,
+ // return the custom message instead. Otherwise return the original error message.
+ if (errorMsg != undefined) {
+ var custom_message = methods._getCustomErrorMessage($(field), element_classes_array, alteredRule, options);
+ if (custom_message) errorMsg = custom_message;
+ }
+ return errorMsg;
+
+ },
+ _getCustomErrorMessage:function (field, classes, rule, options) {
+ var custom_message = false;
+ var validityProp = /^custom\[.*\]$/.test(rule) ? methods._validityProp["custom"] : methods._validityProp[rule];
+ // If there is a validityProp for this rule, check to see if the field has an attribute for it
+ if (validityProp != undefined) {
+ custom_message = field.attr("data-errormessage-"+validityProp);
+ // If there was an error message for it, return the message
+ if (custom_message != undefined)
+ return custom_message;
+ }
+ custom_message = field.attr("data-errormessage");
+ // If there is an inline custom error message, return it
+ if (custom_message != undefined)
+ return custom_message;
+ var id = '#' + field.attr("id");
+ // If we have custom messages for the element's id, get the message for the rule from the id.
+ // Otherwise, if we have custom messages for the element's classes, use the first class message we find instead.
+ if (typeof options.custom_error_messages[id] != "undefined" &&
+ typeof options.custom_error_messages[id][rule] != "undefined" ) {
+ custom_message = options.custom_error_messages[id][rule]['message'];
+ } else if (classes.length > 0) {
+ for (var i = 0; i < classes.length && classes.length > 0; i++) {
+ var element_class = "." + classes[i];
+ if (typeof options.custom_error_messages[element_class] != "undefined" &&
+ typeof options.custom_error_messages[element_class][rule] != "undefined") {
+ custom_message = options.custom_error_messages[element_class][rule]['message'];
+ break;
+ }
+ }
+ }
+ if (!custom_message &&
+ typeof options.custom_error_messages[rule] != "undefined" &&
+ typeof options.custom_error_messages[rule]['message'] != "undefined"){
+ custom_message = options.custom_error_messages[rule]['message'];
+ }
+ return custom_message;
+ },
+ _validityProp: {
+ "required": "value-missing",
+ "custom": "custom-error",
+ "groupRequired": "value-missing",
+ "ajax": "custom-error",
+ "minSize": "range-underflow",
+ "maxSize": "range-overflow",
+ "min": "range-underflow",
+ "max": "range-overflow",
+ "past": "type-mismatch",
+ "future": "type-mismatch",
+ "dateRange": "type-mismatch",
+ "dateTimeRange": "type-mismatch",
+ "maxCheckbox": "range-overflow",
+ "minCheckbox": "range-underflow",
+ "equals": "pattern-mismatch",
+ "funcCall": "custom-error",
+ "creditCard": "pattern-mismatch",
+ "condRequired": "value-missing"
+ },
+ /**
+ * Required validation
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @param {bool} condRequired flag when method is used for internal purpose in condRequired check
+ * @return an error string if validation failed
+ */
+ _required: function(field, rules, i, options, condRequired) {
+ switch (field.prop("type")) {
+ case "text":
+ case "password":
+ case "textarea":
+ case "file":
+ case "select-one":
+ case "select-multiple":
+ default:
+ var field_val = $.trim( field.val() );
+ var dv_placeholder = $.trim( field.attr("data-validation-placeholder") );
+ var placeholder = $.trim( field.attr("placeholder") );
+ if (
+ ( !field_val )
+ || ( dv_placeholder && field_val == dv_placeholder )
+ || ( placeholder && field_val == placeholder )
+ ) {
+ return options.allrules[rules[i]].alertText;
+ }
+ break;
+ case "radio":
+ case "checkbox":
+ // new validation style to only check dependent field
+ if (condRequired) {
+ if (!field.attr('checked')) {
+ return options.allrules[rules[i]].alertTextCheckboxMultiple;
+ }
+ break;
+ }
+ // old validation style
+ var form = field.closest("form, .validationEngineContainer");
+ var name = field.attr("name");
+ if (form.find("input[name='" + name + "']:checked").size() == 0) {
+ if (form.find("input[name='" + name + "']:visible").size() == 1)
+ return options.allrules[rules[i]].alertTextCheckboxe;
+ else
+ return options.allrules[rules[i]].alertTextCheckboxMultiple;
+ }
+ break;
+ }
+ },
+ /**
+ * Validate that 1 from the group field is required
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return an error string if validation failed
+ */
+ _groupRequired: function(field, rules, i, options) {
+ var classGroup = "["+options.validateAttribute+"*=" +rules[i + 1] +"]";
+ var isValid = false;
+ // Check all fields from the group
+ field.closest("form, .validationEngineContainer").find(classGroup).each(function(){
+ if(!methods._required($(this), rules, i, options)){
+ isValid = true;
+ return false;
+ }
+ });
+
+ if(!isValid) {
+ return options.allrules[rules[i]].alertText;
+ }
+ },
+ /**
+ * Validate rules
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return an error string if validation failed
+ */
+ _custom: function(field, rules, i, options) {
+ var customRule = rules[i + 1];
+ var rule = options.allrules[customRule];
+ var fn;
+ if(!rule) {
+ alert("jqv:custom rule not found - "+customRule);
+ return;
+ }
+
+ if(rule["regex"]) {
+ var ex=rule.regex;
+ if(!ex) {
+ alert("jqv:custom regex not found - "+customRule);
+ return;
+ }
+ var pattern = new RegExp(ex);
+
+ if (!pattern.test(field.val())) return options.allrules[customRule].alertText;
+
+ } else if(rule["func"]) {
+ fn = rule["func"];
+
+ if (typeof(fn) !== "function") {
+ alert("jqv:custom parameter 'function' is no function - "+customRule);
+ return;
+ }
+
+ if (!fn(field, rules, i, options))
+ return options.allrules[customRule].alertText;
+ } else {
+ alert("jqv:custom type not allowed "+customRule);
+ return;
+ }
+ },
+ /**
+ * Validate custom function outside of the engine scope
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return an error string if validation failed
+ */
+ _funcCall: function(field, rules, i, options) {
+ var functionName = rules[i + 1];
+ var fn;
+ if(functionName.indexOf('.') >-1)
+ {
+ var namespaces = functionName.split('.');
+ var scope = window;
+ while(namespaces.length)
+ {
+ scope = scope[namespaces.shift()];
+ }
+ fn = scope;
+ }
+ else
+ fn = window[functionName] || options.customFunctions[functionName];
+ if (typeof(fn) == 'function')
+ return fn(field, rules, i, options);
+
+ },
+ /**
+ * Field match
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return an error string if validation failed
+ */
+ _equals: function(field, rules, i, options) {
+ var equalsField = rules[i + 1];
+
+ if (field.val() != $("#" + equalsField).val())
+ return options.allrules.equals.alertText;
+ },
+ /**
+ * Check the maximum size (in characters)
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return an error string if validation failed
+ */
+ _maxSize: function(field, rules, i, options) {
+ var max = rules[i + 1];
+ var len = field.val().length;
+
+ if (len > max) {
+ var rule = options.allrules.maxSize;
+ return rule.alertText + max + rule.alertText2;
+ }
+ },
+ /**
+ * Check the minimum size (in characters)
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return an error string if validation failed
+ */
+ _minSize: function(field, rules, i, options) {
+ var min = rules[i + 1];
+ var len = field.val().length;
+
+ if (len < min) {
+ var rule = options.allrules.minSize;
+ return rule.alertText + min + rule.alertText2;
+ }
+ },
+ /**
+ * Check number minimum value
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return an error string if validation failed
+ */
+ _min: function(field, rules, i, options) {
+ var min = parseFloat(rules[i + 1]);
+ var len = parseFloat(field.val());
+
+ if (len < min) {
+ var rule = options.allrules.min;
+ if (rule.alertText2) return rule.alertText + min + rule.alertText2;
+ return rule.alertText + min;
+ }
+ },
+ /**
+ * Check number maximum value
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return an error string if validation failed
+ */
+ _max: function(field, rules, i, options) {
+ var max = parseFloat(rules[i + 1]);
+ var len = parseFloat(field.val());
+
+ if (len >max ) {
+ var rule = options.allrules.max;
+ if (rule.alertText2) return rule.alertText + max + rule.alertText2;
+ //orefalo: to review, also do the translations
+ return rule.alertText + max;
+ }
+ },
+ /**
+ * Checks date is in the past
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return an error string if validation failed
+ */
+ _past: function(form, field, rules, i, options) {
+
+ var p=rules[i + 1];
+ var fieldAlt = $(form.find("*[name='" + p.replace(/^#+/, '') + "']"));
+ var pdate;
+
+ if (p.toLowerCase() == "now") {
+ pdate = new Date();
+ } else if (undefined != fieldAlt.val()) {
+ if (fieldAlt.is(":disabled"))
+ return;
+ pdate = methods._parseDate(fieldAlt.val());
+ } else {
+ pdate = methods._parseDate(p);
+ }
+ var vdate = methods._parseDate(field.val());
+
+ if (vdate > pdate ) {
+ var rule = options.allrules.past;
+ if (rule.alertText2) return rule.alertText + methods._dateToString(pdate) + rule.alertText2;
+ return rule.alertText + methods._dateToString(pdate);
+ }
+ },
+ /**
+ * Checks date is in the future
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return an error string if validation failed
+ */
+ _future: function(form, field, rules, i, options) {
+
+ var p=rules[i + 1];
+ var fieldAlt = $(form.find("*[name='" + p.replace(/^#+/, '') + "']"));
+ var pdate;
+
+ if (p.toLowerCase() == "now") {
+ pdate = new Date();
+ } else if (undefined != fieldAlt.val()) {
+ if (fieldAlt.is(":disabled"))
+ return;
+ pdate = methods._parseDate(fieldAlt.val());
+ } else {
+ pdate = methods._parseDate(p);
+ }
+ var vdate = methods._parseDate(field.val());
+
+ if (vdate < pdate ) {
+ var rule = options.allrules.future;
+ if (rule.alertText2)
+ return rule.alertText + methods._dateToString(pdate) + rule.alertText2;
+ return rule.alertText + methods._dateToString(pdate);
+ }
+ },
+ /**
+ * Checks if valid date
+ *
+ * @param {string} date string
+ * @return a bool based on determination of valid date
+ */
+ _isDate: function (value) {
+ var dateRegEx = new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(?:(?:0?[1-9]|1[0-2])(\/|-)(?:0?[1-9]|1\d|2[0-8]))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(0?2(\/|-)29)(\/|-)(?:(?:0[48]00|[13579][26]00|[2468][048]00)|(?:\d\d)?(?:0[48]|[2468][048]|[13579][26]))$/);
+ return dateRegEx.test(value);
+ },
+ /**
+ * Checks if valid date time
+ *
+ * @param {string} date string
+ * @return a bool based on determination of valid date time
+ */
+ _isDateTime: function (value){
+ var dateTimeRegEx = new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1}$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^((1[012]|0?[1-9]){1}\/(0?[1-9]|[12][0-9]|3[01]){1}\/\d{2,4}\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1})$/);
+ return dateTimeRegEx.test(value);
+ },
+ //Checks if the start date is before the end date
+ //returns true if end is later than start
+ _dateCompare: function (start, end) {
+ return (new Date(start.toString()) < new Date(end.toString()));
+ },
+ /**
+ * Checks date range
+ *
+ * @param {jqObject} first field name
+ * @param {jqObject} second field name
+ * @return an error string if validation failed
+ */
+ _dateRange: function (field, rules, i, options) {
+ //are not both populated
+ if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) {
+ return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
+ }
+
+ //are not both dates
+ if (!methods._isDate(options.firstOfGroup[0].value) || !methods._isDate(options.secondOfGroup[0].value)) {
+ return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
+ }
+
+ //are both dates but range is off
+ if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) {
+ return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
+ }
+ },
+ /**
+ * Checks date time range
+ *
+ * @param {jqObject} first field name
+ * @param {jqObject} second field name
+ * @return an error string if validation failed
+ */
+ _dateTimeRange: function (field, rules, i, options) {
+ //are not both populated
+ if ((!options.firstOfGroup[0].value && options.secondOfGroup[0].value) || (options.firstOfGroup[0].value && !options.secondOfGroup[0].value)) {
+ return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
+ }
+ //are not both dates
+ if (!methods._isDateTime(options.firstOfGroup[0].value) || !methods._isDateTime(options.secondOfGroup[0].value)) {
+ return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
+ }
+ //are both dates but range is off
+ if (!methods._dateCompare(options.firstOfGroup[0].value, options.secondOfGroup[0].value)) {
+ return options.allrules[rules[i]].alertText + options.allrules[rules[i]].alertText2;
+ }
+ },
+ /**
+ * Max number of checkbox selected
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return an error string if validation failed
+ */
+ _maxCheckbox: function(form, field, rules, i, options) {
+
+ var nbCheck = rules[i + 1];
+ var groupname = field.attr("name");
+ var groupSize = form.find("input[name='" + groupname + "']:checked").size();
+ if (groupSize > nbCheck) {
+ options.showArrow = false;
+ if (options.allrules.maxCheckbox.alertText2)
+ return options.allrules.maxCheckbox.alertText + " " + nbCheck + " " + options.allrules.maxCheckbox.alertText2;
+ return options.allrules.maxCheckbox.alertText;
+ }
+ },
+ /**
+ * Min number of checkbox selected
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return an error string if validation failed
+ */
+ _minCheckbox: function(form, field, rules, i, options) {
+
+ var nbCheck = rules[i + 1];
+ var groupname = field.attr("name");
+ var groupSize = form.find("input[name='" + groupname + "']:checked").size();
+ if (groupSize < nbCheck) {
+ options.showArrow = false;
+ return options.allrules.minCheckbox.alertText + " " + nbCheck + " " + options.allrules.minCheckbox.alertText2;
+ }
+ },
+ /**
+ * Checks that it is a valid credit card number according to the
+ * Luhn checksum algorithm.
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return an error string if validation failed
+ */
+ _creditCard: function(field, rules, i, options) {
+ //spaces and dashes may be valid characters, but must be stripped to calculate the checksum.
+ var valid = false, cardNumber = field.val().replace(/ +/g, '').replace(/-+/g, '');
+
+ var numDigits = cardNumber.length;
+ if (numDigits >= 14 && numDigits <= 16 && parseInt(cardNumber) > 0) {
+
+ var sum = 0, i = numDigits - 1, pos = 1, digit, luhn = new String();
+ do {
+ digit = parseInt(cardNumber.charAt(i));
+ luhn += (pos++ % 2 == 0) ? digit * 2 : digit;
+ } while (--i >= 0)
+
+ for (i = 0; i < luhn.length; i++) {
+ sum += parseInt(luhn.charAt(i));
+ }
+ valid = sum % 10 == 0;
+ }
+ if (!valid) return options.allrules.creditCard.alertText;
+ },
+ /**
+ * Ajax field validation
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return nothing! the ajax validator handles the prompts itself
+ */
+ _ajax: function(field, rules, i, options) {
+
+ var errorSelector = rules[i + 1];
+ var rule = options.allrules[errorSelector];
+ var extraData = rule.extraData;
+ var extraDataDynamic = rule.extraDataDynamic;
+ var data = {
+ "fieldId" : field.attr("id"),
+ "fieldValue" : field.val()
+ };
+
+ if (typeof extraData === "object") {
+ $.extend(data, extraData);
+ } else if (typeof extraData === "string") {
+ var tempData = extraData.split("&");
+ for(var i = 0; i < tempData.length; i++) {
+ var values = tempData[i].split("=");
+ if (values[0] && values[0]) {
+ data[values[0]] = values[1];
+ }
+ }
+ }
+
+ if (extraDataDynamic) {
+ var tmpData = [];
+ var domIds = String(extraDataDynamic).split(",");
+ for (var i = 0; i < domIds.length; i++) {
+ var id = domIds[i];
+ if ($(id).length) {
+ var inputValue = field.closest("form, .validationEngineContainer").find(id).val();
+ var keyValue = id.replace('#', '') + '=' + escape(inputValue);
+ data[id.replace('#', '')] = inputValue;
+ }
+ }
+ }
+
+ // If a field change event triggered this we want to clear the cache for this ID
+ if (options.eventTrigger == "field") {
+ delete(options.ajaxValidCache[field.attr("id")]);
+ }
+
+ // If there is an error or if the the field is already validated, do not re-execute AJAX
+ if (!options.isError && !methods._checkAjaxFieldStatus(field.attr("id"), options)) {
+ $.ajax({
+ type: options.ajaxFormValidationMethod,
+ url: rule.url,
+ cache: false,
+ dataType: "json",
+ data: data,
+ field: field,
+ rule: rule,
+ methods: methods,
+ options: options,
+ beforeSend: function() {},
+ error: function(data, transport) {
+ if (options.onFailure) {
+ options.onFailure(data, transport);
+ } else {
+ methods._ajaxError(data, transport);
+ }
+ },
+ success: function(json) {
+
+ // asynchronously called on success, data is the json answer from the server
+ var errorFieldId = json[0];
+ //var errorField = $($("#" + errorFieldId)[0]);
+ var errorField = $("#"+ errorFieldId).eq(0);
+
+ // make sure we found the element
+ if (errorField.length == 1) {
+ var status = json[1];
+ // read the optional msg from the server
+ var msg = json[2];
+ if (!status) {
+ // Houston we got a problem - display an red prompt
+ options.ajaxValidCache[errorFieldId] = false;
+ options.isError = true;
+
+ // resolve the msg prompt
+ if(msg) {
+ if (options.allrules[msg]) {
+ var txt = options.allrules[msg].alertText;
+ if (txt) {
+ msg = txt;
+ }
+ }
+ }
+ else
+ msg = rule.alertText;
+
+ if (options.showPrompts) methods._showPrompt(errorField, msg, "", true, options);
+ } else {
+ options.ajaxValidCache[errorFieldId] = true;
+
+ // resolves the msg prompt
+ if(msg) {
+ if (options.allrules[msg]) {
+ var txt = options.allrules[msg].alertTextOk;
+ if (txt) {
+ msg = txt;
+ }
+ }
+ }
+ else
+ msg = rule.alertTextOk;
+
+ if (options.showPrompts) {
+ // see if we should display a green prompt
+ if (msg)
+ methods._showPrompt(errorField, msg, "pass", true, options);
+ else
+ methods._closePrompt(errorField);
+ }
+
+ // If a submit form triggered this, we want to re-submit the form
+ if (options.eventTrigger == "submit")
+ field.closest("form").submit();
+ }
+ }
+ errorField.trigger("jqv.field.result", [errorField, options.isError, msg]);
+ }
+ });
+
+ return rule.alertTextLoad;
+ }
+ },
+ /**
+ * Common method to handle ajax errors
+ *
+ * @param {Object} data
+ * @param {Object} transport
+ */
+ _ajaxError: function(data, transport) {
+ if(data.status == 0 && transport == null)
+ alert("The page is not served from a server! ajax call failed");
+ else if(typeof console != "undefined")
+ console.log("Ajax error: " + data.status + " " + transport);
+ },
+ /**
+ * date -> string
+ *
+ * @param {Object} date
+ */
+ _dateToString: function(date) {
+ return date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate();
+ },
+ /**
+ * Parses an ISO date
+ * @param {String} d
+ */
+ _parseDate: function(d) {
+
+ var dateParts = d.split("-");
+ if(dateParts==d)
+ dateParts = d.split("/");
+ if(dateParts==d) {
+ dateParts = d.split(".");
+ return new Date(dateParts[2], (dateParts[1] - 1), dateParts[0]);
+ }
+ return new Date(dateParts[0], (dateParts[1] - 1) ,dateParts[2]);
+ },
+ /**
+ * Builds or updates a prompt with the given information
+ *
+ * @param {jqObject} field
+ * @param {String} promptText html text to display type
+ * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
+ * @param {boolean} ajaxed - use to mark fields than being validated with ajax
+ * @param {Map} options user options
+ */
+ _showPrompt: function(field, promptText, type, ajaxed, options, ajaxform) {
+ //Check if we need to adjust what element to show the prompt on
+ if(field.data('jqv-prompt-at') instanceof jQuery ){
+ field = field.data('jqv-prompt-at');
+ } else if(field.data('jqv-prompt-at')) {
+ field = $(field.data('jqv-prompt-at'));
+ }
+
+ var prompt = methods._getPrompt(field);
+ // The ajax submit errors are not see has an error in the form,
+ // When the form errors are returned, the engine see 2 bubbles, but those are ebing closed by the engine at the same time
+ // Because no error was found befor submitting
+ if(ajaxform) prompt = false;
+ // Check that there is indded text
+ if($.trim(promptText)){
+ if (prompt)
+ methods._updatePrompt(field, prompt, promptText, type, ajaxed, options);
+ else
+ methods._buildPrompt(field, promptText, type, ajaxed, options);
+ }
+ },
+ /**
+ * Builds and shades a prompt for the given field.
+ *
+ * @param {jqObject} field
+ * @param {String} promptText html text to display type
+ * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
+ * @param {boolean} ajaxed - use to mark fields than being validated with ajax
+ * @param {Map} options user options
+ */
+ _buildPrompt: function(field, promptText, type, ajaxed, options) {
+
+ // create the prompt
+ var prompt = $('<div>');
+ prompt.addClass(methods._getClassName(field.attr("id")) + "formError");
+ // add a class name to identify the parent form of the prompt
+ prompt.addClass("parentForm"+methods._getClassName(field.closest('form, .validationEngineContainer').attr("id")));
+ prompt.addClass("formError");
+
+ switch (type) {
+ case "pass":
+ prompt.addClass("greenPopup");
+ break;
+ case "load":
+ prompt.addClass("blackPopup");
+ break;
+ default:
+ /* it has error */
+ //alert("unknown popup type:"+type);
+ }
+ if (ajaxed)
+ prompt.addClass("ajaxed");
+
+ // create the prompt content
+ var promptContent = $('<div>').addClass("formErrorContent").html(promptText).appendTo(prompt);
+
+ // determine position type
+ var positionType=field.data("promptPosition") || options.promptPosition;
+
+ // create the css arrow pointing at the field
+ // note that there is no triangle on max-checkbox and radio
+ if (options.showArrow) {
+ var arrow = $('<div>').addClass("formErrorArrow");
+
+ //prompt positioning adjustment support. Usage: positionType:Xshift,Yshift (for ex.: bottomLeft:+20 or bottomLeft:-20,+10)
+ if (typeof(positionType)=='string')
+ {
+ var pos=positionType.indexOf(":");
+ if(pos!=-1)
+ positionType=positionType.substring(0,pos);
+ }
+
+ switch (positionType) {
+ case "bottomLeft":
+ case "bottomRight":
+ prompt.find(".formErrorContent").before(arrow);
+ arrow.addClass("formErrorArrowBottom").html('<div class="line1"><!-- --></div><div class="line2"><!-- --></div><div class="line3"><!-- --></div><div class="line4"><!-- --></div><div class="line5"><!-- --></div><div class="line6"><!-- --></div><div class="line7"><!-- --></div><div class="line8"><!-- --></div><div class="line9"><!-- --></div><div class="line10"><!-- --></div>');
+ break;
+ case "topLeft":
+ case "topRight":
+ arrow.html('<div class="line10"><!-- --></div><div class="line9"><!-- --></div><div class="line8"><!-- --></div><div class="line7"><!-- --></div><div class="line6"><!-- --></div><div class="line5"><!-- --></div><div class="line4"><!-- --></div><div class="line3"><!-- --></div><div class="line2"><!-- --></div><div class="line1"><!-- --></div>');
+ prompt.append(arrow);
+ break;
+ }
+ }
+ // Add custom prompt class
+ if (options.addPromptClass)
+ prompt.addClass(options.addPromptClass);
+
+ // Add custom prompt class defined in element
+ var requiredOverride = field.attr('data-required-class');
+ if(requiredOverride !== undefined) {
+ prompt.addClass(requiredOverride);
+ } else {
+ if(options.prettySelect) {
+ if($('#' + field.attr('id')).next().is('select')) {
+ var prettyOverrideClass = $('#' + field.attr('id').substr(options.usePrefix.length).substring(options.useSuffix.length)).attr('data-required-class');
+ if(prettyOverrideClass !== undefined) {
+ prompt.addClass(prettyOverrideClass);
+ }
+ }
+ }
+ }
+
+ prompt.css({
+ "opacity": 0
+ });
+ if(positionType === 'inline') {
+ prompt.addClass("inline");
+ if(typeof field.attr('data-prompt-target') !== 'undefined' && $('#'+field.attr('data-prompt-target')).length > 0) {
+ prompt.appendTo($('#'+field.attr('data-prompt-target')));
+ } else {
+ field.after(prompt);
+ }
+ } else {
+ field.before(prompt);
+ }
+
+ var pos = methods._calculatePosition(field, prompt, options);
+ prompt.css({
+ 'position': positionType === 'inline' ? 'relative' : 'absolute',
+ "top": pos.callerTopPosition,
+ "left": pos.callerleftPosition,
+ "marginTop": pos.marginTopSize,
+ "opacity": 0
+ }).data("callerField", field);
+
+
+ if (options.autoHidePrompt) {
+ setTimeout(function(){
+ prompt.animate({
+ "opacity": 0
+ },function(){
+ prompt.closest('.formErrorOuter').remove();
+ prompt.remove();
+ });
+ }, options.autoHideDelay);
+ }
+ return prompt.animate({
+ "opacity": 0.87
+ });
+ },
+ /**
+ * Updates the prompt text field - the field for which the prompt
+ * @param {jqObject} field
+ * @param {String} promptText html text to display type
+ * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red)
+ * @param {boolean} ajaxed - use to mark fields than being validated with ajax
+ * @param {Map} options user options
+ */
+ _updatePrompt: function(field, prompt, promptText, type, ajaxed, options, noAnimation) {
+
+ if (prompt) {
+ if (typeof type !== "undefined") {
+ if (type == "pass")
+ prompt.addClass("greenPopup");
+ else
+ prompt.removeClass("greenPopup");
+
+ if (type == "load")
+ prompt.addClass("blackPopup");
+ else
+ prompt.removeClass("blackPopup");
+ }
+ if (ajaxed)
+ prompt.addClass("ajaxed");
+ else
+ prompt.removeClass("ajaxed");
+
+ prompt.find(".formErrorContent").html(promptText);
+
+ var pos = methods._calculatePosition(field, prompt, options);
+ var css = {"top": pos.callerTopPosition,
+ "left": pos.callerleftPosition,
+ "marginTop": pos.marginTopSize};
+
+ if (noAnimation)
+ prompt.css(css);
+ else
+ prompt.animate(css);
+ }
+ },
+ /**
+ * Closes the prompt associated with the given field
+ *
+ * @param {jqObject}
+ * field
+ */
+ _closePrompt: function(field) {
+ var prompt = methods._getPrompt(field);
+ if (prompt)
+ prompt.fadeTo("fast", 0, function() {
+ prompt.parent('.formErrorOuter').remove();
+ prompt.remove();
+ });
+ },
+ closePrompt: function(field) {
+ return methods._closePrompt(field);
+ },
+ /**
+ * Returns the error prompt matching the field if any
+ *
+ * @param {jqObject}
+ * field
+ * @return undefined or the error prompt (jqObject)
+ */
+ _getPrompt: function(field) {
+ var formId = $(field).closest('form, .validationEngineContainer').attr('id');
+ var className = methods._getClassName(field.attr("id")) + "formError";
+ var match = $("." + methods._escapeExpression(className) + '.parentForm' + methods._getClassName(formId))[0];
+ if (match)
+ return $(match);
+ },
+ /**
+ * Returns the escapade classname
+ *
+ * @param {selector}
+ * className
+ */
+ _escapeExpression: function (selector) {
+ return selector.replace(/([#;&,\.\+\*\~':"\!\^$\[\]\(\)=>\|])/g, "\\$1");
+ },
+ /**
+ * returns true if we are in a RTLed document
+ *
+ * @param {jqObject} field
+ */
+ isRTL: function(field)
+ {
+ var $document = $(document);
+ var $body = $('body');
+ var rtl =
+ (field && field.hasClass('rtl')) ||
+ (field && (field.attr('dir') || '').toLowerCase()==='rtl') ||
+ $document.hasClass('rtl') ||
+ ($document.attr('dir') || '').toLowerCase()==='rtl' ||
+ $body.hasClass('rtl') ||
+ ($body.attr('dir') || '').toLowerCase()==='rtl';
+ return Boolean(rtl);
+ },
+ /**
+ * Calculates prompt position
+ *
+ * @param {jqObject}
+ * field
+ * @param {jqObject}
+ * the prompt
+ * @param {Map}
+ * options
+ * @return positions
+ */
+ _calculatePosition: function (field, promptElmt, options) {
+
+ var promptTopPosition, promptleftPosition, marginTopSize;
+ var fieldWidth = field.width();
+ var fieldLeft = field.position().left;
+ var fieldTop = field.position().top;
+ var fieldHeight = field.height();
+ var promptHeight = promptElmt.height();
+
+
+ // is the form contained in an overflown container?
+ promptTopPosition = promptleftPosition = 0;
+ // compensation for the arrow
+ marginTopSize = -promptHeight;
+
+
+ //prompt positioning adjustment support
+ //now you can adjust prompt position
+ //usage: positionType:Xshift,Yshift
+ //for example:
+ // bottomLeft:+20 means bottomLeft position shifted by 20 pixels right horizontally
+ // topRight:20, -15 means topRight position shifted by 20 pixels to right and 15 pixels to top
+ //You can use +pixels, - pixels. If no sign is provided than + is default.
+ var positionType=field.data("promptPosition") || options.promptPosition;
+ var shift1="";
+ var shift2="";
+ var shiftX=0;
+ var shiftY=0;
+ if (typeof(positionType)=='string') {
+ //do we have any position adjustments ?
+ if (positionType.indexOf(":")!=-1) {
+ shift1=positionType.substring(positionType.indexOf(":")+1);
+ positionType=positionType.substring(0,positionType.indexOf(":"));
+
+ //if any advanced positioning will be needed (percents or something else) - parser should be added here
+ //for now we use simple parseInt()
+
+ //do we have second parameter?
+ if (shift1.indexOf(",") !=-1) {
+ shift2=shift1.substring(shift1.indexOf(",") +1);
+ shift1=shift1.substring(0,shift1.indexOf(","));
+ shiftY=parseInt(shift2);
+ if (isNaN(shiftY)) shiftY=0;
+ };
+
+ shiftX=parseInt(shift1);
+ if (isNaN(shift1)) shift1=0;
+
+ };
+ };
+
+
+ switch (positionType) {
+ default:
+ case "topRight":
+ promptleftPosition += fieldLeft + fieldWidth - 30;
+ promptTopPosition += fieldTop;
+ break;
+
+ case "topLeft":
+ promptTopPosition += fieldTop;
+ promptleftPosition += fieldLeft;
+ break;
+
+ case "centerRight":
+ promptTopPosition = fieldTop+4;
+ marginTopSize = 0;
+ promptleftPosition= fieldLeft + field.outerWidth(true)+5;
+ break;
+ case "centerLeft":
+ promptleftPosition = fieldLeft - (promptElmt.width() + 2);
+ promptTopPosition = fieldTop+4;
+ marginTopSize = 0;
+
+ break;
+
+ case "bottomLeft":
+ promptTopPosition = fieldTop + field.height() + 5;
+ marginTopSize = 0;
+ promptleftPosition = fieldLeft;
+ break;
+ case "bottomRight":
+ promptleftPosition = fieldLeft + fieldWidth - 30;
+ promptTopPosition = fieldTop + field.height() + 5;
+ marginTopSize = 0;
+ break;
+ case "inline":
+ promptleftPosition = 0;
+ promptTopPosition = 0;
+ marginTopSize = 0;
+ };
+
+
+
+ //apply adjusments if any
+ promptleftPosition += shiftX;
+ promptTopPosition += shiftY;
+
+ return {
+ "callerTopPosition": promptTopPosition + "px",
+ "callerleftPosition": promptleftPosition + "px",
+ "marginTopSize": marginTopSize + "px"
+ };
+ },
+ /**
+ * Saves the user options and variables in the form.data
+ *
+ * @param {jqObject}
+ * form - the form where the user option should be saved
+ * @param {Map}
+ * options - the user options
+ * @return the user options (extended from the defaults)
+ */
+ _saveOptions: function(form, options) {
+
+ // is there a language localisation ?
+ if ($.validationEngineLanguage)
+ var allRules = $.validationEngineLanguage.allRules;
+ else
+ $.error("jQuery.validationEngine rules are not loaded, plz add localization files to the page");
+ // --- Internals DO NOT TOUCH or OVERLOAD ---
+ // validation rules and i18
+ $.validationEngine.defaults.allrules = allRules;
+
+ var userOptions = $.extend(true,{},$.validationEngine.defaults,options);
+
+ form.data('jqv', userOptions);
+ return userOptions;
+ },
+
+ /**
+ * Removes forbidden characters from class name
+ * @param {String} className
+ */
+ _getClassName: function(className) {
+ if(className)
+ return className.replace(/:/g, "_").replace(/\./g, "_");
+ },
+ /**
+ * Escape special character for jQuery selector
+ * http://totaldev.com/content/escaping-characters-get-valid-jquery-id
+ * @param {String} selector
+ */
+ _jqSelector: function(str){
+ return str.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1');
+ },
+ /**
+ * Conditionally required field
+ *
+ * @param {jqObject} field
+ * @param {Array[String]} rules
+ * @param {int} i rules index
+ * @param {Map}
+ * user options
+ * @return an error string if validation failed
+ */
+ _condRequired: function(field, rules, i, options) {
+ var idx, dependingField;
+
+ for(idx = (i + 1); idx < rules.length; idx++) {
+ dependingField = jQuery("#" + rules[idx]).first();
+
+ /* Use _required for determining wether dependingField has a value.
+ * There is logic there for handling all field types, and default value; so we won't replicate that here
+ * Indicate this special use by setting the last parameter to true so we only validate the dependingField on chackboxes and radio buttons (#462)
+ */
+ if (dependingField.length && methods._required(dependingField, ["required"], 0, options, true) == undefined) {
+ /* We now know any of the depending fields has a value,
+ * so we can validate this field as per normal required code
+ */
+ return methods._required(field, ["required"], 0, options);
+ }
+ }
+ },
+
+ _submitButtonClick: function(event) {
+ var button = $(this);
+ var form = button.closest('form, .validationEngineContainer');
+ form.data("jqv_submitButton", button.attr("id"));
+ }
+ };
+
+ /**
+ * Plugin entry point.
+ * You may pass an action as a parameter or a list of options.
+ * if none, the init and attach methods are being called.
+ * Remember: if you pass options, the attached method is NOT called automatically
+ *
+ * @param {String}
+ * method (optional) action
+ */
+ $.fn.validationEngine = function(method) {
+
+ var form = $(this);
+ if(!form[0]) return form; // stop here if the form does not exist
+
+ if (typeof(method) == 'string' && method.charAt(0) != '_' && methods[method]) {
+
+ // make sure init is called once
+ if(method != "showPrompt" && method != "hide" && method != "hideAll")
+ methods.init.apply(form);
+
+ return methods[method].apply(form, Array.prototype.slice.call(arguments, 1));
+ } else if (typeof method == 'object' || !method) {
+
+ // default constructor with or without arguments
+ methods.init.apply(form, arguments);
+ return methods.attach.apply(form);
+ } else {
+ $.error('Method ' + method + ' does not exist in jQuery.validationEngine');
+ }
+ };
+
+
+
+ // LEAK GLOBAL OPTIONS
+ $.validationEngine= {fieldIdCounter: 0,defaults:{
+
+ // Name of the event triggering field validation
+ validationEventTrigger: "blur",
+ // Automatically scroll viewport to the first error
+ scroll: true,
+ // Focus on the first input
+ focusFirstField:true,
+ // Show prompts, set to false to disable prompts
+ showPrompts: true,
+ // Should we attempt to validate non-visible input fields contained in the form? (Useful in cases of tabbed containers, e.g. jQuery-UI tabs)
+ validateNonVisibleFields: false,
+ // Opening box position, possible locations are: topLeft,
+ // topRight, bottomLeft, centerRight, bottomRight, inline
+ // inline gets inserted after the validated field or into an element specified in data-prompt-target
+ promptPosition: "topRight",
+ bindMethod:"bind",
+ // internal, automatically set to true when it parse a _ajax rule
+ inlineAjax: false,
+ // if set to true, the form data is sent asynchronously via ajax to the form.action url (get)
+ ajaxFormValidation: false,
+ // The url to send the submit ajax validation (default to action)
+ ajaxFormValidationURL: false,
+ // HTTP method used for ajax validation
+ ajaxFormValidationMethod: 'get',
+ // Ajax form validation callback method: boolean onComplete(form, status, errors, options)
+ // retuns false if the form.submit event needs to be canceled.
+ onAjaxFormComplete: $.noop,
+ // called right before the ajax call, may return false to cancel
+ onBeforeAjaxFormValidation: $.noop,
+ // Stops form from submitting and execute function assiciated with it
+ onValidationComplete: false,
+
+ // Used when you have a form fields too close and the errors messages are on top of other disturbing viewing messages
+ doNotShowAllErrosOnSubmit: false,
+ // Object where you store custom messages to override the default error messages
+ custom_error_messages:{},
+ // true if you want to vind the input fields
+ binded: true,
+ // set to true, when the prompt arrow needs to be displayed
+ showArrow: true,
+ // did one of the validation fail ? kept global to stop further ajax validations
+ isError: false,
+ // Limit how many displayed errors a field can have
+ maxErrorsPerField: false,
+
+ // Caches field validation status, typically only bad status are created.
+ // the array is used during ajax form validation to detect issues early and prevent an expensive submit
+ ajaxValidCache: {},
+ // Auto update prompt position after window resize
+ autoPositionUpdate: false,
+
+ InvalidFields: [],
+ onFieldSuccess: false,
+ onFieldFailure: false,
+ onSuccess: false,
+ onFailure: false,
+ validateAttribute: "class",
+ addSuccessCssClassToField: "",
+ addFailureCssClassToField: "",
+
+ // Auto-hide prompt
+ autoHidePrompt: false,
+ // Delay before auto-hide
+ autoHideDelay: 10000,
+ // Fade out duration while hiding the validations
+ fadeDuration: 0.3,
+ // Use Prettify select library
+ prettySelect: false,
+ // Add css class on prompt
+ addPromptClass : "",
+ // Custom ID uses prefix
+ usePrefix: "",
+ // Custom ID uses suffix
+ useSuffix: "",
+ // Only show one message per error prompt
+ showOneMessage: false
+ }};
+ $(function(){$.validationEngine.defaults.promptPosition = methods.isRTL()?'topLeft':"topRight"});
+})(jQuery);
+
+
diff --git a/views/js/mce_plugin.js b/views/js/mce_plugin.js
new file mode 100644
index 0000000..ed5289d
--- /dev/null
+++ b/views/js/mce_plugin.js
@@ -0,0 +1,45 @@
+(function() {
+
+ tinymce.create('tinymce.plugins.wpsgPlugin', {
+
+ init : function(ed, url) {
+
+ ed.addCommand('mcewpsg', function() {
+ ed.windowManager.open({
+ file : 'admin.php?page=wpsg-Produkt&action=select&noheader=1',
+ width : 350,
+ height : 235,
+ inline : 1
+ }, {
+ plugin_url : url
+ });
+ });
+
+ ed.addButton('wpsg', {
+ title : 'Produkt aus dem Produktkatalog einfügen',
+ cmd : 'mcewpsg',
+ image : url + '/../gfx/basket_select.png'
+ });
+
+ ed.onNodeChange.add(function(ed, cm, n) {
+ cm.setActive('wpsg', n.nodeName == 'IMG');
+ });
+ },
+
+ createControl : function(n, cm) {
+ return null;
+ },
+
+ getInfo : function() {
+ return {
+ longname : 'wpShopGermany Produktauswahl',
+ author : 'maennchen1.de',
+ authorurl : 'http://maennchen1.de',
+ version : "3.0"
+ };
+ }
+ });
+
+ tinymce.PluginManager.add('wpsg', tinymce.plugins.wpsgPlugin);
+
+})();
diff --git a/views/js/wpsg_staffel.js b/views/js/wpsg_staffel.js
new file mode 100644
index 0000000..87a8ffa
--- /dev/null
+++ b/views/js/wpsg_staffel.js
@@ -0,0 +1,117 @@
+
+ (function(jQuery) {
+
+ jQuery.fn.wpsgInputStaffel = function(options) {
+
+ if (options == 'close')
+ {
+
+ jQuery("#wpsg_staffel_dialog").dialog('close');
+ return;
+
+ }
+
+ var settings = jQuery.extend({}, jQuery.fn.wpsgInputStaffel.defaults, options);
+ var field_id = this.attr("id");
+
+ var methods = {
+ renderTable: function() {
+
+ var strHTML = '<table style="width:100%;" borderspacing="0" cellpadding="0">';
+
+ arStaffelung = Array();
+ if (arStaffelung.length > 0)
+ {
+
+ for (var i = 0; i < arStaffelung.length; i ++)
+ {
+
+ var arData = arStaffelung[i];
+
+ strHTML += '<tr class="row' + i + '">';
+ strHTML += '<td style="width:50px;"></td>';
+
+ if (arData[0] == 0 || arStaffelung.length <= 1)
+ strHTML += '<td style="width:150px;">ab <input style="background:transparent; margin-right:5px; width:50px;" class="key" type="text" value="0" readonly="readonly" />' + settings.currency + '</td>';
+ else
+ strHTML += '<td style="width:150px;">ab <input onblur="arStaffelung[' + i + '][0] = jQuery(this).val(); wpsg_updateStaffelung();" style="margin-right:5px; width:50px;" class="key" type="text" value="' + arData[0] + '" />' + settings.currency + '</td>';
+
+ strHTML += '<td style="width:150px;"><input onblur="arStaffelung[' + i + '][1] = jQuery(this).val(); wpsg_updateStaffelung();" style="width:50px; margin-right:5px;" class="value" type="text" value="' + arData[1] + '" />' + settings.currency + '</td>';
+
+ strHTML += '<td style="text-align:right;"><input style="width:100px;" class="button" type="button" value="Entfernen" onclick="wpsg_delStaffelung(\'\', ' + i + ');" /></td>';
+ strHTML += '</tr>';
+
+ }
+
+ }
+
+ strHTML += '<tr><td colspan="4">&nbsp;</td></tr>';
+
+ strHTML += '<tr class="row_neu">';
+ strHTML += '<td>Neu:</td>';
+
+ if (arStaffelung.length == 0)
+ strHTML += '<td>ab <input style="background:transparent; margin-right:5px; width:50px;" class="key" type="text" value="0" readonly="readonly" />' + settings.currency + '</td>';
+ else
+ strHTML += '<td>ab <input style="width:50px; margin-right:5px;" class="key" type="text" value="" />' + settings.currency + '</td>';
+
+ strHTML += '<td><input style="width:50px; margin-right:5px;" class="value" type="text" value="" />' + settings.currency + '</td>';
+ strHTML += '<td style="text-align:right;"><input style="width:100px;" class="button" type="button" value="Hinzufügen" onclick="return wpsg_addStaffelung(\'\');" /></td>';
+ strHTML += '</tr>';
+
+ strHTML += '<tr><td colspan="4">&nbsp;</td></tr>';
+ strHTML += '<tr><td colspan="4" id="wpsg_staffelung_debug">&nbsp;</td></tr>';
+
+ strHTML += '<tr>';
+ strHTML += '<td colspan="3">&nbsp;</td>';
+ strHTML += '<td style="text-align:right;"><input style="width:100px;" class="button" type="button" onclick="return jQuery(\'#' + field_id + '\').wpsgInputStaffel(\'close\');" value="Schließen" /></td>';
+ strHTML += '</tr>';
+
+ strHTML += '</table>';
+
+ return strHTML;
+
+ },
+ showDialog: function() {
+
+ var strHTML = '<div id="wpsg_staffel_dialog" style="display:none;">';
+
+ strHTML += '<div style="padding:5px;" id="wpsg_staffel_table">' + methods.renderTable() + '</div>';
+ strHTML += '</div>';
+
+ jQuery('body').append(strHTML);
+
+ jQuery("#wpsg_staffel_dialog").dialog( {
+ 'dialogClass': 'wp-dialog',
+ 'modal': true,
+ 'width': settings.width,
+ 'height': settings.height,
+ 'title': settings.title
+ } );
+
+ }
+ };
+
+ if (this.text().trim() == '')
+ {
+ this.text(wpsg_staffel.empty);
+ }
+
+ this.bind('click', function() {
+
+ var staffelKey = jQuery(this).text().trim();
+ if (staffelKey == wpsg_staffel.empty) staffelKey = '';
+ methods.showDialog.apply();
+
+ } );
+
+ };
+
+ jQuery.fn.wpsgInputStaffel.defaults = {
+ currency: '€',
+ title: wpsg_staffel.title,
+ width: 350,
+ height: 400
+ };
+
+ })(jQuery); \ No newline at end of file