diff options
| author | Daniel Schmitzer <noreply@maennchen1.de> | 2016-01-14 14:55:36 +0000 |
|---|---|---|
| committer | Daniel Schmitzer <noreply@maennchen1.de> | 2016-01-14 14:55:36 +0000 |
| commit | ad405c7045c6e242080ec9d3ce4c9e586b517c4f (patch) | |
| tree | b41905f4d27f3eaaabd5bad3a39f8d3873540b46 /views/js | |
- Testweise 4
git-svn-id: https://[internal]/wordpress/plugins/wpsg4@5261 0d5edaf7-2b12-4e95-93f4-047927463d4b
Diffstat (limited to 'views/js')
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 Binary files differnew file mode 100644 index 0000000..e138d9b --- /dev/null +++ b/views/js/jquery-cluetip-master/images/darrowdown.gif diff --git a/views/js/jquery-cluetip-master/images/darrowleft.gif b/views/js/jquery-cluetip-master/images/darrowleft.gif Binary files differnew file mode 100644 index 0000000..e22d11c --- /dev/null +++ b/views/js/jquery-cluetip-master/images/darrowleft.gif diff --git a/views/js/jquery-cluetip-master/images/darrowright.gif b/views/js/jquery-cluetip-master/images/darrowright.gif Binary files differnew file mode 100644 index 0000000..d36d7e4 --- /dev/null +++ b/views/js/jquery-cluetip-master/images/darrowright.gif diff --git a/views/js/jquery-cluetip-master/images/darrowup.gif b/views/js/jquery-cluetip-master/images/darrowup.gif Binary files differnew file mode 100644 index 0000000..fd74057 --- /dev/null +++ b/views/js/jquery-cluetip-master/images/darrowup.gif 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,'&').replace(/>/g,'>').replace(/</g,'<'); + } + + 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 && ' ', + 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,"&").replace(/>/g,">").replace(/</g,"<")),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&&" ",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(/ | /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(/ | /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"> </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"> </td></tr>';
+ strHTML += '<tr><td colspan="4" id="wpsg_staffelung_debug"> </td></tr>';
+
+ strHTML += '<tr>';
+ strHTML += '<td colspan="3"> </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 |
