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 @@
-
+
diff --git a/uVote/page/default_page/register_form.tpl b/uVote/page/default_page/register_form.tpl
index cbe0776..dc4be68 100644
--- a/uVote/page/default_page/register_form.tpl
+++ b/uVote/page/default_page/register_form.tpl
@@ -1,19 +1,82 @@
-
\ No newline at end of file
+
+
+
'
+
+
\ No newline at end of file
diff --git a/uVote/path/PCRYPTOSHA.php b/uVote/path/PCRYPTOSHA.php
new file mode 100644
index 0000000..4c528ba
--- /dev/null
+++ b/uVote/path/PCRYPTOSHA.php
@@ -0,0 +1,5 @@
+