diff --git a/lib/hashmask/demo.html b/lib/hashmask/demo.html new file mode 100644 index 0000000..645756d --- /dev/null +++ b/lib/hashmask/demo.html @@ -0,0 +1,61 @@ + + + + + HashMask - Demo + + + + + + + + + +

Login to HashMask Demo

+ +
+

+ + +

+

+ + +

+

+ +

+
+ +
+ + + + diff --git a/lib/hashmask/jquery.hashmask.js b/lib/hashmask/jquery.hashmask.js new file mode 100644 index 0000000..b248427 --- /dev/null +++ b/lib/hashmask/jquery.hashmask.js @@ -0,0 +1,105 @@ +/** + * HashMask - a new approach to password masking security + * + * REQUIRES: + * jquery.sparkline.js + * a one way hashing method, currently sha1, provided by jquery.sha1.js + * + * @author Chris Dary + * @copyright Copyright (c) 2009 {@link http://arc90.com Arc90 Inc.} + * @license http://www.opensource.org/licenses/bsd-license.php +**/ + +(function($) { + $.hashmask = { + settings: { + hashFunction: $.sha1, + useColorAsHint: true, + sparkInterval: 500, + sparklineOptions: { + width: '100px', + height: 'auto', + lineColor: '#69C', + spotColor: false, + minSpotColor: false, + maxSpotColor: false + } + } + }; + + $.fn.hashmask = function(settings) { + /** + * @var object Contains an associative array of all settings for hashmask. + **/ + settings = $.extend({}, $.hashmask.settings, settings); + + /** + * Add hashmask hint to an input. The input must be of type password. + * + * @param selector string A jquery capable selector, as defined here: http://docs.jquery.com/Selectors + * @return void + **/ + return this.each(function() { + var $sparkline, sparkTimeout, i; + var $this = $(this); + + if(!$this.is('input[type="password"]')) + { + throw new Error('HashMask may only be used on inputs of type password.'); + } + + $sparkline = $('
'); + $sparkline.css({ + position: 'absolute', + top: $this.offset().top + parseInt($this.css('borderTopWidth'), 10), + left: $this.offset().left + $this.outerWidth() - parseInt($this.css('borderRightWidth'), 10) - parseInt(settings.sparklineOptions.width, 10), + width: settings.sparklineOptions.width, + height: $this.outerHeight() + }); + $sparkline.click(function() { $this.focus(); }); + + $this.parents('form').append($sparkline); + + $this.keyup(function(e) { + window.clearTimeout(sparkTimeout); + + var inputVal = $this.val(); + if(inputVal === "") + { + $sparkline.html(""); + return; + } + + var inputHash = settings.hashFunction($this.val()).substr(0,20); + var inputHexArr = inputHash.split(''); + var inputDecArr = []; + + /* Convert our hex string array into decimal numbers for sparkline consumption */ + for(i=0; i < inputHexArr.length; i++) + { + inputDecArr.push(parseInt(inputHexArr[i], 16)); + } + + var fillColor; + if(settings.useColorAsHint) + { + fillColor = '#' + inputHash.substr(0,6); + } + else + { + fillColor = settings.sparklineOptions.fillColor + } + + sparkTimeout = window.setTimeout(function() { + $sparkline.sparkline(inputDecArr, $.extend( settings.sparklineOptions, { + height: (settings.sparklineOptions.height == 'auto' ? $this.outerHeight() - parseInt($this.css('borderBottomWidth'), 10) - parseInt($this.css('borderTopWidth'), 10): settings.sparklineOptions.height), + fillColor: fillColor + })); + }, settings.sparkInterval); + + }); + + }); + }; + +})(jQuery); diff --git a/lib/hashmask/jquery.sha1.js b/lib/hashmask/jquery.sha1.js new file mode 100644 index 0000000..40c5725 --- /dev/null +++ b/lib/hashmask/jquery.sha1.js @@ -0,0 +1,170 @@ + +/** + * jQuery SHA1 hash algorithm function + * + * + * Calculate the sha1 hash of a String + * String $.sha1 ( String str ) + * + * + * Calculates the sha1 hash of str using the US Secure Hash Algorithm 1. + * SHA-1 the Secure Hash Algorithm (SHA) was developed by NIST and is specified in the Secure Hash Standard (SHS, FIPS 180). + * This script is used to process variable length message into a fixed-length output using the SHA-1 algorithm. It is fully compatible with UTF-8 encoding. + * If you plan using UTF-8 encoding in your project don't forget to set the page encoding to UTF-8 (Content-Type meta tag). + * This function orginally get from the WebToolkit and rewrite for using as the jQuery plugin. + * + * Example + * Code + * + * $.sha1("I'm Persian."); + * + * Result + * + * "1d302f9dc925d62fc859055999d2052e274513ed" + * + * + * @alias Muhammad Hussein Fattahizadeh < muhammad [AT] semnanweb [DOT] com > + * @link http://www.semnanweb.com/jquery-plugin/sha1.html + * @see http://www.webtoolkit.info/ + * @license http://www.gnu.org/licenses/gpl.html [GNU General Public License] + * @param {jQuery} {sha1:function(string)) + * @return string + */ + +(function($){ + + var rotateLeft = function(lValue, iShiftBits) { + return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits)); + } + + var lsbHex = function(value) { + var string = ""; + var i; + var vh; + var vl; + for(i = 0;i <= 6;i += 2) { + vh = (value>>>(i * 4 + 4))&0x0f; + vl = (value>>>(i*4))&0x0f; + string += vh.toString(16) + vl.toString(16); + } + return string; + }; + + var cvtHex = function(value) { + var string = ""; + var i; + var v; + for(i = 7;i >= 0;i--) { + v = (value>>>(i * 4))&0x0f; + string += v.toString(16); + } + return string; + }; + + var uTF8Encode = function(string) { + string = string.replace(/\x0d\x0a/g, "\x0a"); + var output = ""; + for (var n = 0; n < string.length; n++) { + var c = string.charCodeAt(n); + if (c < 128) { + output += String.fromCharCode(c); + } else if ((c > 127) && (c < 2048)) { + output += String.fromCharCode((c >> 6) | 192); + output += String.fromCharCode((c & 63) | 128); + } else { + output += String.fromCharCode((c >> 12) | 224); + output += String.fromCharCode(((c >> 6) & 63) | 128); + output += String.fromCharCode((c & 63) | 128); + } + } + return output; + }; + + $.extend({ + sha1: function(string) { + var blockstart; + var i, j; + var W = new Array(80); + var H0 = 0x67452301; + var H1 = 0xEFCDAB89; + var H2 = 0x98BADCFE; + var H3 = 0x10325476; + var H4 = 0xC3D2E1F0; + var A, B, C, D, E; + var tempValue; + string = uTF8Encode(string); + var stringLength = string.length; + var wordArray = new Array(); + for(i = 0;i < stringLength - 3;i += 4) { + j = string.charCodeAt(i)<<24 | string.charCodeAt(i + 1)<<16 | string.charCodeAt(i + 2)<<8 | string.charCodeAt(i + 3); + wordArray.push(j); + } + switch(stringLength % 4) { + case 0: + i = 0x080000000; + break; + case 1: + i = string.charCodeAt(stringLength - 1)<<24 | 0x0800000; + break; + case 2: + i = string.charCodeAt(stringLength - 2)<<24 | string.charCodeAt(stringLength - 1)<<16 | 0x08000; + break; + case 3: + i = string.charCodeAt(stringLength - 3)<<24 | string.charCodeAt(stringLength - 2)<<16 | string.charCodeAt(stringLength - 1)<<8 | 0x80; + break; + } + wordArray.push(i); + while((wordArray.length % 16) != 14 ) wordArray.push(0); + wordArray.push(stringLength>>>29); + wordArray.push((stringLength<<3)&0x0ffffffff); + for(blockstart = 0;blockstart < wordArray.length;blockstart += 16) { + for(i = 0;i < 16;i++) W[i] = wordArray[blockstart+i]; + for(i = 16;i <= 79;i++) W[i] = rotateLeft(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); + A = H0; + B = H1; + C = H2; + D = H3; + E = H4; + for(i = 0;i <= 19;i++) { + tempValue = (rotateLeft(A, 5) + ((B&C) | (~B&D)) + E + W[i] + 0x5A827999) & 0x0ffffffff; + E = D; + D = C; + C = rotateLeft(B, 30); + B = A; + A = tempValue; + } + for(i = 20;i <= 39;i++) { + tempValue = (rotateLeft(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff; + E = D; + D = C; + C = rotateLeft(B, 30); + B = A; + A = tempValue; + } + for(i = 40;i <= 59;i++) { + tempValue = (rotateLeft(A, 5) + ((B&C) | (B&D) | (C&D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff; + E = D; + D = C; + C = rotateLeft(B, 30); + B = A; + A = tempValue; + } + for(i = 60;i <= 79;i++) { + tempValue = (rotateLeft(A, 5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff; + E = D; + D = C; + C = rotateLeft(B, 30); + B = A; + A = tempValue; + } + H0 = (H0 + A) & 0x0ffffffff; + H1 = (H1 + B) & 0x0ffffffff; + H2 = (H2 + C) & 0x0ffffffff; + H3 = (H3 + D) & 0x0ffffffff; + H4 = (H4 + E) & 0x0ffffffff; + } + var tempValue = cvtHex(H0) + cvtHex(H1) + cvtHex(H2) + cvtHex(H3) + cvtHex(H4); + return tempValue.toLowerCase(); + } + }); +})(jQuery); \ No newline at end of file diff --git a/lib/hashmask/jquery.sparkline.js b/lib/hashmask/jquery.sparkline.js new file mode 100644 index 0000000..f0fba50 --- /dev/null +++ b/lib/hashmask/jquery.sparkline.js @@ -0,0 +1,936 @@ +/** +* +* jquery.sparkline.js +* +* v1.4.2 +* (c) Splunk, Inc +* Contact: Gareth Watts (gareth@splunk.com) +* http://omnipotent.net/jquery.sparkline/ +* +* Generates inline sparkline charts from data supplied either to the method +* or inline in HTML +* +* Compatible with Internet Explorer 6.0+ and modern browsers equipped with the canvas tag +* (Firefox 2.0+, Safari, Opera, etc) +* +* License: New BSD License +* +* Copyright (c) 2009, Splunk Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* * Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* * Neither the name of Splunk Inc nor the names of its contributors may +* be used to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* +* Usage: +* $(selector).sparkline(values, options) +* +* If values is undefined or set to 'html' then the data values are read from the specified tag: +*

Sparkline: 1,4,6,6,8,5,3,5

+* $('.sparkline').sparkline(); +* There must be no spaces in the enclosed data set +* +* Otherwise values must be an array of numbers +*

Sparkline: This text replaced if the browser is compatible

+* $('#sparkline1').sparkline([1,4,6,6,8,5,3,5]) +* +* For line charts, x values can also be specified: +*

Sparkline: 1:1,2.7:4,3.4:6,5:6,6:8,8.7:5,9:3,10:5

+* $('#sparkline1').sparkline([ [1,1], [2.7,4], [3.4,6], [5,6], [6,8], [8.7,5], [9,3], [10,5] ]) +* +* Supported options: +* lineColor - Color of the line used for the chart +* fillColor - Color used to fill in the chart - Set to '' or false for a transparent chart +* width - Width of the chart - Defaults to 3 times the number of values in pixels +* height - Height of the chart - Defaults to the height of the containing element +* chartRangeMin - Specify the minimum value to use for the range of the chart - Defaults to the minimum value supplied +* chartRangeMax - Specify the maximum value to use for the range of the chart - Defaults to the maximum value supplied +* composite - If true then don't erase any existing chart attached to the tag, but draw +* another chart over the top - Note that width and height are ignored if an +* existing chart is detected. +* +* There are 7 types of sparkline, selected by supplying a "type" option of 'line' (default), +* 'bar', 'tristate', 'bullet', 'discrete', 'pie' or 'box' +* line - Line chart. Options: +* spotColor - Set to '' to not end each line in a circular spot +* minSpotColor - If set, color of spot at minimum value +* maxSpotColor - If set, color of spot at maximum value +* spotRadius - Radius in pixels +* normalRangeMin +* normalRangeMax - If set draws a filled horizontal bar between these two values marking the "normal" +* or expected range of values +* normalRangeColor - Color to use for the above bar +* defaultPixelsPerValue - Defaults to 3 pixels of width for each value in the chart +* +* bar - Bar chart. Options: +* barColor - Color of bars for postive values +* negBarColor - Color of bars for negative values +* barWidth - Width of bars in pixels +* barSpacing - Gap between bars in pixels +* zeroAxis - Centers the y-axis around zero if true +* +* tristate - Charts values of win (>0), lose (<0) or draw (=0) +* posBarColor - Color of win values +* negBarColor - Color of lose values +* zeroBarColor - Color of draw values +* barWidth - Width of bars in pixels +* barSpacing - Gap between bars in pixels +* colorMap - Optional mappnig of values to colors to override the *BarColor values above +* +* discrete - Options: +* lineHeight - Height of each line in pixels - Defaults to 30% of the graph height +* thesholdValue - Values less than this value will be drawn using thresholdColor instead of lineColor +* thresholdColor +* +* bullet - Values for bullet graphs msut be in the order: target, performance, range1, range2, range3, ... +* options: +* targetColor - The color of the vertical target marker +* targetWidth - The width of the target marker in pixels +* performanceColor - The color of the performance measure horizontal bar +* rangeColors - Colors to use for each qualitative range background color +* +* pie - Pie chart. Options: +* sliceColors - An array of colors to use for pie slices +* offset - Angle in degrees to offset the first slice - Try -90 or +90 +* +* box - Box plot. Options: +* raw - Set to true to supply pre-computed plot points as values +* values should be: low_outlier, low_whisker, q1, median, q3, high_whisker, high_outlier +* When set to false you can supply any number of values and the box plot will +* be computed for you. Default is false. +* showOutliers - Set to true (default) to display outliers as circles +* outlierIRQ - Interquartile range used to determine outliers. Default 1.5 +* boxLineColor - Outline color of the box +* boxFillColor - Fill color for the box +* whiskerColor - Line color used for whiskers +* outlierLineColor - Outline color of outlier circles +* outlierFillColor - Fill color of the outlier circles +* spotRadius - Radius of outlier circles +* medianColor - Line color of the median line +* target - Draw a target cross hair at the supplied value (default undefined) +* +* +* +* Examples: +* $('#sparkline1').sparkline(myvalues, { lineColor: '#f00', fillColor: false }); +* $('.barsparks').sparkline('html', { type:'bar', height:'40px', barWidth:5 }); +* $('#tristate').sparkline([1,1,-1,1,0,0,-1], { type:'tristate' }): +* $('#discrete').sparkline([1,3,4,5,5,3,4,5], { type:'discrete' }); +* $('#bullet').sparkline([10,12,12,9,7], { type:'bullet' }); +* $('#pie').sparkline([1,1,2], { type:'pie' }); +*/ + + +(function($) { + + // Provide a cross-browser interface to a few simple drawing primitives + $.fn.simpledraw = function(width, height, use_existing) { + if (use_existing && this[0].vcanvas) return this[0].vcanvas; + if (width==undefined) width=$(this).innerWidth(); + if (height==undefined) height=$(this).innerHeight(); + if ($.browser.hasCanvas) { + return new vcanvas_canvas(width, height, this); + } else if ($.browser.msie) { + return new vcanvas_vml(width, height, this); + } else { + return false; + } + }; + + var pending = []; + + $.fn.sparkline = function(uservalues, options) { + var options = $.extend({ + type : 'line', + lineColor : '#00f', + fillColor : '#cdf', + defaultPixelsPerValue : 3, + width : 'auto', + height : 'auto', + composite : false + }, options ? options : {}); + + return this.each(function() { + var render = function() { + var values = (uservalues=='html' || uservalues==undefined) ? $(this).text().split(',') : uservalues; + + var width = options.width=='auto' ? values.length*options.defaultPixelsPerValue : options.width; + if (options.height == 'auto') { + if (!options.composite || !this.vcanvas) { + // must be a better way to get the line height + var tmp = document.createElement('span'); + tmp.innerHTML = 'a'; + $(this).html(tmp); + height = $(tmp).innerHeight(); + $(tmp).remove(); + } + } else { + height = options.height; + } + + $.fn.sparkline[options.type].call(this, values, options, width, height); + } + // jQuery 1.3.0 completely changed the meaning of :hidden :-/ + if (($(this).html() && $(this).is(':hidden')) || ($.fn.jquery < "1.3.0" && $(this).parents().is(':hidden'))) { + pending.push([this, render]); + } else { + render.call(this); + } + }); + }; + + + $.sparkline_display_visible = function() { + for (var i=pending.length-1; i>=0; i--) { + var el = pending[i][0]; + if ($(el).is(':visible') && !$(el).parents().is(':hidden')) { + pending[i][1].call(el); + pending.splice(i, 1); + } + } + }; + + $.fn.sparkline.line = function(values, options, width, height) { + var options = $.extend({ + spotColor : '#f80', + spotRadius : 1.5, + minSpotColor : '#f80', + maxSpotColor : '#f80', + normalRangeMin : undefined, + normalRangeMax : undefined, + normalRangeColor : '#ccc', + chartRangeMin : undefined, + chartRangeMax : undefined + }, options ? options : {}); + + var xvalues = [], yvalues = []; + for (i=0; imaxy) + maxy = options.normalRangeMax; + } + if (options.chartRangeMin!=undefined && options.chartRangeMinmaxy) { + maxy = options.chartRangeMax; + } + var rangex = maxx-minx == 0 ? 1 : maxx-minx; + var rangey = maxy-miny == 0 ? 1 : maxy-miny; + var vl = yvalues.length-1; + + if (vl<1) { + this.innerHTML = ''; + return; + } + + var target = $(this).simpledraw(width, height, options.composite); + if (target) { + var canvas_width = target.pixel_width; + var canvas_height = target.pixel_height; + var canvas_top = 0; + var canvas_left = 0; + + if (options.spotRadius && (canvas_width < (options.spotRadius*4) || canvas_height < (options.spotRadius*4))) { + options.spotRadius = 0; + } + if (options.spotRadius) { + // adjust the canvas size as required so that spots will fit + if (options.minSpotColor || (options.spotColor && yvalues[vl]==miny)) + canvas_height -= Math.ceil(options.spotRadius); + if (options.maxSpotColor || (options.spotColor && yvalues[vl]==maxy)) { + canvas_height -= Math.ceil(options.spotRadius); + canvas_top += Math.ceil(options.spotRadius); + } + if (options.minSpotColor || options.maxSpotColor && (yvalues[0]==miny || yvalues[0]==maxy)) { + canvas_left += Math.ceil(options.spotRadius); + canvas_width -= Math.ceil(options.spotRadius); + } + if (options.spotColor || (options.minSpotColor || options.maxSpotColor && (yvalues[vl]==miny||yvalues[vl]==maxy))) + canvas_width -= Math.ceil(options.spotRadius); + } + + + canvas_height--; + if (options.normalRangeMin!=undefined) { + var ytop = canvas_top+Math.round(canvas_height-(canvas_height*((options.normalRangeMax-miny)/rangey))); + var height = Math.round((canvas_height*(options.normalRangeMax-options.normalRangeMin))/rangey); + target.drawRect(canvas_left, ytop, canvas_width, height, undefined, options.normalRangeColor); + } + + var path = [ [canvas_left, canvas_top+canvas_height] ]; + for(var i=0; imax) { + max = options.chartRangeMax; + } + if (options.zeroAxis == undefined) options.zeroAxis = min<0; + var range = max-min == 0 ? 1 : max-min; + + var target = $(this).simpledraw(width, height); + if (target) { + var canvas_width = target.pixel_width; + var canvas_height = target.pixel_height; + var yzero = min<0 && options.zeroAxis ? canvas_height-Math.round(canvas_height * (Math.abs(min)/range))-1 : canvas_height-1; + + for(var i=0; i 0) { + var y = 0; + var height = half_height-1; + var color = options.posBarColor; + } else { + var y = half_height-1; + var height = 2; + var color = options.zeroBarColor; + } + if (options.colorMap[values[i]]) { + color = options.colorMap[values[i]]; + } + target.drawRect(x, y, options.barWidth-1, height-1, color, color); + } + } else { + // Remove the tag contents if sparklines aren't supported + this.innerHTML = ''; + } + }; + + $.fn.sparkline.discrete = function(values, options, width, height) { + values = $.map(values, Number); + var options = $.extend({ + lineHeight: 'auto', + thresholdColor: undefined, + thresholdValue : 0, + chartRangeMax: undefined, + chartRangeMin: undefined + }, options); + + width = options.width=='auto' ? values.length*2 : width; + var interval = Math.floor(width / values.length); + + var target = $(this).simpledraw(width, height); + if (target) { + var canvas_width = target.pixel_width; + var canvas_height = target.pixel_height; + var line_height = options.lineHeight == 'auto' ? Math.round(canvas_height * 0.3) : options.lineHeight; + var pheight = canvas_height - line_height; + var min = Math.min.apply(Math, values); + var max = Math.max.apply(Math, values); + if (options.chartRangeMin!=undefined && options.chartRangeMinmax) { + max = options.chartRangeMax; + } + var range = max-min; + + for(var i=0; i1) { + var canvas_width = target.pixel_width-Math.ceil(options.targetWidth/2); + var canvas_height = target.pixel_height; + + var min = Math.min.apply(Math, values); + var max = Math.max.apply(Math, values); + if (options.base == undefined) { + var min = min < 0 ? min : 0; + } else { + min = options.base; + } + var range = max-min; + + // draw range values + for(i=2; i1) { + var canvas_width = target.pixel_width; + var canvas_height = target.pixel_height; + + var radius = Math.floor(Math.min(canvas_width, canvas_height)/2); + var total = 0; + for(var i=0; i 0) { // avoid divide by zero + end = next + (circle*(values[i]/total)); + } + target.drawPieSlice(radius, radius, radius, start, end, undefined, options.sliceColors[i % options.sliceColors.length]); + next = end; + } + } + }; + + function quartile(values, q) { + if (q==2) { + var vl2 = Math.floor(values.length/2); + return values.length % 2 ? values[vl2] : (values[vl2]+values[vl2+1])/2; + } else { + var vl4 = Math.floor(values.length/4); + return values.length % 2 ? (values[vl4*q]+values[vl4*q+1])/2 : values[vl4*q]; + } + }; + + $.fn.sparkline.box = function(values, options, width, height) { + values = $.map(values, Number); + var options = $.extend({ + raw: false, + boxLineColor: 'black', + boxFillColor: '#cdf', + whiskerColor: 'black', + outlierLineColor: '#333', + outlierFillColor: 'white', + medianColor: 'red', + showOutliers: true, + outlierIQR: 1.5, + spotRadius: 1.5, + target: undefined, + targetColor: '#4a2', + chartRangeMax: undefined, + chartRangeMin: undefined + }, options); + + width = options.width=='auto' ? '4.0em' : width; + + minvalue = options.chartRangeMin==undefined ? Math.min.apply(Math, values) : options.chartRangeMin; + maxvalue = options.chartRangeMax==undefined ? Math.max.apply(Math, values) : options.chartRangeMax; + var target = $(this).simpledraw(width, height); + if (target && values.length>1) { + var canvas_width = target.pixel_width; + var canvas_height = target.pixel_height; + if (options.raw) { + if (options.showOutliers && values.length>5) { + var loutlier=values[0], lwhisker=values[1], q1=values[2], q2=values[3], q3=values[4], rwhisker=values[5], routlier=values[6]; + } else { + var lwhisker=values[0], q1=values[1], q2=values[2], q3=values[3], rwhisker=values[4]; + } + } else { + values.sort(function(a, b) { return a-b; }); + var q1 = quartile(values, 1); + var q2 = quartile(values, 2); + var q3 = quartile(values, 3); + var iqr = q3-q1; + if (options.showOutliers) { + var lwhisker=undefined, rwhisker=undefined; + for(var i=0; i q1-(iqr*options.outlierIQR)) + lwhisker = values[i]; + if (values[i] < q3+(iqr*options.outlierIQR)) + rwhisker = values[i]; + } + var loutlier = values[0]; + var routlier = values[values.length-1]; + } else { + var lwhisker = values[0]; + var rwhisker = values[values.length-1]; + } + } + + var unitsize = canvas_width / (maxvalue-minvalue+1); + var canvas_left = 0; + if (options.showOutliers) { + canvas_left = Math.ceil(options.spotRadius); + canvas_width -= 2*Math.ceil(options.spotRadius); + var unitsize = canvas_width / (maxvalue-minvalue+1); + if (loutlier < lwhisker) + target.drawCircle((loutlier-minvalue)*unitsize+canvas_left, canvas_height/2, options.spotRadius, options.outlierLineColor, options.outlierFillColor); + if (routlier > rwhisker) + target.drawCircle((routlier-minvalue)*unitsize+canvas_left, canvas_height/2, options.spotRadius, options.outlierLineColor, options.outlierFillColor); + } + + // box + target.drawRect( + Math.round((q1-minvalue)*unitsize+canvas_left), + Math.round(canvas_height*0.1), + Math.round((q3-q1)*unitsize), + Math.round(canvas_height*0.8), + options.boxLineColor, + options.boxFillColor); + // left whisker + target.drawLine( + Math.round((lwhisker-minvalue)*unitsize+canvas_left), + Math.round(canvas_height/2), + Math.round((q1-minvalue)*unitsize+canvas_left), + Math.round(canvas_height/2), + options.lineColor); + target.drawLine( + Math.round((lwhisker-minvalue)*unitsize+canvas_left), + Math.round(canvas_height/4), + Math.round((lwhisker-minvalue)*unitsize+canvas_left), + Math.round(canvas_height-canvas_height/4), + options.whiskerColor); + // right whisker + target.drawLine(Math.round((rwhisker-minvalue)*unitsize+canvas_left), + Math.round(canvas_height/2), + Math.round((q3-minvalue)*unitsize+canvas_left), + Math.round(canvas_height/2), + options.lineColor); + target.drawLine( + Math.round((rwhisker-minvalue)*unitsize+canvas_left), + Math.round(canvas_height/4), + Math.round((rwhisker-minvalue)*unitsize+canvas_left), + Math.round(canvas_height-canvas_height/4), + options.whiskerColor); + // median line + target.drawLine( + Math.round((q2-minvalue)*unitsize+canvas_left), + Math.round(canvas_height*0.1), + Math.round((q2-minvalue)*unitsize+canvas_left), + Math.round(canvas_height*0.9), + options.medianColor); + if (options.target) { + var size = Math.ceil(options.spotRadius); + target.drawLine( + Math.round((options.target-minvalue)*unitsize+canvas_left), + Math.round((canvas_height/2)-size), + Math.round((options.target-minvalue)*unitsize+canvas_left), + Math.round((canvas_height/2)+size), + options.targetColor); + target.drawLine( + Math.round((options.target-minvalue)*unitsize+canvas_left-size), + Math.round(canvas_height/2), + Math.round((options.target-minvalue)*unitsize+canvas_left+size), + Math.round(canvas_height/2), + options.targetColor); + } + } else { + // Remove the tag contents if sparklines aren't supported + this.innerHTML = ''; + } + }; + + + // IE doesn't provide an indexOf method for arrays :-( + if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function(entry) { + for(var i=0; i'; + this.canvas.insertAdjacentHTML('beforeEnd', groupel); + this.group = $(this.canvas).children()[0]; + }, + + drawShape : function(path, lineColor, fillColor) { + var vpath = []; + for(var i=0; i' + +' '; + this.group.insertAdjacentHTML('beforeEnd', vel); + }, + + drawCircle : function(x, y, radius, lineColor, fillColor) { + x -= radius+1; + y -= radius+1; + var stroke = lineColor == undefined ? ' stroked="false" ' : ' strokeWeight="1" strokeColor="'+lineColor+'" '; + var fill = fillColor == undefined ? ' filled="false"' : ' fillColor="'+fillColor+'" filled="true" '; + var vel = ''; + this.group.insertAdjacentHTML('beforeEnd', vel); + + }, + + drawPieSlice : function(x, y, radius, startAngle, endAngle, lineColor, fillColor) { + if (startAngle == endAngle) { + return; // VML seems to have problem when start angle equals end angle. + } + if ((endAngle - startAngle) == (2*Math.PI)) { + startAngle = 0.0; // VML seems to have a problem when drawing a full circle that doesn't start 0 + endAngle = (2*Math.PI); + } + + var startx = x + Math.round(Math.cos(startAngle) * radius); + var starty = y + Math.round(Math.sin(startAngle) * radius); + var endx = x + Math.round(Math.cos(endAngle) * radius); + var endy = y + Math.round(Math.sin(endAngle) * radius); + + var vpath = [ x-radius, y-radius, x+radius, y+radius, startx, starty, endx, endy ]; + var stroke = lineColor == undefined ? ' stroked="false" ' : ' strokeWeight="1" strokeColor="'+lineColor+'" '; + var fill = fillColor == undefined ? ' filled="false"' : ' fillColor="'+fillColor+'" filled="true" '; + var vel = '' + +' '; + this.group.insertAdjacentHTML('beforeEnd', vel); + }, + + drawRect : function(x, y, width, height, lineColor, fillColor) { + return this.drawShape( [ [x, y], [x, y+height], [x+width, y+height], [x+width, y], [x, y] ], lineColor, fillColor); + } + }); + +})(jQuery); diff --git a/lib/jqbootstrapvalidation/.gitignore b/lib/jqbootstrapvalidation/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/lib/jqbootstrapvalidation/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/lib/jqbootstrapvalidation/LICENSE b/lib/jqbootstrapvalidation/LICENSE new file mode 100644 index 0000000..ad5ddc4 --- /dev/null +++ b/lib/jqbootstrapvalidation/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2012 David Godfrey aka ReactiveRaven + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/lib/jqbootstrapvalidation/README.md b/lib/jqbootstrapvalidation/README.md new file mode 100644 index 0000000..edb16ae --- /dev/null +++ b/lib/jqbootstrapvalidation/README.md @@ -0,0 +1,13 @@ +jqBootstapValidation +==================== + +A JQuery validation framework for bootstrap forms. + +Displays validation errors in `help-block` elements as users type. + +More information is available at http://ReactiveRaven.github.com/jqBootstrapValidation + +Changes +======= + +1.3.2 - Patch for infinite-loop/slow-script-warning in IE8 - thanks to @dangerbell diff --git a/lib/jqbootstrapvalidation/jqBootstrapValidation.js b/lib/jqbootstrapvalidation/jqBootstrapValidation.js new file mode 100644 index 0000000..29cbb08 --- /dev/null +++ b/lib/jqbootstrapvalidation/jqBootstrapValidation.js @@ -0,0 +1,912 @@ +/* jqBootstrapValidation + * A plugin for automating validation on Twitter Bootstrap formatted forms. + * + * v1.3.6 + * + * License: MIT - see LICENSE file + * + * http://ReactiveRaven.github.com/jqBootstrapValidation/ + */ + +(function( $ ){ + + var createdElements = []; + + var defaults = { + options: { + prependExistingHelpBlock: false, + sniffHtml: true, // sniff for 'required', 'maxlength', etc + preventSubmit: true, // stop the form submit event from firing if validation fails + submitError: false, // function called if there is an error when trying to submit + submitSuccess: false, // function called just before a successful submit event is sent to the server + semanticallyStrict: false, // set to true to tidy up generated HTML output + autoAdd: { + helpBlocks: true + }, + filter: function () { + // return $(this).is(":visible"); // only validate elements you can see + return true; // validate everything + } + }, + methods: { + init : function( options ) { + + var settings = $.extend(true, {}, defaults); + + settings.options = $.extend(true, settings.options, options); + + var $siblingElements = this; + + var uniqueForms = $.unique( + $siblingElements.map( function () { + return $(this).parents("form")[0]; + }).toArray() + ); + + $(uniqueForms).bind("submit", function (e) { + var $form = $(this); + var warningsFound = 0; + var $inputs = $form.find("input,textarea,select").not("[type=submit],[type=image]").filter(settings.options.filter); + $inputs.trigger("submit.validation").trigger("validationLostFocus.validation"); + + $inputs.each(function (i, el) { + var $this = $(el), + $controlGroup = $this.parents(".control-group").first(); + if ( + $controlGroup.hasClass("warning") + ) { + $controlGroup.removeClass("warning").addClass("error"); + warningsFound++; + } + }); + + $inputs.trigger("validationLostFocus.validation"); + + if (warningsFound) { + if (settings.options.preventSubmit) { + e.preventDefault(); + } + $form.addClass("error"); + if ($.isFunction(settings.options.submitError)) { + settings.options.submitError($form, e, $inputs.jqBootstrapValidation("collectErrors", true)); + } + } else { + $form.removeClass("error"); + if ($.isFunction(settings.options.submitSuccess)) { + settings.options.submitSuccess($form, e); + } + } + }); + + return this.each(function(){ + + // Get references to everything we're interested in + var $this = $(this), + $controlGroup = $this.parents(".control-group").first(), + $helpBlock = $controlGroup.find(".help-block").first(), + $form = $this.parents("form").first(), + validatorNames = []; + + // create message container if not exists + if (!$helpBlock.length && settings.options.autoAdd && settings.options.autoAdd.helpBlocks) { + $helpBlock = $('
'); + $controlGroup.find('.controls').append($helpBlock); + createdElements.push($helpBlock[0]); + } + + // ============================================================= + // SNIFF HTML FOR VALIDATORS + // ============================================================= + + // *snort sniff snuffle* + + if (settings.options.sniffHtml) { + var message = ""; + // --------------------------------------------------------- + // PATTERN + // --------------------------------------------------------- + if ($this.attr("pattern") !== undefined) { + message = "Not in the expected format"; + if ($this.data("validationPatternMessage")) { + message = $this.data("validationPatternMessage"); + } + $this.data("validationPatternMessage", message); + $this.data("validationPatternRegex", $this.attr("pattern")); + } + // --------------------------------------------------------- + // MAX + // --------------------------------------------------------- + if ($this.attr("max") !== undefined || $this.attr("aria-valuemax") !== undefined) { + var max = ($this.attr("max") !== undefined ? $this.attr("max") : $this.attr("aria-valuemax")); + message = "Too high: Maximum of '" + max + "'"; + if ($this.data("validationMaxMessage")) { + message = $this.data("validationMaxMessage"); + } + $this.data("validationMaxMessage", message); + $this.data("validationMaxMax", max); + } + // --------------------------------------------------------- + // MIN + // --------------------------------------------------------- + if ($this.attr("min") !== undefined || $this.attr("aria-valuemin") !== undefined) { + var min = ($this.attr("min") !== undefined ? $this.attr("min") : $this.attr("aria-valuemin")); + message = "Too low: Minimum of '" + min + "'"; + if ($this.data("validationMinMessage")) { + message = $this.data("validationMinMessage"); + } + $this.data("validationMinMessage", message); + $this.data("validationMinMin", min); + } + // --------------------------------------------------------- + // MAXLENGTH + // --------------------------------------------------------- + if ($this.attr("maxlength") !== undefined) { + message = "Too long: Maximum of '" + $this.attr("maxlength") + "' characters"; + if ($this.data("validationMaxlengthMessage")) { + message = $this.data("validationMaxlengthMessage"); + } + $this.data("validationMaxlengthMessage", message); + $this.data("validationMaxlengthMaxlength", $this.attr("maxlength")); + } + // --------------------------------------------------------- + // MINLENGTH + // --------------------------------------------------------- + if ($this.attr("minlength") !== undefined) { + message = "Too short: Minimum of '" + $this.attr("minlength") + "' characters"; + if ($this.data("validationMinlengthMessage")) { + message = $this.data("validationMinlengthMessage"); + } + $this.data("validationMinlengthMessage", message); + $this.data("validationMinlengthMinlength", $this.attr("minlength")); + } + // --------------------------------------------------------- + // REQUIRED + // --------------------------------------------------------- + if ($this.attr("required") !== undefined || $this.attr("aria-required") !== undefined) { + message = settings.builtInValidators.required.message; + if ($this.data("validationRequiredMessage")) { + message = $this.data("validationRequiredMessage"); + } + $this.data("validationRequiredMessage", message); + } + // --------------------------------------------------------- + // NUMBER + // --------------------------------------------------------- + if ($this.attr("type") !== undefined && $this.attr("type").toLowerCase() === "number") { + message = settings.builtInValidators.number.message; + if ($this.data("validationNumberMessage")) { + message = $this.data("validationNumberMessage"); + } + $this.data("validationNumberMessage", message); + } + // --------------------------------------------------------- + // EMAIL + // --------------------------------------------------------- + if ($this.attr("type") !== undefined && $this.attr("type").toLowerCase() === "email") { + message = "Not a valid email address"; + if ($this.data("validationValidemailMessage")) { + message = $this.data("validationValidemailMessage"); + } else if ($this.data("validationEmailMessage")) { + message = $this.data("validationEmailMessage"); + } + $this.data("validationValidemailMessage", message); + } + // --------------------------------------------------------- + // MINCHECKED + // --------------------------------------------------------- + if ($this.attr("minchecked") !== undefined) { + message = "Not enough options checked; Minimum of '" + $this.attr("minchecked") + "' required"; + if ($this.data("validationMincheckedMessage")) { + message = $this.data("validationMincheckedMessage"); + } + $this.data("validationMincheckedMessage", message); + $this.data("validationMincheckedMinchecked", $this.attr("minchecked")); + } + // --------------------------------------------------------- + // MAXCHECKED + // --------------------------------------------------------- + if ($this.attr("maxchecked") !== undefined) { + message = "Too many options checked; Maximum of '" + $this.attr("maxchecked") + "' required"; + if ($this.data("validationMaxcheckedMessage")) { + message = $this.data("validationMaxcheckedMessage"); + } + $this.data("validationMaxcheckedMessage", message); + $this.data("validationMaxcheckedMaxchecked", $this.attr("maxchecked")); + } + } + + // ============================================================= + // COLLECT VALIDATOR NAMES + // ============================================================= + + // Get named validators + if ($this.data("validation") !== undefined) { + validatorNames = $this.data("validation").split(","); + } + + // Get extra ones defined on the element's data attributes + $.each($this.data(), function (i, el) { + var parts = i.replace(/([A-Z])/g, ",$1").split(","); + if (parts[0] === "validation" && parts[1]) { + validatorNames.push(parts[1]); + } + }); + + // ============================================================= + // NORMALISE VALIDATOR NAMES + // ============================================================= + + var validatorNamesToInspect = validatorNames; + var newValidatorNamesToInspect = []; + + do // repeatedly expand 'shortcut' validators into their real validators + { + // Uppercase only the first letter of each name + $.each(validatorNames, function (i, el) { + validatorNames[i] = formatValidatorName(el); + }); + + // Remove duplicate validator names + validatorNames = $.unique(validatorNames); + + // Pull out the new validator names from each shortcut + newValidatorNamesToInspect = []; + $.each(validatorNamesToInspect, function(i, el) { + if ($this.data("validation" + el + "Shortcut") !== undefined) { + // Are these custom validators? + // Pull them out! + $.each($this.data("validation" + el + "Shortcut").split(","), function(i2, el2) { + newValidatorNamesToInspect.push(el2); + }); + } else if (settings.builtInValidators[el.toLowerCase()]) { + // Is this a recognised built-in? + // Pull it out! + var validator = settings.builtInValidators[el.toLowerCase()]; + if (validator.type.toLowerCase() === "shortcut") { + $.each(validator.shortcut.split(","), function (i, el) { + el = formatValidatorName(el); + newValidatorNamesToInspect.push(el); + validatorNames.push(el); + }); + } + } + }); + + validatorNamesToInspect = newValidatorNamesToInspect; + + } while (validatorNamesToInspect.length > 0) + + // ============================================================= + // SET UP VALIDATOR ARRAYS + // ============================================================= + + var validators = {}; + + $.each(validatorNames, function (i, el) { + // Set up the 'override' message + var message = $this.data("validation" + el + "Message"); + var hasOverrideMessage = (message !== undefined); + var foundValidator = false; + message = + ( + message + ? message + : "'" + el + "' validation failed " + ) + ; + + $.each( + settings.validatorTypes, + function (validatorType, validatorTemplate) { + if (validators[validatorType] === undefined) { + validators[validatorType] = []; + } + if (!foundValidator && $this.data("validation" + el + formatValidatorName(validatorTemplate.name)) !== undefined) { + validators[validatorType].push( + $.extend( + true, + { + name: formatValidatorName(validatorTemplate.name), + message: message + }, + validatorTemplate.init($this, el) + ) + ); + foundValidator = true; + } + } + ); + + if (!foundValidator && settings.builtInValidators[el.toLowerCase()]) { + + var validator = $.extend(true, {}, settings.builtInValidators[el.toLowerCase()]); + if (hasOverrideMessage) { + validator.message = message; + } + var validatorType = validator.type.toLowerCase(); + + if (validatorType === "shortcut") { + foundValidator = true; + } else { + $.each( + settings.validatorTypes, + function (validatorTemplateType, validatorTemplate) { + if (validators[validatorTemplateType] === undefined) { + validators[validatorTemplateType] = []; + } + if (!foundValidator && validatorType === validatorTemplateType.toLowerCase()) { + $this.data("validation" + el + formatValidatorName(validatorTemplate.name), validator[validatorTemplate.name.toLowerCase()]); + validators[validatorType].push( + $.extend( + validator, + validatorTemplate.init($this, el) + ) + ); + foundValidator = true; + } + } + ); + } + } + + if (! foundValidator) { + $.error("Cannot find validation info for '" + el + "'"); + } + }); + + // ============================================================= + // STORE FALLBACK VALUES + // ============================================================= + + $helpBlock.data( + "original-contents", + ( + $helpBlock.data("original-contents") + ? $helpBlock.data("original-contents") + : $helpBlock.html() + ) + ); + + $helpBlock.data( + "original-role", + ( + $helpBlock.data("original-role") + ? $helpBlock.data("original-role") + : $helpBlock.attr("role") + ) + ); + + $controlGroup.data( + "original-classes", + ( + $controlGroup.data("original-clases") + ? $controlGroup.data("original-classes") + : $controlGroup.attr("class") + ) + ); + + $this.data( + "original-aria-invalid", + ( + $this.data("original-aria-invalid") + ? $this.data("original-aria-invalid") + : $this.attr("aria-invalid") + ) + ); + + // ============================================================= + // VALIDATION + // ============================================================= + + $this.bind( + "validation.validation", + function (event, params) { + + var value = getValue($this); + + // Get a list of the errors to apply + var errorsFound = []; + + $.each(validators, function (validatorType, validatorTypeArray) { + if (value || value.length || (params && params.includeEmpty) || (!!settings.validatorTypes[validatorType].blockSubmit && params && !!params.submitting)) { + $.each(validatorTypeArray, function (i, validator) { + if (settings.validatorTypes[validatorType].validate($this, value, validator)) { + errorsFound.push(validator.message); + } + }); + } + }); + + return errorsFound; + } + ); + + $this.bind( + "getValidators.validation", + function () { + return validators; + } + ); + + // ============================================================= + // WATCH FOR CHANGES + // ============================================================= + $this.bind( + "submit.validation", + function () { + return $this.triggerHandler("change.validation", {submitting: true}); + } + ); + $this.bind( + [ + "keyup", + "focus", + "blur", + "click", + "keydown", + "keypress", + "change" + ].join(".validation ") + ".validation", + function (e, params) { + + var value = getValue($this); + + var errorsFound = []; + + $controlGroup.find("input,textarea,select").each(function (i, el) { + var oldCount = errorsFound.length; + $.each($(el).triggerHandler("validation.validation", params), function (j, message) { + errorsFound.push(message); + }); + if (errorsFound.length > oldCount) { + $(el).attr("aria-invalid", "true"); + } else { + var original = $this.data("original-aria-invalid"); + $(el).attr("aria-invalid", (original !== undefined ? original : false)); + } + }); + + $form.find("input,select,textarea").not($this).not("[name=\"" + $this.attr("name") + "\"]").trigger("validationLostFocus.validation"); + + errorsFound = $.unique(errorsFound.sort()); + + // Were there any errors? + if (errorsFound.length) { + // Better flag it up as a warning. + $controlGroup.removeClass("success error").addClass("warning"); + + // How many errors did we find? + if (settings.options.semanticallyStrict && errorsFound.length === 1) { + // Only one? Being strict? Just output it. + $helpBlock.html(errorsFound[0] + + ( settings.options.prependExistingHelpBlock ? $helpBlock.data("original-contents") : "" )); + } else { + // Multiple? Being sloppy? Glue them together into an UL. + $helpBlock.html("
  • " + errorsFound.join("
  • ") + "
" + + ( settings.options.prependExistingHelpBlock ? $helpBlock.data("original-contents") : "" )); + } + } else { + $controlGroup.removeClass("warning error success"); + if (value.length > 0) { + $controlGroup.addClass("success"); + } + $helpBlock.html($helpBlock.data("original-contents")); + } + + if (e.type === "blur") { + $controlGroup.removeClass("success"); + } + } + ); + $this.bind("validationLostFocus.validation", function () { + $controlGroup.removeClass("success"); + }); + }); + }, + destroy : function( ) { + + return this.each( + function() { + + var + $this = $(this), + $controlGroup = $this.parents(".control-group").first(), + $helpBlock = $controlGroup.find(".help-block").first(); + + // remove our events + $this.unbind('.validation'); // events are namespaced. + // reset help text + $helpBlock.html($helpBlock.data("original-contents")); + // reset classes + $controlGroup.attr("class", $controlGroup.data("original-classes")); + // reset aria + $this.attr("aria-invalid", $this.data("original-aria-invalid")); + // reset role + $helpBlock.attr("role", $this.data("original-role")); + // remove all elements we created + if (createdElements.indexOf($helpBlock[0]) > -1) { + $helpBlock.remove(); + } + + } + ); + + }, + collectErrors : function(includeEmpty) { + + var errorMessages = {}; + this.each(function (i, el) { + var $el = $(el); + var name = $el.attr("name"); + var errors = $el.triggerHandler("validation.validation", {includeEmpty: true}); + errorMessages[name] = $.extend(true, errors, errorMessages[name]); + }); + + $.each(errorMessages, function (i, el) { + if (el.length === 0) { + delete errorMessages[i]; + } + }); + + return errorMessages; + + }, + hasErrors: function() { + + var errorMessages = []; + + this.each(function (i, el) { + errorMessages = errorMessages.concat( + $(el).triggerHandler("getValidators.validation") ? $(el).triggerHandler("validation.validation", {submitting: true}) : [] + ); + }); + + return (errorMessages.length > 0); + }, + override : function (newDefaults) { + defaults = $.extend(true, defaults, newDefaults); + } + }, + validatorTypes: { + callback: { + name: "callback", + init: function ($this, name) { + return { + validatorName: name, + callback: $this.data("validation" + name + "Callback"), + lastValue: $this.val(), + lastValid: true, + lastFinished: true + }; + }, + validate: function ($this, value, validator) { + if (validator.lastValue === value && validator.lastFinished) { + return !validator.lastValid; + } + + if (validator.lastFinished === true) + { + validator.lastValue = value; + validator.lastValid = true; + validator.lastFinished = false; + + var rrjqbvValidator = validator; + var rrjqbvThis = $this; + executeFunctionByName( + validator.callback, + window, + $this, + value, + function (data) { + if (rrjqbvValidator.lastValue === data.value) { + rrjqbvValidator.lastValid = data.valid; + if (data.message) { + rrjqbvValidator.message = data.message; + } + rrjqbvValidator.lastFinished = true; + rrjqbvThis.data("validation" + rrjqbvValidator.validatorName + "Message", rrjqbvValidator.message); + // Timeout is set to avoid problems with the events being considered 'already fired' + setTimeout(function () { + rrjqbvThis.trigger("change.validation"); + }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst + } + } + ); + } + + return false; + + } + }, + ajax: { + name: "ajax", + init: function ($this, name) { + return { + validatorName: name, + url: $this.data("validation" + name + "Ajax"), + lastValue: $this.val(), + lastValid: true, + lastFinished: true + }; + }, + validate: function ($this, value, validator) { + if (""+validator.lastValue === ""+value && validator.lastFinished === true) { + return validator.lastValid === false; + } + + if (validator.lastFinished === true) + { + validator.lastValue = value; + validator.lastValid = true; + validator.lastFinished = false; + $.ajax({ + url: validator.url, + data: "value=" + value + "&field=" + $this.attr("name"), + dataType: "json", + success: function (data) { + if (""+validator.lastValue === ""+data.value) { + validator.lastValid = !!(data.valid); + if (data.message) { + validator.message = data.message; + } + validator.lastFinished = true; + $this.data("validation" + validator.validatorName + "Message", validator.message); + // Timeout is set to avoid problems with the events being considered 'already fired' + setTimeout(function () { + $this.trigger("change.validation"); + }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst + } + }, + failure: function () { + validator.lastValid = true; + validator.message = "ajax call failed"; + validator.lastFinished = true; + $this.data("validation" + validator.validatorName + "Message", validator.message); + // Timeout is set to avoid problems with the events being considered 'already fired' + setTimeout(function () { + $this.trigger("change.validation"); + }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst + } + }); + } + + return false; + + } + }, + regex: { + name: "regex", + init: function ($this, name) { + return {regex: regexFromString($this.data("validation" + name + "Regex"))}; + }, + validate: function ($this, value, validator) { + return (!validator.regex.test(value) && ! validator.negative) + || (validator.regex.test(value) && validator.negative); + } + }, + required: { + name: "required", + init: function ($this, name) { + return {}; + }, + validate: function ($this, value, validator) { + return !!(value.length === 0 && ! validator.negative) + || !!(value.length > 0 && validator.negative); + }, + blockSubmit: true + }, + match: { + name: "match", + init: function ($this, name) { + var element = $this.parents("form").first().find("[name=\"" + $this.data("validation" + name + "Match") + "\"]").first(); + element.bind("validation.validation", function () { + $this.trigger("change.validation", {submitting: true}); + }); + return {"element": element}; + }, + validate: function ($this, value, validator) { + return (value !== validator.element.val() && ! validator.negative) + || (value === validator.element.val() && validator.negative); + }, + blockSubmit: true + }, + max: { + name: "max", + init: function ($this, name) { + return {max: $this.data("validation" + name + "Max")}; + }, + validate: function ($this, value, validator) { + return (parseFloat(value, 10) > parseFloat(validator.max, 10) && ! validator.negative) + || (parseFloat(value, 10) <= parseFloat(validator.max, 10) && validator.negative); + } + }, + min: { + name: "min", + init: function ($this, name) { + return {min: $this.data("validation" + name + "Min")}; + }, + validate: function ($this, value, validator) { + return (parseFloat(value) < parseFloat(validator.min) && ! validator.negative) + || (parseFloat(value) >= parseFloat(validator.min) && validator.negative); + } + }, + maxlength: { + name: "maxlength", + init: function ($this, name) { + return {maxlength: $this.data("validation" + name + "Maxlength")}; + }, + validate: function ($this, value, validator) { + return ((value.length > validator.maxlength) && ! validator.negative) + || ((value.length <= validator.maxlength) && validator.negative); + } + }, + minlength: { + name: "minlength", + init: function ($this, name) { + return {minlength: $this.data("validation" + name + "Minlength")}; + }, + validate: function ($this, value, validator) { + return ((value.length < validator.minlength) && ! validator.negative) + || ((value.length >= validator.minlength) && validator.negative); + } + }, + maxchecked: { + name: "maxchecked", + init: function ($this, name) { + var elements = $this.parents("form").first().find("[name=\"" + $this.attr("name") + "\"]"); + elements.bind("click.validation", function () { + $this.trigger("change.validation", {includeEmpty: true}); + }); + return {maxchecked: $this.data("validation" + name + "Maxchecked"), elements: elements}; + }, + validate: function ($this, value, validator) { + return (validator.elements.filter(":checked").length > validator.maxchecked && ! validator.negative) + || (validator.elements.filter(":checked").length <= validator.maxchecked && validator.negative); + }, + blockSubmit: true + }, + minchecked: { + name: "minchecked", + init: function ($this, name) { + var elements = $this.parents("form").first().find("[name=\"" + $this.attr("name") + "\"]"); + elements.bind("click.validation", function () { + $this.trigger("change.validation", {includeEmpty: true}); + }); + return {minchecked: $this.data("validation" + name + "Minchecked"), elements: elements}; + }, + validate: function ($this, value, validator) { + return (validator.elements.filter(":checked").length < validator.minchecked && ! validator.negative) + || (validator.elements.filter(":checked").length >= validator.minchecked && validator.negative); + }, + blockSubmit: true + } + }, + builtInValidators: { + email: { + name: "Email", + type: "shortcut", + shortcut: "validemail" + }, + validemail: { + name: "Validemail", + type: "regex", + regex: "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\\.[A-Za-z]{2,4}", + message: "Not a valid email address" + }, + passwordagain: { + name: "Passwordagain", + type: "match", + match: "password", + message: "Does not match the given password" + }, + positive: { + name: "Positive", + type: "shortcut", + shortcut: "number,positivenumber" + }, + negative: { + name: "Negative", + type: "shortcut", + shortcut: "number,negativenumber" + }, + number: { + name: "Number", + type: "regex", + regex: "([+-]?\\\d+(\\\.\\\d*)?([eE][+-]?[0-9]+)?)?", + message: "Must be a number" + }, + integer: { + name: "Integer", + type: "regex", + regex: "[+-]?\\\d+", + message: "No decimal places allowed" + }, + positivenumber: { + name: "Positivenumber", + type: "min", + min: 0, + message: "Must be a positive number" + }, + negativenumber: { + name: "Negativenumber", + type: "max", + max: 0, + message: "Must be a negative number" + }, + required: { + name: "Required", + type: "required", + message: "This is required" + }, + checkone: { + name: "Checkone", + type: "minchecked", + minchecked: 1, + message: "Check at least one option" + } + } + }; + + var formatValidatorName = function (name) { + return name + .toLowerCase() + .replace( + /(^|\s)([a-z])/g , + function(m,p1,p2) { + return p1+p2.toUpperCase(); + } + ) + ; + }; + + var getValue = function ($this) { + // Extract the value we're talking about + var value = $this.val(); + var type = $this.attr("type"); + if (type === "checkbox") { + value = ($this.is(":checked") ? value : ""); + } + if (type === "radio") { + value = ($('input[name="' + $this.attr("name") + '"]:checked').length > 0 ? value : ""); + } + return value; + }; + + function regexFromString(inputstring) { + return new RegExp("^" + inputstring + "$"); + } + + /** + * Thanks to Jason Bunting via StackOverflow.com + * + * http://stackoverflow.com/questions/359788/how-to-execute-a-javascript-function-when-i-have-its-name-as-a-string#answer-359910 + * Short link: http://tinyurl.com/executeFunctionByName + **/ + function executeFunctionByName(functionName, context /*, args*/) { + var args = Array.prototype.slice.call(arguments).splice(2); + var namespaces = functionName.split("."); + var func = namespaces.pop(); + for(var i = 0; i < namespaces.length; i++) { + context = context[namespaces[i]]; + } + return context[func].apply(this, args); + } + + $.fn.jqBootstrapValidation = function( method ) { + + if ( defaults.methods[method] ) { + return defaults.methods[method].apply( this, Array.prototype.slice.call( arguments, 1 )); + } else if ( typeof method === 'object' || ! method ) { + return defaults.methods.init.apply( this, arguments ); + } else { + $.error( 'Method ' + method + ' does not exist on jQuery.jqBootstrapValidation' ); + return null; + } + + }; + + $.jqBootstrapValidation = function (options) { + $(":input").not("[type=image],[type=submit]").jqBootstrapValidation.apply(this,arguments); + }; + +})( jQuery ); diff --git a/uVote/page/default_page/default_page.php b/uVote/page/default_page/default_page.php index 51abfbd..8407b5e 100644 --- a/uVote/page/default_page/default_page.php +++ b/uVote/page/default_page/default_page.php @@ -5,7 +5,9 @@ class default_page extends SYSTEM\PAGE\Page { private function js(){ return ''. ''. - ''. + ''. + ''. +// ''. ''; ''; } diff --git a/uVote/page/default_page/js/loadtexts.js b/uVote/page/default_page/js/loadtexts.js index a22f566..998b274 100644 --- a/uVote/page/default_page/js/loadtexts.js +++ b/uVote/page/default_page/js/loadtexts.js @@ -15,11 +15,28 @@ $(document).ready(function() { $('.btnvote_off').click(function () { vote_click($(this).attr('poll_ID'),3); }); - $('.inputEmail, inputPassword, inputPassword2').click(function () { - vote_click($(this).attr('email', 'password', 'password2'), inputEmail, inputPassword, inputPassword2); - }); +// $('#register_btn').click(function () { +// account_create ($(this).attr ('#inputEmail')) +// }); + //jqBootstrapValidation + $("#form_register input").not("[type=submit]").jqBootstrapValidation( + { + preventSubmit: true, + submitError: function($form, event, errors) {}, + submitSuccess: function($form, event){ + alert ('.api.php?call=account&action=create&username=' + $('#bt_login_user').val() + '&password_sha=' + $.sha1($('#bt_login_password').val()) + '&email=' + $('#bt_login_user').val() + '&locale=deDE'); + $.get('.api.php?call=account&action=create&username=' + $('#bt_login_user').val() + '&password_sha=' + $.sha1($('#bt_login_password').val() + '&email=' + $('#bt_login_user').val() + '&locale=deDE'), function (data) { + if(data == 1){ + alert ("abc"); + } else { + $('#help-block-user-password-combi-wrong').attr('style', 'display: block;'); + } + }); + event.preventDefault(); + } + }); }); -function getuserpersonaldata(inputEmail, inputPassword){ +function account_create(inputEmail, inputPassword){ $.get('.api.php?call=account&action=create&username=' + NULL + '&password_sha=' + password + '&email=' + email + '&locale=deDE', function (data) { dataTmp = data; }).complete(function() { diff --git a/uVote/page/default_page/page.html b/uVote/page/default_page/page.html index ae10280..5a893b1 100644 --- a/uVote/page/default_page/page.html +++ b/uVote/page/default_page/page.html @@ -34,7 +34,7 @@ - +