6033 lines
247 KiB
JavaScript
6033 lines
247 KiB
JavaScript
/*
|
|
* jFormer JavaScript Library v1.4.4
|
|
* http://jFormer.com/
|
|
*
|
|
* Copyright 2011, Kirk Ouimet, Seth Zander Jensen
|
|
* Dual licensed under the MIT or GPL Version 2 licenses.
|
|
* http://jFormer.com/download#license
|
|
*
|
|
* Date: Mon Jan 10 2011
|
|
*/
|
|
|
|
// Simple class creation and inheritance
|
|
// Inspired by base2 and Prototype
|
|
(function(){
|
|
var initializing = false, fnTest = /xyz/.test(function(){
|
|
xyz;
|
|
}) ? /\b_super\b/ : /.*/;
|
|
|
|
// The base Class implementation (does nothing)
|
|
this.Class = function(){};
|
|
|
|
// Create a new Class that inherits from this class
|
|
Class.extend = function(prop) {
|
|
var _super = this.prototype;
|
|
|
|
// Instantiate a base class (but only create the instance,
|
|
// don't run the init constructor)
|
|
initializing = true;
|
|
var prototype = new this();
|
|
initializing = false;
|
|
|
|
// Copy the properties over onto the new prototype
|
|
for (var name in prop) {
|
|
// Check if we're overwriting an existing function
|
|
prototype[name] = typeof prop[name] == "function" &&
|
|
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
|
|
(function(name, fn){
|
|
return function() {
|
|
var tmp = this._super;
|
|
|
|
// Add a new ._super() method that is the same method
|
|
// but on the super-class
|
|
this._super = _super[name];
|
|
|
|
// The method only need to be bound temporarily, so we
|
|
// remove it when we're done executing
|
|
var ret = fn.apply(this, arguments);
|
|
this._super = tmp;
|
|
|
|
return ret;
|
|
};
|
|
})(name, prop[name]) :
|
|
prop[name];
|
|
}
|
|
|
|
// The dummy class constructor
|
|
function Class() {
|
|
// All construction is actually done in the init method
|
|
if ( !initializing && this.init )
|
|
this.init.apply(this, arguments);
|
|
}
|
|
|
|
// Populate our constructed prototype object
|
|
Class.prototype = prototype;
|
|
|
|
// Enforce the constructor to be what we expect
|
|
Class.constructor = Class;
|
|
|
|
// And make this class extendable
|
|
Class.extend = arguments.callee;
|
|
|
|
return Class;
|
|
};
|
|
})();
|
|
|
|
/*
|
|
Date Input 1.2.1
|
|
Requires jQuery version: >= 1.2.6
|
|
|
|
Copyright (c) 2007-2008 Jonathan Leighton & Torchbox Ltd
|
|
|
|
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.
|
|
*/
|
|
|
|
DateInput = (function($) {
|
|
|
|
function DateInput(element, options) {
|
|
if (typeof(opts) != "object") options = {};
|
|
$.extend(this, DateInput.DEFAULT_OPTS, options);
|
|
|
|
var button = $('<span class="jFormComponentDateButton">Find Date</span>');
|
|
|
|
this.input = $(element);
|
|
this.input.after(button);
|
|
this.button = $(element).parent().find('span.jFormComponentDateButton');
|
|
this.bindMethodsToObj("show", "hide", "hideIfClickOutside", "keydownHandler", "selectDate");
|
|
|
|
this.build();
|
|
this.selectDate();
|
|
this.hide();
|
|
};
|
|
DateInput.DEFAULT_OPTS = {
|
|
jFormComponentDateSelectorMonthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
|
|
short_jFormComponentDateSelectorMonthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
|
|
short_day_names: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
|
|
start_of_week: 0
|
|
};
|
|
DateInput.prototype = {
|
|
build: function() {
|
|
var monthNav = $('<p class="jFormComponentDateSelectorMonthNavigator">' +
|
|
'<span class="jFormComponentDateSelectorButton jFormComponentDateSelectorPrevious" title="[Page-Up]">«</span>' +
|
|
' <span class="jFormComponentDateSelectorMonthName"></span> ' +
|
|
'<span class="jFormComponentDateSelectorButton jFormComponentDateSelectorNext" title="[Page-Down]">»</span>' +
|
|
'</p>');
|
|
this.monthNameSpan = $(".jFormComponentDateSelectorMonthName", monthNav);
|
|
$(".jFormComponentDateSelectorPrevious", monthNav).click(this.bindToObj(function() {
|
|
this.moveMonthBy(-1);
|
|
}));
|
|
$(".jFormComponentDateSelectorNext", monthNav).click(this.bindToObj(function() {
|
|
this.moveMonthBy(1);
|
|
}));
|
|
|
|
var yearNav = $('<p class="jFormComponentDateSelectorYearNavigator">' +
|
|
'<span class="jFormComponentDateSelectorButton jFormComponentDateSelectorPrevious" title="[Ctrl+Page-Up]">«</span>' +
|
|
' <span class="jFormComponentDateSelectorYearName"></span> ' +
|
|
'<span class="jFormComponentDateSelectorButton jFormComponentDateSelectorNext" title="[Ctrl+Page-Down]">»</span>' +
|
|
'</p>');
|
|
this.yearNameSpan = $(".jFormComponentDateSelectorYearName", yearNav);
|
|
$(".jFormComponentDateSelectorPrevious", yearNav).click(this.bindToObj(function() {
|
|
this.moveMonthBy(-12);
|
|
}));
|
|
$(".jFormComponentDateSelectorNext", yearNav).click(this.bindToObj(function() {
|
|
this.moveMonthBy(12);
|
|
}));
|
|
|
|
var nav = $('<div class="jFormComponentDateSelectorNavigator"></div>').append(monthNav, yearNav);
|
|
|
|
var tableShell = "<table><thead><tr>";
|
|
$(this.adjustDays(this.short_day_names)).each(function() {
|
|
tableShell += "<th>" + this + "</th>";
|
|
});
|
|
tableShell += "</tr></thead><tbody></tbody></table>";
|
|
|
|
this.dateSelector = this.rootLayers = $('<div class="jFormComponentDateSelector"></div>').append(nav, tableShell).insertAfter(this.input);
|
|
|
|
if ($.browser.msie && $.browser.version < 7) {
|
|
|
|
this.ieframe = $('<iframe class="jFormComponentDateSelectorIEFrame" frameborder="0" src="#"></iframe>').insertBefore(this.dateSelector);
|
|
this.rootLayers = this.rootLayers.add(this.ieframe);
|
|
|
|
$(".jFormComponentDateSelectorButton", nav).mouseover(function() {
|
|
$(this).addClass("hover")
|
|
});
|
|
$(".jFormComponentDateSelectorButton", nav).mouseout(function() {
|
|
$(this).removeClass("hover")
|
|
});
|
|
};
|
|
|
|
this.tbody = $("tbody", this.dateSelector);
|
|
|
|
this.input.change(this.bindToObj(function() {
|
|
this.selectDate();
|
|
}));
|
|
this.selectDate();
|
|
},
|
|
|
|
selectMonth: function(date) {
|
|
var newMonth = new Date(date.getFullYear(), date.getMonth(), 1);
|
|
|
|
if (!this.currentMonth || !(this.currentMonth.getFullYear() == newMonth.getFullYear() &&
|
|
this.currentMonth.getMonth() == newMonth.getMonth())) {
|
|
|
|
this.currentMonth = newMonth;
|
|
|
|
var rangeStart = this.rangeStart(date), rangeEnd = this.rangeEnd(date);
|
|
var numDays = this.daysBetween(rangeStart, rangeEnd);
|
|
var dayCells = "";
|
|
|
|
for (var i = 0; i <= numDays; i++) {
|
|
var currentDay = new Date(rangeStart.getFullYear(), rangeStart.getMonth(), rangeStart.getDate() + i, 12, 00);
|
|
|
|
if (this.isFirstDayOfWeek(currentDay)) dayCells += "<tr>";
|
|
|
|
if (currentDay.getMonth() == date.getMonth()) {
|
|
dayCells += '<td class="jFormComponentDateSelectorSelectedDay" date="' + this.dateToString(currentDay) + '">' + currentDay.getDate() + '</td>';
|
|
} else {
|
|
dayCells += '<td class="jFormComponentDateSelectorUnselectedMonth" date="' + this.dateToString(currentDay) + '">' + currentDay.getDate() + '</td>';
|
|
};
|
|
|
|
if (this.isLastDayOfWeek(currentDay)) dayCells += "</tr>";
|
|
};
|
|
this.tbody.empty().append(dayCells);
|
|
|
|
this.monthNameSpan.empty().append(this.monthName(date));
|
|
this.yearNameSpan.empty().append(this.currentMonth.getFullYear());
|
|
|
|
$(".jFormComponentDateSelectorSelectedDay", this.tbody).click(this.bindToObj(function(event) {
|
|
this.changeInput($(event.target).attr("date"));
|
|
}));
|
|
|
|
$("td[date=" + this.dateToString(new Date()) + "]", this.tbody).addClass("jFormComponentDateSelectorToday");
|
|
|
|
$("td.jFormComponentDateSelectorSelectedDay", this.tbody).mouseover(function() {
|
|
$(this).addClass("hover")
|
|
});
|
|
$("td.jFormComponentDateSelectorSelectedDay", this.tbody).mouseout(function() {
|
|
$(this).removeClass("hover")
|
|
});
|
|
};
|
|
|
|
$('.jFormComponentDateSelectorSelected', this.tbody).removeClass("jFormComponentDateSelectorSelected");
|
|
$('td[date=' + this.selectedDateString + ']', this.tbody).addClass("jFormComponentDateSelectorSelected");
|
|
},
|
|
|
|
selectDate: function(date) {
|
|
if (typeof(date) == "undefined") {
|
|
date = this.stringToDate(this.input.val());
|
|
};
|
|
if (!date) date = new Date();
|
|
|
|
this.selectedDate = date;
|
|
this.selectedDateString = this.dateToString(this.selectedDate);
|
|
this.selectMonth(this.selectedDate);
|
|
},
|
|
|
|
changeInput: function(dateString) {
|
|
this.input.val(dateString).change();
|
|
this.hide();
|
|
},
|
|
|
|
show: function() {
|
|
this.rootLayers.css("display", "block");
|
|
this.button.unbind("click", this.show);
|
|
this.input.unbind("focus", this.show);
|
|
$(document.body).keydown(this.keydownHandler);
|
|
$([window, document.body]).click(this.hideIfClickOutside);
|
|
this.setPosition();
|
|
},
|
|
|
|
hide: function() {
|
|
this.rootLayers.css("display", "none");
|
|
$([window, document.body]).unbind("click", this.hideIfClickOutside);
|
|
this.button.click(this.show);
|
|
this.input.focus(this.show);
|
|
$(document.body).unbind("keydown", this.keydownHandler);
|
|
},
|
|
|
|
hideIfClickOutside: function(event) {
|
|
if (event.target != this.input[0] && event.target != this.button[0] && !this.insideSelector(event)) {
|
|
this.hide();
|
|
};
|
|
},
|
|
|
|
insideSelector: function(event) {
|
|
var offset = this.dateSelector.offset();
|
|
offset.right = offset.left + this.dateSelector.outerWidth();
|
|
offset.bottom = offset.top + this.dateSelector.outerHeight();
|
|
|
|
|
|
return event.pageY < offset.bottom &&
|
|
event.pageY > offset.top &&
|
|
event.pageX < offset.right &&
|
|
event.pageX > offset.left;
|
|
},
|
|
|
|
keydownHandler: function(event) {
|
|
switch (event.keyCode)
|
|
{
|
|
case 9:
|
|
case 27:
|
|
this.hide();
|
|
return;
|
|
break;
|
|
case 13:
|
|
this.changeInput(this.selectedDateString);
|
|
break;
|
|
case 33:
|
|
this.moveDateMonthBy(event.ctrlKey ? -12 : -1);
|
|
break;
|
|
case 34:
|
|
this.moveDateMonthBy(event.ctrlKey ? 12 : 1);
|
|
break;
|
|
case 38:
|
|
this.moveDateBy(-7);
|
|
break;
|
|
case 40:
|
|
this.moveDateBy(7);
|
|
break;
|
|
case 37:
|
|
this.moveDateBy(-1);
|
|
break;
|
|
case 39:
|
|
this.moveDateBy(1);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
event.preventDefault();
|
|
},
|
|
|
|
stringToDate: function(string) {
|
|
string = string.replace(/[^\d]/g, '/');
|
|
if (string.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4,4})$/)) {
|
|
return new Date(string);
|
|
} else {
|
|
return null;
|
|
};
|
|
},
|
|
|
|
dateToString: function(date) {
|
|
return padString(date.getMonth()+1) +'/'+ padString(date.getDate()) +"/"+ date.getFullYear();
|
|
|
|
function padString(number){
|
|
number = '' + number;
|
|
if(number.length == 1){
|
|
number = '0'+number;
|
|
}
|
|
return number;
|
|
}
|
|
},
|
|
|
|
setPosition: function() {
|
|
var offset = this.button.position();
|
|
this.rootLayers.css({
|
|
top: offset.top,
|
|
left: offset.left + this.button.outerWidth() + 4
|
|
});
|
|
if (this.ieframe) {
|
|
this.ieframe.css({
|
|
width: this.dateSelector.outerWidth(),
|
|
height: this.dateSelector.outerHeight()
|
|
});
|
|
}
|
|
var bottom = offset.top + this.dateSelector.outerHeight() + 12;
|
|
var top = '';
|
|
if(jFormerUtility.isSet(window.scrollY)) {
|
|
top = window.scrollY;
|
|
}
|
|
else { // IE FTL
|
|
top = document.documentElement.scrollTop;
|
|
}
|
|
if(top + $(window).height() > bottom) {
|
|
} else {
|
|
$.scrollTo(bottom - $(window).height() + 'px', 250, {
|
|
axis:'y'
|
|
});
|
|
}
|
|
},
|
|
|
|
moveDateBy: function(amount) {
|
|
var newDate = new Date(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate() + amount);
|
|
this.selectDate(newDate);
|
|
},
|
|
|
|
moveDateMonthBy: function(amount) {
|
|
var newDate = new Date(this.selectedDate.getFullYear(), this.selectedDate.getMonth() + amount, this.selectedDate.getDate());
|
|
if (newDate.getMonth() == this.selectedDate.getMonth() + amount + 1) {
|
|
|
|
newDate.setDate(0);
|
|
};
|
|
this.selectDate(newDate);
|
|
},
|
|
|
|
moveMonthBy: function(amount) {
|
|
var newMonth = new Date(this.currentMonth.getFullYear(), this.currentMonth.getMonth() + amount, this.currentMonth.getDate());
|
|
this.selectMonth(newMonth);
|
|
},
|
|
|
|
monthName: function(date) {
|
|
return this.jFormComponentDateSelectorMonthNames[date.getMonth()];
|
|
},
|
|
|
|
bindToObj: function(fn) {
|
|
var self = this;
|
|
return function() {
|
|
return fn.apply(self, arguments)
|
|
};
|
|
},
|
|
|
|
bindMethodsToObj: function() {
|
|
for (var i = 0; i < arguments.length; i++) {
|
|
this[arguments[i]] = this.bindToObj(this[arguments[i]]);
|
|
};
|
|
},
|
|
|
|
indexFor: function(array, value) {
|
|
for (var i = 0; i < array.length; i++) {
|
|
if (value == array[i]) return i;
|
|
};
|
|
},
|
|
|
|
monthNum: function(jFormComponentDateSelectorMonthName) {
|
|
return this.indexFor(this.jFormComponentDateSelectorMonthNames, jFormComponentDateSelectorMonthName);
|
|
},
|
|
|
|
shortMonthNum: function(jFormComponentDateSelectorMonthName) {
|
|
return this.indexFor(this.short_jFormComponentDateSelectorMonthNames, jFormComponentDateSelectorMonthName);
|
|
},
|
|
|
|
shortDayNum: function(day_name) {
|
|
return this.indexFor(this.short_day_names, day_name);
|
|
},
|
|
|
|
daysBetween: function(start, end) {
|
|
start = Date.UTC(start.getFullYear(), start.getMonth(), start.getDate());
|
|
end = Date.UTC(end.getFullYear(), end.getMonth(), end.getDate());
|
|
return (end - start) / 86400000;
|
|
},
|
|
|
|
changeDayTo: function(dayOfWeek, date, direction) {
|
|
var difference = direction * (Math.abs(date.getDay() - dayOfWeek - (direction * 7)) % 7);
|
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate() + difference);
|
|
},
|
|
|
|
rangeStart: function(date) {
|
|
return this.changeDayTo(this.start_of_week, new Date(date.getFullYear(), date.getMonth()), -1);
|
|
},
|
|
|
|
rangeEnd: function(date) {
|
|
return this.changeDayTo((this.start_of_week - 1) % 7, new Date(date.getFullYear(), date.getMonth() + 1, 0), 1);
|
|
},
|
|
|
|
isFirstDayOfWeek: function(date) {
|
|
return date.getDay() == this.start_of_week;
|
|
},
|
|
|
|
isLastDayOfWeek: function(date) {
|
|
return date.getDay() == (this.start_of_week - 1) % 7;
|
|
},
|
|
|
|
adjustDays: function(days) {
|
|
var newDays = [];
|
|
for (var i = 0; i < days.length; i++) {
|
|
newDays[i] = days[(i + this.start_of_week) % 7];
|
|
};
|
|
return newDays;
|
|
}
|
|
};
|
|
|
|
$.fn.date_input = function(opts) {
|
|
return this.each(function() {
|
|
new DateInput(this, opts);
|
|
});
|
|
};
|
|
$.date_input = {
|
|
initialize: function(opts) {
|
|
$("input.date_input").date_input(opts);
|
|
}
|
|
};
|
|
|
|
return DateInput;
|
|
})(jQuery);
|
|
/// <reference path="../../../lib/jquery-1.2.6.js" />
|
|
/*
|
|
Masked Input plugin for jQuery
|
|
Copyright (c) 2007-2009 Josh Bush (digitalbush.com)
|
|
Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
|
|
Version: 1.2.2 (03/09/2009 22:39:06)
|
|
*/
|
|
(function($) {
|
|
var pasteEventName = ($.browser.msie ? 'paste' : 'input') + ".mask";
|
|
var iPhone = (window.orientation != undefined);
|
|
|
|
$.mask = {
|
|
//Predefined character definitions
|
|
definitions: {
|
|
'9': "[0-9]",
|
|
'a': "[A-Za-z]",
|
|
'*': "[A-Za-z0-9]"
|
|
}
|
|
};
|
|
|
|
$.fn.extend({
|
|
//Helper Function for Caret positioning
|
|
caret: function(begin, end) {
|
|
if (this.length == 0) return;
|
|
if (typeof begin == 'number') {
|
|
end = (typeof end == 'number') ? end : begin;
|
|
return this.each(function() {
|
|
if (this.setSelectionRange) {
|
|
this.focus();
|
|
this.setSelectionRange(begin, end);
|
|
} else if (this.createTextRange) {
|
|
var range = this.createTextRange();
|
|
range.collapse(true);
|
|
range.moveEnd('character', end);
|
|
range.moveStart('character', begin);
|
|
range.select();
|
|
}
|
|
});
|
|
} else {
|
|
if (this[0].setSelectionRange) {
|
|
begin = this[0].selectionStart;
|
|
end = this[0].selectionEnd;
|
|
} else if (document.selection && document.selection.createRange) {
|
|
var range = document.selection.createRange();
|
|
begin = 0 - range.duplicate().moveStart('character', -100000);
|
|
end = begin + range.text.length;
|
|
}
|
|
return { begin: begin, end: end };
|
|
}
|
|
},
|
|
unmask: function() { return this.trigger("unmask"); },
|
|
mask: function(mask, settings) {
|
|
if (!mask && this.length > 0) {
|
|
var input = $(this[0]);
|
|
var tests = input.data("tests");
|
|
return $.map(input.data("buffer"), function(c, i) {
|
|
return tests[i] ? c : null;
|
|
}).join('');
|
|
}
|
|
settings = $.extend({
|
|
placeholder: "_",
|
|
completed: null
|
|
}, settings);
|
|
|
|
var defs = $.mask.definitions;
|
|
var tests = [];
|
|
var partialPosition = mask.length;
|
|
var firstNonMaskPos = null;
|
|
var len = mask.length;
|
|
|
|
$.each(mask.split(""), function(i, c) {
|
|
if (c == '?') {
|
|
len--;
|
|
partialPosition = i;
|
|
} else if (defs[c]) {
|
|
tests.push(new RegExp(defs[c]));
|
|
if(firstNonMaskPos==null)
|
|
firstNonMaskPos = tests.length - 1;
|
|
} else {
|
|
tests.push(null);
|
|
}
|
|
});
|
|
|
|
return this.each(function() {
|
|
var input = $(this);
|
|
var buffer = $.map(mask.split(""), function(c, i) { if (c != '?') return defs[c] ? settings.placeholder : c });
|
|
var ignore = false; //Variable for ignoring control keys
|
|
var focusText = input.val();
|
|
|
|
input.data("buffer", buffer).data("tests", tests);
|
|
|
|
function seekNext(pos) {
|
|
while (++pos <= len && !tests[pos]);
|
|
return pos;
|
|
};
|
|
|
|
function shiftL(pos) {
|
|
while (!tests[pos] && --pos >= 0);
|
|
for (var i = pos; i < len; i++) {
|
|
if (tests[i]) {
|
|
buffer[i] = settings.placeholder;
|
|
var j = seekNext(i);
|
|
if (j < len && tests[i].test(buffer[j])) {
|
|
buffer[i] = buffer[j];
|
|
} else
|
|
break;
|
|
}
|
|
}
|
|
writeBuffer();
|
|
input.caret(Math.max(firstNonMaskPos, pos));
|
|
};
|
|
|
|
function shiftR(pos) {
|
|
for (var i = pos, c = settings.placeholder; i < len; i++) {
|
|
if (tests[i]) {
|
|
var j = seekNext(i);
|
|
var t = buffer[i];
|
|
buffer[i] = c;
|
|
if (j < len && tests[j].test(t))
|
|
c = t;
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
function keydownEvent(e) {
|
|
var pos = $(this).caret();
|
|
var k = e.keyCode;
|
|
ignore = (k < 16 || (k > 16 && k < 32) || (k > 32 && k < 41));
|
|
if(!e.shiftKey){
|
|
if(k==36){
|
|
e.preventDefault();
|
|
$(this).caret(seekNext(0));
|
|
}
|
|
|
|
if(k==35){
|
|
e.preventDefault();
|
|
var tempPos = input.val().indexOf(' ');
|
|
var tempLength = input.val().length;
|
|
while (tests[tempPos] == null || input.val().charAt(tempPos) != ' '){
|
|
tempPos = tempPos + 1;
|
|
if (tempPos == tempLength){
|
|
break;
|
|
}
|
|
}
|
|
$(this).caret(tempPos);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//delete selection before proceeding
|
|
if ((pos.begin - pos.end) != 0 && (!ignore || k == 8 || k == 46))
|
|
clearBuffer(pos.begin, pos.end);
|
|
|
|
//backspace, delete, and escape get special treatment
|
|
if (k == 8 || k == 46 || (iPhone && k == 127)) {//backspace/delete
|
|
shiftL(pos.begin + (k == 46 ? 0 : -1));
|
|
return false;
|
|
} else if (k == 27) {//escape
|
|
input.val(focusText);
|
|
input.caret(0, checkVal());
|
|
return false;
|
|
}
|
|
};
|
|
|
|
function keypressEvent(e) {
|
|
if (ignore) {
|
|
ignore = false;
|
|
//Fixes Mac FF bug on backspace
|
|
return (e.keyCode == 8) ? false : null;
|
|
}
|
|
e = e || window.event;
|
|
var k = e.charCode || e.keyCode || e.which;
|
|
var pos = $(this).caret();
|
|
|
|
if (e.ctrlKey || e.altKey || e.metaKey) {//Ignore
|
|
return true;
|
|
} else if ((k >= 32 && k <= 125) || k > 186) {//typeable characters
|
|
var p = seekNext(pos.begin - 1);
|
|
if (p < len) {
|
|
var c = String.fromCharCode(k);
|
|
if (tests[p].test(c)) {
|
|
shiftR(p);
|
|
buffer[p] = c;
|
|
writeBuffer();
|
|
var next = seekNext(p);
|
|
$(this).caret(next);
|
|
if (settings.completed && next == len)
|
|
settings.completed.call(input);
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
function clearBuffer(start, end) {
|
|
for (var i = start; i < end && i < len; i++) {
|
|
if (tests[i])
|
|
buffer[i] = settings.placeholder;
|
|
}
|
|
};
|
|
|
|
function writeBuffer() { return input.val(buffer.join('')).val(); };
|
|
|
|
function checkVal(allow) {
|
|
//try to place characters where they belong
|
|
var test = input.val();
|
|
var lastMatch = -1;
|
|
for (var i = 0, pos = 0; i < len; i++) {
|
|
if (tests[i]) {
|
|
buffer[i] = settings.placeholder;
|
|
while (pos++ < test.length) {
|
|
var c = test.charAt(pos - 1);
|
|
if (tests[i].test(c)) {
|
|
buffer[i] = c;
|
|
lastMatch = i;
|
|
break;
|
|
}
|
|
}
|
|
if (pos > test.length)
|
|
break;
|
|
} else if (buffer[i] == test[pos] && i!=partialPosition) {
|
|
pos++;
|
|
lastMatch = i;
|
|
}
|
|
}
|
|
if (!allow && lastMatch + 1 < partialPosition) {
|
|
input.val("");
|
|
clearBuffer(0, len);
|
|
} else if (allow || lastMatch + 1 >= partialPosition) {
|
|
writeBuffer();
|
|
if (!allow) input.val(input.val().substring(0, lastMatch + 1));
|
|
}
|
|
return (partialPosition ? i : firstNonMaskPos);
|
|
};
|
|
|
|
if (!input.attr("readonly"))
|
|
input
|
|
.one("unmask", function() {
|
|
input
|
|
.unbind(".mask")
|
|
.removeData("buffer")
|
|
.removeData("tests");
|
|
})
|
|
.bind("focus.mask", function() {
|
|
focusText = input.val();
|
|
var pos = checkVal();
|
|
writeBuffer();
|
|
setTimeout(function() {
|
|
if (pos == mask.length)
|
|
input.caret(0, pos);
|
|
else
|
|
input.caret(pos);
|
|
}, 0);
|
|
})
|
|
.bind("blur.mask", function() {
|
|
checkVal();
|
|
if (input.val() != focusText)
|
|
input.change();
|
|
})
|
|
.bind("keydown.mask", keydownEvent)
|
|
.bind("keypress.mask", keypressEvent)
|
|
.bind(pasteEventName, function() {
|
|
setTimeout(function() { input.caret(checkVal(true)); }, 0);
|
|
});
|
|
|
|
checkVal(); //Perform initial check for existing values
|
|
});
|
|
}
|
|
});
|
|
})(jQuery);/**
|
|
* jQuery.ScrollTo - Easy element scrolling using jQuery.
|
|
* Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
|
|
* Dual licensed under MIT and GPL.
|
|
* Date: 3/9/2009
|
|
* @author Ariel Flesler
|
|
* @version 1.4.1
|
|
*
|
|
* http://flesler.blogspot.com/2007/10/jqueryscrollto.html
|
|
*/
|
|
;(function($){var m=$.scrollTo=function(b,h,f){$(window).scrollTo(b,h,f)};m.defaults={axis:'xy',duration:parseFloat($.fn.jquery)>=1.3?0:1};m.window=function(b){return $(window).scrollable()};$.fn.scrollable=function(){return this.map(function(){var b=this,h=!b.nodeName||$.inArray(b.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!h)return b;var f=(b.contentWindow||b).document||b.ownerDocument||b;return $.browser.safari||f.compatMode=='BackCompat'?f.body:f.documentElement})};$.fn.scrollTo=function(l,j,a){if(typeof j=='object'){a=j;j=0}if(typeof a=='function')a={onAfter:a};if(l=='max')l=9e9;a=$.extend({},m.defaults,a);j=j||a.speed||a.duration;a.queue=a.queue&&a.axis.length>1;if(a.queue)j/=2;a.offset=n(a.offset);a.over=n(a.over);return this.scrollable().each(function(){var k=this,o=$(k),d=l,p,g={},q=o.is('html,body');switch(typeof d){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px)?$/.test(d)){d=n(d);break}d=$(d,this);case'object':if(d.is||d.style)p=(d=$(d)).offset()}$.each(a.axis.split(''),function(b,h){var f=h=='x'?'Left':'Top',i=f.toLowerCase(),c='scroll'+f,r=k[c],s=h=='x'?'Width':'Height';if(p){g[c]=p[i]+(q?0:r-o.offset()[i]);if(a.margin){g[c]-=parseInt(d.css('margin'+f))||0;g[c]-=parseInt(d.css('border'+f+'Width'))||0}g[c]+=a.offset[i]||0;if(a.over[i])g[c]+=d[s.toLowerCase()]()*a.over[i]}else g[c]=d[i];if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],u(s));if(!b&&a.queue){if(r!=g[c])t(a.onAfterFirst);delete g[c]}});t(a.onAfter);function t(b){o.animate(g,j,a.easing,b&&function(){b.call(this,l,a)})};function u(b){var h='scroll'+b;if(!q)return k[h];var f='client'+b,i=k.ownerDocument.documentElement,c=k.ownerDocument.body;return Math.max(i[h],c[h])-Math.min(i[f],c[f])}}).end()};function n(b){return typeof b=='object'?b:{top:b,left:b}}})(jQuery);
|
|
|
|
/**
|
|
* jQuery.LocalScroll - Animated scrolling navigation, using anchors.
|
|
* Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
|
|
* Dual licensed under MIT and GPL.
|
|
* Date: 3/11/2009
|
|
* @author Ariel Flesler
|
|
* @version 1.2.7
|
|
**/
|
|
;(function($){var l=location.href.replace(/#.*/,'');var g=$.localScroll=function(a){$('body').localScroll(a)};g.defaults={duration:1e3,axis:'y',event:'click',stop:true,target:window,reset:true};g.hash=function(a){if(location.hash){a=$.extend({},g.defaults,a);a.hash=false;if(a.reset){var e=a.duration;delete a.duration;$(a.target).scrollTo(0,a);a.duration=e}i(0,location,a)}};$.fn.localScroll=function(b){b=$.extend({},g.defaults,b);return b.lazy?this.bind(b.event,function(a){var e=$([a.target,a.target.parentNode]).filter(d)[0];if(e)i(a,e,b)}):this.find('a,area').filter(d).bind(b.event,function(a){i(a,this,b)}).end().end();function d(){return!!this.href&&!!this.hash&&this.href.replace(this.hash,'')==l&&(!b.filter||$(this).is(b.filter))}};function i(a,e,b){var d=e.hash.slice(1),f=document.getElementById(d)||document.getElementsByName(d)[0];if(!f)return;if(a)a.preventDefault();var h=$(b.target);if(b.lock&&h.is(':animated')||b.onBefore&&b.onBefore.call(b,a,f,h)===false)return;if(b.stop)h.stop(true);if(b.hash){var j=f.id==d?'id':'name',k=$('<a> </a>').attr(j,d).css({position:'absolute',top:$(window).scrollTop(),left:$(window).scrollLeft()});f[j]='';$('body').prepend(k);location=e.hash;k.remove();f[j]=d}h.scrollTo(f,b).trigger('notify.serialScroll',[f])}})(jQuery);
|
|
|
|
/**
|
|
* jQuery[a] - Animated scrolling of series
|
|
* Copyright (c) 2007-2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
|
|
* Dual licensed under MIT and GPL.
|
|
* Date: 3/20/2008
|
|
* @author Ariel Flesler
|
|
* @version 1.2.1
|
|
*
|
|
* http://flesler.blogspot.com/2008/02/jqueryserialscroll.html
|
|
*/
|
|
;(function($){var a='serialScroll',b='.'+a,c='bind',C=$[a]=function(b){$.scrollTo.window()[a](b)};C.defaults={duration:1e3,axis:'x',event:'click',start:0,step:1,lock:1,cycle:1,constant:1};$.fn[a]=function(y){y=$.extend({},C.defaults,y);var z=y.event,A=y.step,B=y.lazy;return this.each(function(){var j=y.target?this:document,k=$(y.target||this,j),l=k[0],m=y.items,o=y.start,p=y.interval,q=y.navigation,r;if(!B)m=w();if(y.force)t({},o);$(y.prev||[],j)[c](z,-A,s);$(y.next||[],j)[c](z,A,s);if(!l.ssbound)k[c]('prev'+b,-A,s)[c]('next'+b,A,s)[c]('goto'+b,t);if(p)k[c]('start'+b,function(e){if(!p){v();p=1;u()}})[c]('stop'+b,function(){v();p=0});k[c]('notify'+b,function(e,a){var i=x(a);if(i>-1)o=i});l.ssbound=1;if(y.jump)(B?k:w())[c](z,function(e){t(e,x(e.target))});if(q)q=$(q,j)[c](z,function(e){e.data=Math.round(w().length/q.length)*q.index(this);t(e,this)});function s(e){e.data+=o;t(e,this)};function t(e,a){if(!isNaN(a)){e.data=a;a=l}var c=e.data,n,d=e.type,f=y.exclude?w().slice(0,-y.exclude):w(),g=f.length,h=f[c],i=y.duration;if(d)e.preventDefault();if(p){v();r=setTimeout(u,y.interval)}if(!h){n=c<0?0:n=g-1;if(o!=n)c=n;else if(!y.cycle)return;else c=g-n-1;h=f[c]}if(!h||d&&o==c||y.lock&&k.is(':animated')||d&&y.onBefore&&y.onBefore.call(a,e,h,k,w(),c)===!1)return;if(y.stop)k.queue('fx',[]).stop();if(y.constant)i=Math.abs(i/A*(o-c));k.scrollTo(h,i,y).trigger('notify'+b,[c])};function u(){k.trigger('next'+b)};function v(){clearTimeout(r)};function w(){return $(m,l)};function x(a){if(!isNaN(a))return a;var b=w(),i;while((i=b.index(a))==-1&&a!=l)a=a.parentNode;return i}})}})(jQuery);/**
|
|
* jquery.simpletip 1.3.1. A simple tooltip plugin
|
|
*
|
|
* Copyright (c) 2009 Craig Thompson
|
|
* http://craigsworks.com
|
|
*
|
|
* Licensed under GPLv3
|
|
* http://www.opensource.org/licenses/gpl-3.0.html
|
|
*
|
|
* Launch : February 2009
|
|
* Version : 1.3.1
|
|
* Released: February 5, 2009 - 11:04am
|
|
*/
|
|
(function($){
|
|
|
|
function Simpletip(elem, conf)
|
|
{
|
|
var self = this;
|
|
elem = jQuery(elem);
|
|
|
|
var wrappedContent = ['<span class="tipArrow"></span><div class="tipContent">',conf.content.html(),'</div>'].join('');
|
|
|
|
var tooltip = jQuery(conf.content)
|
|
.addClass(conf.baseClass)
|
|
.addClass( (conf.fixed) ? conf.fixedClass : '' )
|
|
.addClass( (conf.persistent) ? conf.persistentClass : '' )
|
|
.html(wrappedContent);
|
|
|
|
// Add an event listener that listens for a window resize and repositions the element
|
|
jQuery(window).resize(function(){
|
|
if(tooltip.is(':visible')) {
|
|
self.updatePos();
|
|
}
|
|
|
|
});
|
|
|
|
if(!conf.hidden) tooltip.show();
|
|
else tooltip.hide();
|
|
|
|
if(!conf.persistent)
|
|
{
|
|
elem.hover(
|
|
function(event){
|
|
self.show(event)
|
|
},
|
|
function(){
|
|
self.hide()
|
|
}
|
|
);
|
|
|
|
if(!conf.fixed)
|
|
{
|
|
elem.mousemove( function(event){
|
|
if(tooltip.css('display') !== 'none') self.updatePos(event);
|
|
});
|
|
};
|
|
}
|
|
else
|
|
{
|
|
elem.click(function(event)
|
|
{
|
|
if(event.target === elem.get(0))
|
|
{
|
|
//if(tooltip.css('display') !== 'none')
|
|
// self.hide();
|
|
// else
|
|
//self.show();
|
|
}
|
|
});
|
|
|
|
jQuery(window).mousedown(function(event)
|
|
{
|
|
if(tooltip.css('display') !== 'none')
|
|
{
|
|
var check = (conf.focus) ? jQuery(event.target).parents('.tooltip').andSelf().filter(function(){
|
|
return this === tooltip.get(0)
|
|
}).length : 0;
|
|
//if(check === 0) self.hide();
|
|
};
|
|
});
|
|
};
|
|
|
|
|
|
jQuery.extend(self,
|
|
{
|
|
getVersion: function()
|
|
{
|
|
return [1, 2, 0];
|
|
},
|
|
|
|
getParent: function()
|
|
{
|
|
return elem;
|
|
},
|
|
|
|
getTooltip: function()
|
|
{
|
|
return tooltip;
|
|
},
|
|
|
|
getPos: function()
|
|
{
|
|
return tooltip.position();
|
|
},
|
|
|
|
setPos: function(posX, posY)
|
|
{
|
|
var elemPos = elem.position();
|
|
|
|
if(typeof posX == 'string') posX = parseInt(posX) + elemPos.left;
|
|
if(typeof posY == 'string') posY = parseInt(posY) + elemPos.top;
|
|
|
|
tooltip.css({
|
|
left: posX,
|
|
top: posY
|
|
});
|
|
|
|
return self;
|
|
},
|
|
|
|
show: function(event)
|
|
{
|
|
var onbefore = conf.onBeforeShow();
|
|
if(onbefore === false){
|
|
return false;
|
|
}
|
|
self.updatePos( (conf.fixed) ? null : event );
|
|
|
|
switch(conf.showEffect)
|
|
{
|
|
case 'fade':
|
|
tooltip.fadeIn(conf.showTime); break;
|
|
case 'slide':
|
|
tooltip.slideDown(conf.showTime, self.updatePos); break;
|
|
case 'custom':
|
|
conf.showCustom.call(tooltip, conf.showTime); break;
|
|
default:
|
|
case 'none':
|
|
tooltip.show(); break;
|
|
};
|
|
|
|
tooltip.addClass(conf.activeClass);
|
|
|
|
conf.onShow.call(self);
|
|
|
|
jQuery(document).trigger('blurTip', [tooltip, 'show']);
|
|
|
|
return self;
|
|
},
|
|
|
|
hide: function()
|
|
{
|
|
conf.onBeforeHide.call(self);
|
|
|
|
switch(conf.hideEffect)
|
|
{
|
|
case 'fade':
|
|
tooltip.fadeOut(conf.hideTime); break;
|
|
case 'slide':
|
|
tooltip.slideUp(conf.hideTime); break;
|
|
case 'custom':
|
|
conf.hideCustom.call(tooltip, conf.hideTime); break;
|
|
default:
|
|
case 'none':
|
|
tooltip.hide(); break;
|
|
};
|
|
|
|
tooltip.removeClass(conf.activeClass);
|
|
|
|
conf.onHide.call(self);
|
|
|
|
jQuery(document).trigger('blurTip', [tooltip, 'hide']);
|
|
|
|
return self;
|
|
},
|
|
|
|
update: function(content)
|
|
{
|
|
|
|
//tooltip.html(content);
|
|
|
|
return self;
|
|
},
|
|
|
|
load: function(uri, data)
|
|
{
|
|
conf.beforeContentLoad.call(self);
|
|
|
|
tooltip.load(uri, data, function(){
|
|
conf.onContentLoad.call(self);
|
|
});
|
|
|
|
return self;
|
|
},
|
|
|
|
boundryCheck: function(posX, posY)
|
|
{
|
|
var newX = posX + tooltip.outerWidth();
|
|
var newY = posY + tooltip.outerHeight();
|
|
|
|
var windowWidth = jQuery(window).width() + jQuery(window).scrollLeft();
|
|
var windowHeight = jQuery(window).height() + jQuery(window).scrollTop();
|
|
|
|
return [(newX >= windowWidth), (newY >= windowHeight)];
|
|
},
|
|
|
|
updatePos: function(event)
|
|
{
|
|
var tooltipWidth = tooltip.outerWidth();
|
|
var tooltipHeight = tooltip.outerHeight();
|
|
|
|
if(!event && conf.fixed)
|
|
{
|
|
if(conf.position.constructor == Array)
|
|
{
|
|
posX = parseInt(conf.position[0]);
|
|
posY = parseInt(conf.position[1]);
|
|
}
|
|
else if(jQuery(conf.position).attr('nodeType') === 1)
|
|
{
|
|
var offset = jQuery(conf.position).position();
|
|
posX = offset.left;
|
|
posY = offset.top;
|
|
}
|
|
else
|
|
{
|
|
var elemPos = elem.position();
|
|
var elemWidth = elem.outerWidth();
|
|
var elemHeight = elem.outerHeight();
|
|
var posX = '';
|
|
var posY = '';
|
|
switch(conf.position)
|
|
{
|
|
case 'top':
|
|
posX = elemPos.left - (tooltipWidth / 2) + (elemWidth / 2);
|
|
posY = elemPos.top - tooltipHeight;
|
|
break;
|
|
|
|
case 'bottom':
|
|
posX = elemPos.left - (tooltipWidth / 2) + (elemWidth / 2);
|
|
posY = elemPos.top + elemHeight;
|
|
break;
|
|
|
|
case 'left':
|
|
posX = elemPos.left - tooltipWidth;
|
|
posY = elemPos.top - (tooltipHeight / 2) + (elemHeight / 2);
|
|
break;
|
|
|
|
case 'right':
|
|
posX = elemPos.left + elemWidth;
|
|
posY = elemPos.top - (tooltipHeight / 2) + (elemHeight / 2);
|
|
break;
|
|
|
|
case 'topRight':
|
|
posX = elemPos.left + elemWidth;
|
|
posY = elemPos.top;
|
|
break;
|
|
|
|
default:
|
|
case 'default':
|
|
posX = (elemWidth / 2) + elemPos.left + 20;
|
|
posY = elemPos.top;
|
|
break;
|
|
};
|
|
};
|
|
}
|
|
else
|
|
{
|
|
var posX = event.pageX;
|
|
var posY = event.pageY;
|
|
};
|
|
|
|
if(typeof conf.position != 'object')
|
|
{
|
|
posX = posX + conf.offset[0];
|
|
posY = posY + conf.offset[1];
|
|
|
|
if(conf.boundryCheck)
|
|
{
|
|
var overflow = self.boundryCheck(posX, posY);
|
|
|
|
if(overflow[0]) posX = posX - (tooltipWidth / 2) - (2 * conf.offset[0]);
|
|
if(overflow[1]) posY = posY - (tooltipHeight / 2) - (2 * conf.offset[1]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(typeof conf.position[0] == "string") posX = String(posX);
|
|
if(typeof conf.position[1] == "string") posY = String(posY);
|
|
};
|
|
|
|
self.setPos(posX, posY);
|
|
|
|
return self;
|
|
}
|
|
});
|
|
};
|
|
|
|
jQuery.fn.simpletip = function(conf)
|
|
{
|
|
// Check if a simpletip is already present
|
|
var api = jQuery(this).eq(typeof conf == 'number' ? conf : 0).data("simpletip");
|
|
if(api) return api;
|
|
|
|
// Default configuration
|
|
var defaultConf = {
|
|
// Basics
|
|
content: 'A simple tooltip',
|
|
persistent: false,
|
|
focus: false,
|
|
hidden: true,
|
|
|
|
// Positioning
|
|
position: 'default',
|
|
offset: [0, 0],
|
|
boundryCheck: false,
|
|
fixed: true,
|
|
|
|
// Effects
|
|
showEffect: 'fade',
|
|
showTime: 150,
|
|
showCustom: null,
|
|
hideEffect: 'fade',
|
|
hideTime: 150,
|
|
hideCustom: null,
|
|
|
|
// Selectors and classes
|
|
baseClass: 'tooltip',
|
|
activeClass: 'active',
|
|
fixedClass: 'fixed',
|
|
persistentClass: 'persistent',
|
|
focusClass: 'focus',
|
|
|
|
// Callbacks
|
|
onBeforeShow: function(){
|
|
return true;
|
|
},
|
|
onShow: function(){},
|
|
onBeforeHide: function(){},
|
|
onHide: function(){},
|
|
beforeContentLoad: function(){},
|
|
onContentLoad: function(){}
|
|
};
|
|
jQuery.extend(defaultConf, conf);
|
|
|
|
this.each(function()
|
|
{
|
|
var el = new Simpletip(jQuery(this), defaultConf);
|
|
jQuery(this).data("simpletip", el);
|
|
});
|
|
|
|
return this;
|
|
};
|
|
})();/**
|
|
* jFormer is the steward of the form. Holds base functions which are not specific to any page, section, or component.
|
|
* jFormer is initialized on top of the existing HTML and handles validation, tool tip management, dependencies, instances, triggers, pages, and form submission.
|
|
*
|
|
* @author Kirk Ouimet <kirk@kirkouimet.com>
|
|
* @author Seth Jensen <seth@sethjdesign.com>
|
|
* @version .5
|
|
*/
|
|
JFormer = Class.extend({
|
|
init: function(formId, options) {
|
|
// Keep track of when the form starts initializing (turns off at buttom of init)
|
|
this.initializing = true;
|
|
|
|
// Update the options object
|
|
this.options = $.extend(true, {
|
|
animationOptions: {
|
|
pageScroll: {
|
|
duration: 375,
|
|
adjustHeightDuration: 375
|
|
},
|
|
instance: {
|
|
appearDuration: 0,
|
|
appearEffect: 'fade',
|
|
removeDuration: 0,
|
|
removeEffect: 'fade',
|
|
adjustHeightDuration: 0
|
|
},
|
|
dependency: {
|
|
appearDuration: 250,
|
|
appearEffect: 'fade',
|
|
hideDuration: 100,
|
|
hideEffect: 'fade',
|
|
adjustHeightDuration: 100
|
|
},
|
|
alert: {
|
|
appearDuration: 250,
|
|
appearEffect: 'fade',
|
|
hideDuration: 100,
|
|
hideEffect: 'fade'
|
|
},
|
|
modal: {
|
|
appearDuration: 0,
|
|
hideDuration: 0
|
|
}
|
|
},
|
|
trackBind: false,
|
|
disableAnalytics: false,
|
|
setupPageScroller: true,
|
|
validationTips: true,
|
|
pageNavigator: false,
|
|
saveState: false,
|
|
splashPage: false,
|
|
progressBar: false,
|
|
alertsEnabled: true,
|
|
clientSideValidation: true,
|
|
debugMode: false,
|
|
submitButtonText: 'Submit',
|
|
submitProcessingButtonText: 'Processing...',
|
|
onSubmitStart: function() {return true;},
|
|
onSubmitFinish: function() {return true;}
|
|
}, options.options || {});
|
|
|
|
|
|
// Show number of binds
|
|
if(this.options.trackBind){
|
|
jQuery.fn.bind = function(bind) {
|
|
return function () {
|
|
console.count("jQuery Bind Count");
|
|
console.log("jQuery Bind %o", arguments[0] , this);
|
|
return bind.apply(this, arguments);
|
|
};
|
|
}(jQuery.fn.bind);
|
|
}
|
|
|
|
// Class variables
|
|
this.id = formId;
|
|
this.form = $(['form#',this.id].join(''));
|
|
this.formData = {};
|
|
this.jFormPageWrapper = this.form.find('div.jFormPageWrapper');
|
|
this.jFormPageScroller = this.form.find('div.jFormPageScroller');
|
|
this.jFormPageNavigator = null;
|
|
this.jFormPages = {};
|
|
this.currentJFormPage = null;
|
|
this.maxJFormPageIdArrayIndexReached = null;
|
|
this.jFormPageIdArray = [];
|
|
this.currentJFormPageIdArrayIndex = null;
|
|
this.blurredTips = [];
|
|
this.lastEnabledPage = false;
|
|
|
|
// Stats
|
|
this.initializationTime = (new Date().getTime()) / 1000;
|
|
this.durationInSeconds = 0;
|
|
this.jFormComponentCount = 0;
|
|
|
|
// Controls
|
|
this.control = this.form.find('ul.jFormerControl');
|
|
this.controlNextLi = this.form.find('ul.jFormerControl li.nextLi');
|
|
this.controlNextButton = this.controlNextLi.find('button.nextButton');
|
|
this.controlPreviousLi = this.form.find('ul.jFormerControl li.previousLi');
|
|
this.controlPreviousButton = this.controlPreviousLi.find('button.previousButton');
|
|
|
|
// Save states
|
|
this.saveIntervalSetTimeoutId = null;
|
|
|
|
// Initialize all of the pages
|
|
this.initPages(options.jFormPages);
|
|
|
|
// Add a splash page if enabled
|
|
if(this.options.splashPage !== false || this.options.saveState !== false) {
|
|
if(this.options.splashPage == false) {
|
|
this.options.splashPage = {};
|
|
}
|
|
this.addSplashPage();
|
|
}
|
|
// Set the current page
|
|
else {
|
|
this.currentJFormPageIdArrayIndex = 0;
|
|
this.maxJFormPageIdArrayIndexReached = 0;
|
|
this.currentJFormPage = this.jFormPages[this.jFormPageIdArray[0]];
|
|
this.currentJFormPage.active = true;
|
|
this.currentJFormPage.startTime = (new Date().getTime() / 1000 );
|
|
// Add the page navigator
|
|
if(this.options.pageNavigator !== false) {
|
|
this.addPageNavigator();
|
|
}
|
|
}
|
|
|
|
// Setup the page scroller - mainly CSS changes to width and height
|
|
if(this.options.setupPageScroller) {
|
|
this.setupPageScroller();
|
|
}
|
|
|
|
// Hide all inactive pages
|
|
this.hideInactivePages();
|
|
|
|
// Setup the control buttons
|
|
this.setupControl();
|
|
|
|
// Add a submit button listener
|
|
this.addSubmitListener();
|
|
|
|
// Add enter key listener
|
|
this.addEnterKeyListener();
|
|
|
|
// The blur tip listener
|
|
this.addBlurTipListener();
|
|
|
|
// Check dependencies
|
|
this.checkDependencies(true);
|
|
|
|
// Analytics - disabled for now
|
|
//this.recordAnalytics();
|
|
|
|
// Record when the form is finished initializing
|
|
this.initializing = false;
|
|
|
|
//functions that need to run after the page is completely loaded
|
|
var self = this;
|
|
$(window).load(function(){
|
|
self.adjustHeight();
|
|
});
|
|
},
|
|
|
|
initPages: function(jFormPages) {
|
|
var self = this
|
|
var each = $.each;
|
|
var dependencies = {};
|
|
|
|
each(jFormPages, function(jFormPageKey, jFormPageValue) {
|
|
var jFormPage = new JFormPage(self, jFormPageKey, jFormPageValue.options);
|
|
jFormPage.show();
|
|
|
|
// Handle page level dependencies
|
|
if(jFormPage.options.dependencyOptions !== null) {
|
|
$.each(jFormPage.options.dependencyOptions.dependentOn, function(index, componentId) {
|
|
if(dependencies[componentId] === undefined) {
|
|
dependencies[componentId] = {pages:[],sections:[],components:[]};
|
|
}
|
|
dependencies[componentId].pages.push({jFormPageId:jFormPageKey});
|
|
});
|
|
}
|
|
|
|
each(jFormPageValue.jFormSections, function(jFormSectionKey, jFormSectionValue) {
|
|
var jFormSection = new JFormSection(jFormPage, jFormSectionKey, jFormSectionValue.options);
|
|
|
|
// Handle section level dependencies
|
|
if(jFormSection.options.dependencyOptions !== null) {
|
|
$.each(jFormSection.options.dependencyOptions.dependentOn, function(index, componentId) {
|
|
if(dependencies[componentId] === undefined) {
|
|
dependencies[componentId] = {pages:[],sections:[],components:[]};
|
|
}
|
|
dependencies[componentId].sections.push({jFormPageId:jFormPageKey,jFormSectionId:jFormSectionKey});
|
|
});
|
|
}
|
|
|
|
each(jFormSectionValue.jFormComponents, function(jFormComponentKey, jFormComponentValue) {
|
|
self.jFormComponentCount = self.jFormComponentCount + 1;
|
|
var jFormComponent = new window[jFormComponentValue.type](jFormSection, jFormComponentKey, jFormComponentValue.type, jFormComponentValue.options);
|
|
jFormSection.addComponent(jFormComponent);
|
|
|
|
// Handle component level dependencies
|
|
if(jFormComponent.options.dependencyOptions !== null) {
|
|
$.each(jFormComponent.options.dependencyOptions.dependentOn, function(index, componentId) {
|
|
if(dependencies[componentId] === undefined) {
|
|
dependencies[componentId] = {pages:[],sections:[],components:[]};
|
|
}
|
|
dependencies[componentId].components.push({jFormPageId:jFormPageKey,jFormSectionId:jFormSectionKey,jFormComponentId:jFormComponentKey});
|
|
});
|
|
}
|
|
});
|
|
jFormPage.addSection(jFormSection);
|
|
});
|
|
self.addJFormPage(jFormPage);
|
|
});
|
|
|
|
// Add listeners for all of the components that are being dependent on
|
|
$.each(dependencies, function(componentId, dependentTypes) {
|
|
|
|
$('#'+componentId+':text, textarea#'+componentId).bind('keyup', function(event) {
|
|
$.each(dependentTypes.pages, function(index, object) {
|
|
self.jFormPages[object.jFormPageId].checkDependencies();
|
|
});
|
|
$.each(dependentTypes.sections, function(index, object) {
|
|
self.jFormPages[object.jFormPageId].jFormSections[object.jFormSectionId].checkDependencies();
|
|
});
|
|
$.each(dependentTypes.components, function(index, object) {
|
|
self.jFormPages[object.jFormPageId].jFormSections[object.jFormSectionId].jFormComponents[object.jFormComponentId].checkDependencies();
|
|
});
|
|
});
|
|
|
|
$('#'+componentId+'-wrapper').bind('jFormComponent:changed', function(event) {
|
|
//console.log('running depend check');
|
|
|
|
$.each(dependentTypes.pages, function(index, object) {
|
|
self.jFormPages[object.jFormPageId].checkDependencies();
|
|
});
|
|
$.each(dependentTypes.sections, function(index, object) {
|
|
self.jFormPages[object.jFormPageId].jFormSections[object.jFormSectionId].checkDependencies();
|
|
});
|
|
$.each(dependentTypes.components, function(index, object) {
|
|
//console.log('running a check', componentId, 'for', object.jFormComponentId);
|
|
self.jFormPages[object.jFormPageId].jFormSections[object.jFormSectionId].jFormComponents[object.jFormComponentId].checkDependencies();
|
|
});
|
|
});
|
|
|
|
// Handle instances (this is super kludgy)
|
|
var component = self.select(componentId);
|
|
//console.log(component);
|
|
if(component !== null && component.options.instanceOptions !== null){
|
|
component.options.dependencies = dependentTypes;
|
|
}
|
|
});
|
|
},
|
|
|
|
select: function(jFormComponentId) {
|
|
var componentFound = false,
|
|
component = null;
|
|
$.each(this.jFormPages, function(jFormPageKey, jFormPage){
|
|
$.each(jFormPage.jFormSections, function(sectionKey, sectionObject){
|
|
$.each(sectionObject.jFormComponents, function(componentKey, componentObject){
|
|
if (componentObject.id == jFormComponentId){
|
|
component = componentObject;
|
|
componentFound = true;
|
|
}
|
|
return !componentFound;
|
|
});
|
|
return !componentFound;
|
|
});
|
|
return !componentFound;
|
|
});
|
|
return component;
|
|
},
|
|
|
|
checkDependencies: function(onInit) {
|
|
$.each(this.jFormPages, function(jFormPageKey, jFormPage) {
|
|
jFormPage.checkDependencies();
|
|
|
|
$.each(jFormPage.jFormSections, function(jFormSectionKey, jFormSection) {
|
|
jFormSection.checkDependencies();
|
|
|
|
$.each(jFormSection.jFormComponents, function(jFormComponentKey, jFormComponent) {
|
|
jFormComponent.checkDependencies();
|
|
});
|
|
});
|
|
});
|
|
},
|
|
|
|
addSplashPage: function() {
|
|
var self = this;
|
|
|
|
// Setup the jFormPage for the splash page
|
|
this.options.splashPage.jFormPage = new JFormPage(this, this.form.find('div.jFormerSplashPage').attr('id'));
|
|
this.options.splashPage.jFormPage.addSection(new JFormSection(this.options.splashPage.jFormPage, this.form.find('div.jFormerSplashPage').attr('id') + '-section'));
|
|
this.options.splashPage.jFormPage.page.width(this.form.width());
|
|
this.options.splashPage.jFormPage.active = true;
|
|
this.options.splashPage.jFormPage.startTime = (new Date().getTime() / 1000 );
|
|
|
|
// Set the splash page as the current page
|
|
this.currentJFormPage = this.options.splashPage.jFormPage;
|
|
|
|
// Set the height of the page wrapper to the height of the splash page
|
|
this.jFormPageWrapper.height(this.options.splashPage.jFormPage.page.outerHeight());
|
|
|
|
// If they have a custom button
|
|
if(this.options.splashPage.customButtonId) {
|
|
this.options.splashPage.controlSplashLi = this.form.find('#'+this.options.splashPage.customButtonId);
|
|
this.options.splashPage.controlSplashButton = this.form.find('#'+this.options.splashPage.customButtonId);
|
|
}
|
|
// Use the native control buttons
|
|
else {
|
|
this.options.splashPage.controlSplashLi = this.form.find('li.splashLi');
|
|
this.options.splashPage.controlSplashButton = this.form.find('button.splashButton');
|
|
}
|
|
|
|
// Hide the other native controls
|
|
this.setupControl();
|
|
|
|
// Handle save state options on the splash page
|
|
if(this.options.saveState !== false) {
|
|
self.addSaveStateToSplashPage();
|
|
}
|
|
// If there is no save state, just setup the button to start the form
|
|
else {
|
|
this.options.splashPage.controlSplashButton.bind('click', function(event) {
|
|
event.preventDefault();
|
|
self.beginFormFromSplashPage(false);
|
|
});
|
|
}
|
|
},
|
|
|
|
beginFormFromSplashPage: function(initSaveState, loadForm) {
|
|
var self = this;
|
|
|
|
// Add the page navigator
|
|
if(this.options.pageNavigator !== false && this.jFormPageNavigator == null) {
|
|
this.addPageNavigator();
|
|
this.jFormPageNavigator.show();
|
|
}
|
|
else if(this.options.pageNavigator !== false) {
|
|
this.jFormPageNavigator.show();
|
|
}
|
|
|
|
// Find all of the pages
|
|
var pages = this.form.find('.jFormPage');
|
|
|
|
// Set the width of each page
|
|
pages.css('width', this.form.find('.jFormWrapperContainer').width());
|
|
|
|
// Mark the splash page as inactive
|
|
self.options.splashPage.jFormPage.active = false;
|
|
|
|
if(!loadForm){
|
|
// Set the current page index
|
|
self.currentJFormPageIdArrayIndex = 0;
|
|
|
|
// Scroll to the new page, hide the old page when it is finished
|
|
self.jFormPages[self.jFormPageIdArray[0]].scrollTo({onAfter: function() {
|
|
self.options.splashPage.jFormPage.hide();
|
|
self.renumberPageNavigator();
|
|
}});
|
|
}
|
|
|
|
// Initialize the save state is set
|
|
if(initSaveState) {
|
|
self.initSaveState();
|
|
}
|
|
},
|
|
|
|
addSaveStateToSplashPage: function() {
|
|
var self = this;
|
|
// Initialize the three save state components
|
|
|
|
var sectionId = self.options.splashPage.jFormPage.id + '-section';
|
|
$.each(self.options.saveState.components, function(jFormComponentId, jFormComponentOptions) {
|
|
self.options.splashPage.jFormPage.jFormSections[sectionId].addComponent(new window[jFormComponentOptions.type](self.options.splashPage.jFormPage.jFormSections[sectionId], jFormComponentId, jFormComponentOptions.type, jFormComponentOptions.options));
|
|
});
|
|
|
|
// When they change the option from new to resume, alter the label and peform maintenance
|
|
var formState = 'newForm'; // Default value
|
|
var saveStateJFormComponents = this.options.splashPage.jFormPage.jFormSections[sectionId].jFormComponents;
|
|
saveStateJFormComponents.saveStateStatus.component.find('input:option').bind('click', {context: this}, function(event) {
|
|
// Remove any failure notices
|
|
self.form.find('li.jFormerFailureNotice').remove();
|
|
|
|
formState = $(event.target).val();
|
|
// Change the form to reflect building a new form
|
|
if(formState == 'newForm') {
|
|
saveStateJFormComponents.saveStatePassword.component.find('label').html('Create password: <span class="jFormComponentLabelRequiredStar"> *</span>');
|
|
self.options.splashPage.controlSplashButton.text('Begin');
|
|
}
|
|
// Change the form to reflect resuming a form
|
|
else if(formState == 'resumeForm') {
|
|
saveStateJFormComponents.saveStatePassword.component.find('label').html('Form password: <span class="jFormComponentLabelRequiredStar"> *</span>');
|
|
self.options.splashPage.controlSplashButton.text('Resume');
|
|
}
|
|
});
|
|
|
|
// Add a special event listener to the splash page start button
|
|
self.options.splashPage.controlSplashButton.bind('click', {context: this}, function(event) {
|
|
event.preventDefault();
|
|
|
|
// Remove any failure notice
|
|
self.form.find('li.jFormerFailureNotice').remove();
|
|
|
|
var validateSaveStateIdentifier = saveStateJFormComponents.saveStateIdentifier.validate();
|
|
var validateSaveStatePassword = saveStateJFormComponents.saveStatePassword.validate();
|
|
if(validateSaveStateIdentifier && validateSaveStatePassword) {
|
|
// Set the form button text
|
|
if(formState == 'newForm') {
|
|
//console.log('newForm');
|
|
self.options.splashPage.controlSplashButton.text('Creating form...');
|
|
var formJson = {};
|
|
formJson.meta = {};
|
|
formJson.meta.totalTime = 0;
|
|
formJson.meta.currentPage = self.getActivePage().id;
|
|
formJson.meta.maxPageIndex = self.maxJFormPageIdArrayIndexReached;
|
|
formJson.form = {};
|
|
}
|
|
else {
|
|
self.options.splashPage.controlSplashButton.text('Loading form...');
|
|
}
|
|
|
|
$(event.target).attr('disabled', 'disabled');
|
|
$.ajax({
|
|
url: self.form.attr('action'),
|
|
type: 'post',
|
|
data: {
|
|
'jFormerTask': 'initializeSaveState',
|
|
'identifier': saveStateJFormComponents.saveStateIdentifier.getValue(),
|
|
'password': saveStateJFormComponents.saveStatePassword.getValue(),
|
|
'formState' : formState,
|
|
'formData' : jFormerUtility.jsonEncode(formJson)
|
|
},
|
|
dataType: 'json',
|
|
success: function(json) {
|
|
// If the form was successfully initialized
|
|
if(json.status == 'success'){
|
|
if(formState == 'newForm'){
|
|
self.beginFormFromSplashPage(true, false);
|
|
}
|
|
else if(formState == 'resumeForm') {
|
|
self.beginFormFromSplashPage(true, true);
|
|
|
|
// Set the duration from the form save state
|
|
self.durationInSeconds = json.response.meta.totalTime;
|
|
|
|
// Load the data from the save state
|
|
self.setData(json.response.form);
|
|
|
|
//setup the pageNavigator
|
|
self.maxJFormPageIdArrayIndexReached = json.response.meta.maxPageIndex;
|
|
if(self.options.pageNavigator != null) {
|
|
self.updatePageNavigator();
|
|
}
|
|
|
|
// Scroll to the active page, set in the form save state
|
|
if(self.jFormPages[json.response.meta.currentPage] == undefined){
|
|
json.response.meta.currentPage = self.jFormPages[self.jFormPageIdArray[0]].id;
|
|
}
|
|
|
|
if(self.jFormPages[json.response.meta.currentPage].active === false) {
|
|
self.currentJFormPageIdArrayIndex = $.inArray(json.response.meta.currentPage, self.jFormPageIdArray);
|
|
|
|
self.jFormPages[json.response.meta.currentPage].scrollTo({
|
|
onAfter: function() {
|
|
self.options.splashPage.jFormPage.hide();
|
|
}
|
|
});
|
|
}
|
|
|
|
}
|
|
}
|
|
// If the form already exists
|
|
else if(json.status == 'exists') {
|
|
// Set the form button text
|
|
if(formState == 'newForm') {
|
|
self.options.splashPage.controlSplashButton.text('Begin');
|
|
}
|
|
else {
|
|
self.options.splashPage.controlSplashButton.text('Resume');
|
|
}
|
|
|
|
if(json.response.failureNoticeHtml) {
|
|
self.control.append($('<li class="jFormerFailureNotice jFormComponentValidationFailed">'+json.response.failureNoticeHtml+'</li>'));
|
|
|
|
}
|
|
$(event.target).removeAttr('disabled');
|
|
}
|
|
// If the request failed
|
|
else if(json.status == 'failure') {
|
|
// Set the form button text
|
|
if(formState == 'newForm') {
|
|
self.options.splashPage.controlSplashButton.text('Begin');
|
|
}
|
|
else {
|
|
self.options.splashPage.controlSplashButton.text('Resume');
|
|
}
|
|
|
|
// Set the failure notice
|
|
if(json.response.failureNoticeHtml){
|
|
self.control.append($(['<li class="jFormerFailureNotice jFormComponentValidationFailed">',json.response.failureNoticeHtml,'</li>'].join('')));
|
|
|
|
}
|
|
// Execute any failure javascript
|
|
if(json.response.failureJs){
|
|
eval(json.response.failureJs);
|
|
}
|
|
$(event.target).removeAttr('disabled');
|
|
|
|
}
|
|
},
|
|
error: function(XMLHttpRequest, textStatus, errorThrown){
|
|
self.showAlert('There was a problem initializing the form.');
|
|
self.setupControl();
|
|
}
|
|
});
|
|
}
|
|
// If the save state form does not validate, focus on the first failed component
|
|
else {
|
|
self.options.splashPage.jFormPage.focusOnFirstFailedComponent();
|
|
}
|
|
});
|
|
},
|
|
|
|
addPageNavigator: function(){
|
|
var self = this;
|
|
|
|
this.jFormPageNavigator = this.form.find('.jFormPageNavigator');
|
|
|
|
this.jFormPageNavigator.find('.jFormPageNavigatorLink:first').click(function(event) {
|
|
// Don't scroll to the page if you already on it
|
|
if(self.currentJFormPageIdArrayIndex != 0) {
|
|
self.currentJFormPageIdArrayIndex = 0;
|
|
|
|
self.scrollToPage(self.jFormPageIdArray[0], {
|
|
//onAfter: function() {
|
|
//}
|
|
});
|
|
}
|
|
});
|
|
|
|
// Update the style is right aligned
|
|
if(this.options.pageNavigator.position == 'right'){
|
|
this.form.find('.jFormWrapperContainer').width(this.form.width() - this.jFormPageNavigator.width() - 30);
|
|
}
|
|
},
|
|
|
|
updatePageNavigator: function() {
|
|
var self = this, pageCount, pageIndex;
|
|
for(var i = 1; i <= this.maxJFormPageIdArrayIndexReached + 1; i++) {
|
|
pageCount = i;
|
|
var jFormPageNavigatorLink = $('#navigatePage'+pageCount);
|
|
|
|
// Remove the active class from the page you aren't on
|
|
if(this.currentJFormPageIdArrayIndex != pageCount - 1) {
|
|
jFormPageNavigatorLink.removeClass('jFormPageNavigatorLinkActive');
|
|
}
|
|
// Add the active class to the page you are on
|
|
else {
|
|
jFormPageNavigatorLink.addClass('jFormPageNavigatorLinkActive');
|
|
}
|
|
|
|
// If the page is currently locked
|
|
if(jFormPageNavigatorLink.hasClass('jFormPageNavigatorLinkLocked')){
|
|
// Remove the lock
|
|
jFormPageNavigatorLink.removeClass('jFormPageNavigatorLinkLocked').addClass('jFormPageNavigatorLinkUnlocked');
|
|
|
|
jFormPageNavigatorLink.click(function(event) {
|
|
var target = $(event.target);
|
|
if(!target.is('li')){
|
|
target = target.closest('li');
|
|
}
|
|
|
|
pageIndex = target.attr('id').match(/[0-9]+$/)
|
|
pageIndex = parseInt(pageIndex) - 1;
|
|
|
|
// Perform a silent validation on the page you are leaving
|
|
self.getActivePage().validate(true);
|
|
|
|
// Don't scroll to the page if you already on it
|
|
if(self.currentJFormPageIdArrayIndex != pageIndex) {
|
|
self.scrollToPage(self.jFormPageIdArray[pageIndex]);
|
|
}
|
|
|
|
self.currentJFormPageIdArrayIndex = pageIndex;
|
|
|
|
});
|
|
}
|
|
}
|
|
},
|
|
|
|
renumberPageNavigator: function() {
|
|
$('.jFormPageNavigatorLink:visible').each(function(index, element) {
|
|
// Renumber page link icons
|
|
if($(element).find('span').length > 0) {
|
|
$(element).find('span').html(index+1);
|
|
}
|
|
// Relabel pages that have no title or icons
|
|
else {
|
|
$(element).html('Page '+(index+1));
|
|
}
|
|
});
|
|
},
|
|
|
|
addJFormPage: function(jFormPage) {
|
|
this.jFormPageIdArray.push(jFormPage.id);
|
|
this.jFormPages[jFormPage.id] = jFormPage;
|
|
},
|
|
|
|
removeJFormPage: function(jFormPageId) {
|
|
var self = this;
|
|
|
|
// Remove the HTML
|
|
$('#'+jFormPageId).remove();
|
|
|
|
this.jFormPageIdArray = $.grep(self.jFormPageIdArray, function(value) {
|
|
return value != jFormPageId;
|
|
});
|
|
delete this.jFormPages[jFormPageId];
|
|
},
|
|
|
|
addEnterKeyListener: function() {
|
|
var self = this;
|
|
|
|
// Prevent the default submission on key down
|
|
this.form.bind('keydown', {context:this}, function(event) {
|
|
if(event.keyCode === 13 || event.charCode === 13) {
|
|
if($(event.target).is('textarea')){
|
|
return;
|
|
}
|
|
event.preventDefault();
|
|
}
|
|
});
|
|
|
|
this.form.bind('keyup', {context:this}, function(event) {
|
|
// Get the current page, check to see if you are on the splash page
|
|
var currentPage = self.getActivePage().page;
|
|
|
|
// Listen for the enter key keycode
|
|
if(event.keyCode === 13 || event.charCode === 13) {
|
|
var target = $(event.target);
|
|
// Do nothing if you are on a text area
|
|
if(target.is('textarea')){
|
|
return;
|
|
}
|
|
|
|
// If you are on a button, press it
|
|
if(target.is('button')){
|
|
event.preventDefault();
|
|
target.trigger('click').blur();
|
|
}
|
|
// If you are on a field where pressing enter submits
|
|
else if(target.is('.jFormComponentEnterSubmits')){
|
|
event.preventDefault();
|
|
target.blur();
|
|
self.controlNextButton.trigger('click');
|
|
}
|
|
// If you are on an input that is a check box or radio button, select it
|
|
else if(target.is('input:checkbox')) {
|
|
event.preventDefault();
|
|
target.trigger('click');
|
|
}
|
|
// If you are the last input and you are a password input, submit the form
|
|
else if(target.is('input:password')) {
|
|
event.preventDefault();
|
|
target.blur();
|
|
|
|
// Handle if you are on the splash page
|
|
if(self.options.splashPage !== null && self.currentJFormPage.id == self.options.splashPage.jFormPage.id) {
|
|
self.options.splashPage.controlSplashButton.trigger('click');
|
|
}
|
|
else {
|
|
self.controlNextButton.trigger('click');
|
|
}
|
|
}
|
|
|
|
}
|
|
});
|
|
},
|
|
|
|
addSubmitListener: function(){
|
|
var self = this;
|
|
this.form.bind('submit', {context: this}, function(event) {
|
|
event.preventDefault();
|
|
self.submitEvent(event);
|
|
});
|
|
},
|
|
|
|
initSaveState: function() {
|
|
var self = this, interval = this.options.saveState.interval * 1000;
|
|
if(this.options.saveState === null){
|
|
return;
|
|
}
|
|
this.saveIntervalSetTimeoutId = setInterval(function(){
|
|
self.saveState(self.options.saveState.showSavingAlert);
|
|
}, interval);
|
|
this.saveStateInitialized = true;
|
|
return;
|
|
},
|
|
|
|
saveState: function(showMessage) {
|
|
if(this.saveRunning == true){
|
|
return true;
|
|
}
|
|
this.saveRunning = true;
|
|
var self = this;
|
|
var tempDurationInSeconds = this.durationInSeconds + this.getTimeActive();
|
|
var formJson = {};
|
|
formJson.meta = {};
|
|
formJson.meta.totalTime = tempDurationInSeconds;
|
|
formJson.meta.currentPage = this.getActivePage().id;
|
|
formJson.meta.maxPageIndex = this.maxJFormPageIdArrayIndexReached;
|
|
formJson.form = this.getData();
|
|
$.ajax({
|
|
url: self.form.attr('action'),
|
|
type: 'post',
|
|
data: {
|
|
'jFormerTask': 'saveState',
|
|
'formData': jFormerUtility.jsonEncode(formJson)
|
|
},
|
|
dataType: 'json',
|
|
success: function(json) {
|
|
if(showMessage === true){
|
|
self.showAlert('Saving...');
|
|
}
|
|
self.saveRunning = false;
|
|
},
|
|
error: function(XMLHttpRequest, textStatus, errorThrown){
|
|
if(textStatus != 'error'){
|
|
errorThrown = textStatus ? textStatus : 'unknown';
|
|
}
|
|
self.showAlert('There was an error saving your form, we\'ll try again : '+ errorThrown, 'error');
|
|
self.saveRunning = false;
|
|
}
|
|
});
|
|
},
|
|
|
|
getData: function() {
|
|
var self = this;
|
|
this.formData = {};
|
|
$.each(this.jFormPages, function(jFormKey, jFormPage) {
|
|
self.formData[jFormKey] = jFormPage.getData();
|
|
});
|
|
return this.formData;
|
|
},
|
|
|
|
setData: function(data) {
|
|
|
|
var self = this;
|
|
this.formData = data;
|
|
$.each(data, function(key, page) {
|
|
if(self.jFormPages[key] != undefined){
|
|
self.jFormPages[key].setData(page);
|
|
} else {
|
|
return;
|
|
}
|
|
});
|
|
return this.formData;
|
|
},
|
|
|
|
setupPageScroller: function(options) {
|
|
var self = this;
|
|
|
|
// Set some default values for the options
|
|
|
|
var defaultOptions = {
|
|
adjustHeightDuration: 0,
|
|
jFormWrapperContainerWidth : self.form.find('.jFormWrapperContainer').width(),
|
|
jFormPageWrapperWidth : self.jFormPageWrapper.width(),
|
|
activePageOuterHeight : self.getActivePage().page.outerHeight()
|
|
};
|
|
|
|
options = $.extend(defaultOptions, options);
|
|
|
|
|
|
// Find all of the pages
|
|
var pages = this.form.find('.jFormPage');
|
|
|
|
// Set the width of each page
|
|
pages.css('width', options.jFormWrapperContainerWidth).show();
|
|
|
|
// Set the width of the scroller
|
|
self.jFormPageScroller.css('width', options.jFormPageWrapperWidth * (pages.length + 1));
|
|
|
|
// Set the height of the wrapper
|
|
self.jFormPageWrapper.height(options.activePageOuterHeight);
|
|
|
|
// Scroll to the current page (prevent weird Firefox bug where the page does not display on soft refresh
|
|
self.scrollToPage(self.currentJFormPage.id, options);
|
|
},
|
|
|
|
setupControl: function() {
|
|
|
|
//console.log('setting up control');
|
|
|
|
var self = this;
|
|
// console.log(this.currentJFormPageIdArrayIndex);
|
|
// Setup event listener for next button
|
|
this.controlNextButton.unbind().click(function(event) {
|
|
event.preventDefault();
|
|
event['context'] = self;
|
|
self.submitEvent(event);
|
|
}).removeAttr('disabled');
|
|
|
|
//check to see if this is the last enabled page.
|
|
this.lastEnabledPage = false;
|
|
for(i = this.jFormPageIdArray.length - 1 ; i > this.currentJFormPageIdArrayIndex; i--){
|
|
if(!this.jFormPages[this.jFormPageIdArray[i]].disabledByDependency){
|
|
this.lastEnabledPage = false;
|
|
break;
|
|
}
|
|
this.lastEnabledPage = true;
|
|
}
|
|
|
|
// Setup event listener for previous button
|
|
this.controlPreviousButton.unbind().click(function(event) {
|
|
event.preventDefault();
|
|
|
|
// Be able to return to the splash page
|
|
if(self.options.splashPage !== false && self.currentJFormPageIdArrayIndex === 0) {
|
|
self.currentJFormPageIdArrayIndex = null;
|
|
if(self.jFormPageNavigator){
|
|
self.jFormPageNavigator.hide();
|
|
}
|
|
self.options.splashPage.jFormPage.scrollTo();
|
|
}
|
|
// Scroll to the previous page
|
|
else {
|
|
if(self.jFormPages[self.jFormPageIdArray[self.currentJFormPageIdArrayIndex - 1]].disabledByDependency){
|
|
for(var i = 1; i <= self.currentJFormPageIdArrayIndex; i++){
|
|
var nextIndex = self.currentJFormPageIdArrayIndex - i;
|
|
if(nextIndex == 0 && self.options.splashPage !== false && self.jFormPages[self.jFormPageIdArray[nextIndex]].disabledByDependency ){
|
|
if(self.jFormPageNavigator){
|
|
self.jFormPageNavigator.hide();
|
|
}
|
|
self.options.splashPage.jFormPage.scrollTo();
|
|
break;
|
|
}
|
|
else if(!self.jFormPages[self.jFormPageIdArray[nextIndex]].disabledByDependency){
|
|
self.currentJFormPageIdArrayIndex = nextIndex;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
self.currentJFormPageIdArrayIndex = self.currentJFormPageIdArrayIndex - 1;
|
|
}
|
|
self.scrollToPage(self.jFormPageIdArray[self.currentJFormPageIdArrayIndex]);
|
|
}
|
|
});
|
|
|
|
// First page with more pages after, or splash page
|
|
if(this.currentJFormPageIdArrayIndex === 0 && this.currentJFormPageIdArrayIndex != this.jFormPageIdArray.length - 1 && this.lastEnabledPage === false) {
|
|
this.controlNextButton.html('Next');
|
|
this.controlNextLi.show();
|
|
this.controlPreviousLi.hide();
|
|
this.controlPreviousButton.attr('disabled', 'disabled');
|
|
}
|
|
// Last page
|
|
else if(self.currentJFormPageIdArrayIndex == this.jFormPageIdArray.length - 1 || this.lastEnabledPage === true) {
|
|
this.controlNextButton.html(this.options.submitButtonText);
|
|
this.controlNextLi.show();
|
|
|
|
// First page is the last page
|
|
if(self.currentJFormPageIdArrayIndex === 0 ) {
|
|
// Hide the previous button
|
|
this.controlPreviousLi.hide();
|
|
this.controlPreviousButton.attr('disabled', '');
|
|
}
|
|
// There is a previous page
|
|
else if(self.currentJFormPageIdArrayIndex > 0) {
|
|
this.controlPreviousButton.removeAttr('disabled');
|
|
this.controlPreviousLi.show();
|
|
}
|
|
}
|
|
// Middle page with a previous and a next
|
|
else {
|
|
this.controlNextButton.html('Next');
|
|
this.controlNextLi.show();
|
|
this.controlPreviousButton.removeAttr('disabled');
|
|
this.controlPreviousLi.show();
|
|
}
|
|
|
|
// Splash page
|
|
if(this.options.splashPage !== false) {
|
|
// If you are on the splash page
|
|
if(this.options.splashPage.jFormPage.active) {
|
|
this.options.splashPage.controlSplashLi.show();
|
|
this.controlNextLi.hide();
|
|
this.controlPreviousLi.hide();
|
|
this.controlPreviousButton.attr('disabled', 'disabled');
|
|
}
|
|
// If you aren't on the splash page, don't show the splash button
|
|
else {
|
|
this.options.splashPage.controlSplashLi.hide();
|
|
}
|
|
|
|
// If you are on the first page
|
|
if(this.currentJFormPageIdArrayIndex === 0 && this.options.saveState == false) {
|
|
this.controlPreviousButton.removeAttr('disabled');
|
|
this.controlPreviousLi.show();
|
|
}
|
|
}
|
|
|
|
// Failure page
|
|
if(this.control.find('.startOver').length == 1){
|
|
// Hide the other buttons
|
|
this.controlNextLi.hide();
|
|
this.controlPreviousLi.hide();
|
|
|
|
// Bind an event listener to the start over button
|
|
this.control.find('.startOver').one('click', function(event){
|
|
event.preventDefault();
|
|
self.currentJFormPageIdArrayIndex = 0;
|
|
self.scrollToPage(self.jFormPageIdArray[0], {
|
|
onAfter: function(){
|
|
// Remove the start over button
|
|
$(event.target).parent().remove();
|
|
self.removeJFormPage(self.id+'jFormPageFailure');
|
|
}
|
|
});
|
|
});
|
|
}
|
|
},
|
|
|
|
scrollToPage: function(jFormPageId, options) {
|
|
//console.log('JFormer('+this.id+'):scrollToPage', jFormPageId, options);
|
|
|
|
// Prevent scrolling to dependency disabled pages
|
|
if(this.jFormPages[jFormPageId] && this.jFormPages[jFormPageId].disabledByDependency) {
|
|
return false;
|
|
}
|
|
|
|
var self = this;
|
|
|
|
// Disable buttons
|
|
this.controlNextButton.attr('disabled', true);
|
|
this.controlPreviousButton.attr('disabled', true);
|
|
|
|
// Handle page specific onScrollTo onBefore custom function
|
|
if(this.jFormPages[jFormPageId] && this.jFormPages[jFormPageId].options.onScrollTo.onBefore !== null) {
|
|
// put a notice up if defined
|
|
if(this.jFormPages[jFormPageId].options.onScrollTo.notificationHtml !== undefined) {
|
|
if(self.control.find('.jformerScrollToNotification').length != 0 ){
|
|
self.control.find('.jformerScrollToNotification').html(this.jFormPages[jFormPageId].options.onScrollTo.notificationHtml);
|
|
} else {
|
|
self.control.append('<li class="jformerScrollToNotification">'+this.jFormPages[jFormPageId].options.onScrollTo.notificationHtml+'<li>');
|
|
}
|
|
|
|
}
|
|
this.jFormPages[jFormPageId].options.onScrollTo.onBefore();
|
|
}
|
|
|
|
// Remember the active duration time of the page
|
|
var oldJFormPage = this.getActivePage();
|
|
oldJFormPage.durationActiveInSeconds = oldJFormPage.durationActiveInSeconds + oldJFormPage.getTimeActive();
|
|
|
|
// Show every page so you can see them as you scroll through
|
|
$.each(this.jFormPages, function(jFormPageKey, jFormPage) {
|
|
jFormPage.show();
|
|
jFormPage.active = false;
|
|
});
|
|
|
|
// If on the splash page, set the current page to the splash page
|
|
if(self.options.splashPage !== false && jFormPageId == self.options.splashPage.jFormPage.id) {
|
|
self.currentJFormPage = self.options.splashPage.jFormPage;
|
|
self.currentJFormPage.show();
|
|
}
|
|
// Set the current page to the new page
|
|
else {
|
|
this.currentJFormPage = this.jFormPages[jFormPageId];
|
|
}
|
|
|
|
// Mark the current page as active
|
|
this.currentJFormPage.active = true;
|
|
|
|
// Adjust the height of the page wrapper
|
|
// If there is a custom adjust height duration
|
|
if(options && options.adjustHeightDuration !== undefined) {
|
|
self.adjustHeight({adjustHeightDuration: options.adjustHeightDuration});
|
|
}
|
|
else {
|
|
self.adjustHeight();
|
|
}
|
|
|
|
// Run the next animation immediately
|
|
this.jFormPageWrapper.dequeue();
|
|
|
|
// Scroll the document the top of the form
|
|
this.scrollToTop();
|
|
|
|
// PageWrapper is like a viewport - this scrolls to the top of the new page, but the document needs to be scrolled too
|
|
var initializing = this.initializing;
|
|
this.jFormPageWrapper.scrollTo(
|
|
self.currentJFormPage.page,
|
|
self.options.animationOptions.pageScroll.duration,
|
|
{
|
|
onAfter: function() {
|
|
// Don't hide any pages while scrolling
|
|
if($(self.jFormPageWrapper).queue('fx').length <= 1 ) {
|
|
self.hideInactivePages(self.getActivePage());
|
|
}
|
|
|
|
// Set the max page reach indexed
|
|
if(self.maxJFormPageIdArrayIndexReached < self.currentJFormPageIdArrayIndex) {
|
|
self.maxJFormPageIdArrayIndexReached = self.currentJFormPageIdArrayIndex;
|
|
}
|
|
|
|
// Update the page navigator
|
|
self.updatePageNavigator();
|
|
|
|
// Start the time for the new page
|
|
self.currentJFormPage.startTime = (new Date().getTime()/1000);
|
|
|
|
// Run any special functions
|
|
if(options && options.onAfter) {
|
|
options.onAfter();
|
|
}
|
|
// Setup the controls
|
|
self.setupControl();
|
|
|
|
// Enable the buttons again
|
|
self.controlNextButton.removeAttr('disabled').blur();
|
|
self.controlPreviousButton.removeAttr('disabled').blur();
|
|
|
|
// Focus on the first failed component, if it is failed,
|
|
if(self.currentJFormPage.validationPassed === false && !initializing){
|
|
self.currentJFormPage.focusOnFirstFailedComponent();
|
|
}
|
|
|
|
// Handle page specific onScrollTo onAfter custom function
|
|
if(self.jFormPages[jFormPageId] && self.jFormPages[jFormPageId].options.onScrollTo.onAfter !== null) {
|
|
self.jFormPages[jFormPageId].options.onScrollTo.onAfter();
|
|
if(self.jFormPages[jFormPageId].options.onScrollTo.notificationHtml !== null) {
|
|
self.control.find('li.jFormerScrollToNotification').remove();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
return this;
|
|
},
|
|
|
|
scrollToTop: function() {
|
|
if(this.initializing) {
|
|
return;
|
|
}
|
|
|
|
var self = this;
|
|
// Only scroll if the top of the form is not visible
|
|
if($(window).scrollTop() > this.form.offset().top) {
|
|
$(document).scrollTo(self.form, self.options.animationOptions.pageScroll.duration, {
|
|
offset: {
|
|
top: -10
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
getActivePage: function() {
|
|
// if active page has not been set
|
|
return this.currentJFormPage;
|
|
},
|
|
|
|
getTimeActive: function(){
|
|
var currentTotal = 0;
|
|
$.each(this.jFormPages, function(key, page){
|
|
currentTotal = currentTotal + page.durationActiveInSeconds;
|
|
});
|
|
currentTotal = currentTotal + this.getActivePage().getTimeActive();
|
|
return currentTotal;
|
|
},
|
|
|
|
hideInactivePages: function(){
|
|
$.each(this.jFormPages, function(jFormPageKey, jFormPage){
|
|
jFormPage.hide();
|
|
});
|
|
},
|
|
|
|
clearValidation: function() {
|
|
$.each(this.jFormPages, function(jFormPageKey, jFormPage){
|
|
jFormPage.clearValidation();
|
|
});
|
|
},
|
|
|
|
submitEvent: function(event) {
|
|
var self = this;
|
|
//console.log('last enabled page', self.lastEnabledPage);
|
|
// Stop the event no matter what
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
|
|
// Remove any failure notices
|
|
self.control.find('.jFormerFailureNotice').remove();
|
|
self.form.find('.jFormerFailure').remove();
|
|
|
|
// Run a custom function at beginning of the form submission
|
|
var onSubmitStartResult;
|
|
if(typeof(self.options.onSubmitStart) != 'function') {
|
|
onSubmitStartResult = eval(self.options.onSubmitStart);
|
|
}
|
|
else {
|
|
onSubmitStartResult = self.options.onSubmitStart();
|
|
}
|
|
|
|
// Validate the current page if you are not the last page
|
|
var clientSideValidationPassed = false;
|
|
if(this.options.clientSideValidation) {
|
|
if(self.currentJFormPageIdArrayIndex < self.jFormPageIdArray.length - 1 && !self.lastEnabledPage) {
|
|
//console.log('Validating single page.');
|
|
clientSideValidationPassed = self.getActivePage().validate();
|
|
}
|
|
else {
|
|
//console.log('Validating whole form.');
|
|
clientSideValidationPassed = self.validateAll();
|
|
}
|
|
}
|
|
// Ignore client side validation
|
|
else {
|
|
this.clearValidation();
|
|
clientSideValidationPassed = true;
|
|
}
|
|
|
|
// Run any custom functions at the end of the validation
|
|
var onSubmitFinishResult = self.options.onSubmitFinish();
|
|
|
|
// If the custom finish function returns false, do not submit the form
|
|
if(onSubmitFinishResult) {
|
|
// Last page, submit the form
|
|
//console.log(clientSideValidationPassed && (self.currentJFormPageIdArrayIndex == self.jFormPageIdArray.length - 1) || (self.lastEnabledPage === true ));
|
|
if(clientSideValidationPassed && (self.currentJFormPageIdArrayIndex == self.jFormPageIdArray.length - 1) || (self.lastEnabledPage === true )) {
|
|
self.submitForm(event);
|
|
}
|
|
// Not last page, scroll to the next page
|
|
else if(clientSideValidationPassed && self.currentJFormPageIdArrayIndex < self.jFormPageIdArray.length - 1) {
|
|
// if the next page is disabled by dependency, loop through till you find a good page.
|
|
if(self.jFormPages[self.jFormPageIdArray[self.currentJFormPageIdArrayIndex + 1]].disabledByDependency){
|
|
for(var i = self.currentJFormPageIdArrayIndex + 1; i <= self.jFormPageIdArray.length - 1; i++){
|
|
// page is enabled, set the proper index, and break out of the loop.
|
|
if(!self.jFormPages[self.jFormPageIdArray[self.currentJFormPageIdArrayIndex + i]].disabledByDependency){
|
|
self.currentJFormPageIdArrayIndex = self.currentJFormPageIdArrayIndex + i;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
self.currentJFormPageIdArrayIndex = self.currentJFormPageIdArrayIndex + 1;
|
|
}
|
|
self.scrollToPage(self.jFormPageIdArray[self.currentJFormPageIdArrayIndex]);
|
|
}
|
|
}
|
|
},
|
|
|
|
validateAll: function(){
|
|
var self = this;
|
|
var validationPassed = true;
|
|
var index = 0;
|
|
$.each(this.jFormPages, function(jFormPageKey, jFormPage) {
|
|
var passed = jFormPage.validate();
|
|
//console.log(jFormPage.id, 'passed', passed);
|
|
if(passed === false) {
|
|
//console.log('something went wrong' );
|
|
self.currentJFormPageIdArrayIndex = index;
|
|
if(self.currentJFormPage.id != jFormPage.id) {
|
|
jFormPage.scrollTo();
|
|
}
|
|
validationPassed = false;
|
|
return false; // Break out of the .each
|
|
}
|
|
index++;
|
|
});
|
|
return validationPassed;
|
|
},
|
|
|
|
adjustHeight: function(options) {
|
|
//console.log('jFormer:adjustHeight', options)
|
|
|
|
var self = this;
|
|
var duration = this.options.animationOptions.pageScroll.adjustHeightDuration;
|
|
|
|
// Use custom one time duration settings
|
|
if(this.initializing){
|
|
duration = 0;
|
|
}else if(options && options.adjustHeightDuration !== undefined) {
|
|
duration = options.adjustHeightDuration;
|
|
}
|
|
|
|
this.jFormPageWrapper.animate({
|
|
'height' : self.getActivePage().page.outerHeight()
|
|
}, duration);
|
|
},
|
|
|
|
submitForm: function(event) {
|
|
var self = this;
|
|
|
|
// Use a temporary form targeted to the iframe to submit the results
|
|
var formClone = this.form.clone(false);
|
|
formClone.attr('id', formClone.attr('id')+'-clone');
|
|
formClone.attr('style', 'display: none;');
|
|
formClone.empty();
|
|
formClone.appendTo($(this.form).parent());
|
|
// Wrap all of the form responses into an object based on the component jFormComponentType
|
|
var formData = $('<input type="hidden" name="jFormer" />').attr('value', encodeURI(jFormerUtility.jsonEncode(this.getData()))); // Set all non-file values in one form object
|
|
var formIdentifier = $('<input type="hidden" name="jFormerId" value="'+this.id+'" />');
|
|
formClone.append(formData);
|
|
formClone.append(formIdentifier);
|
|
|
|
|
|
this.form.find('input:file').each(function(index, fileInput) {
|
|
if($(fileInput).val() != '') {
|
|
// grab the IDs needed to pass
|
|
var sectionId = $(fileInput).closest('.jFormSection').attr('id');
|
|
var pageId = $(fileInput).closest('.jFormPage').attr('id');
|
|
//var fileInput = $(fileInput).clone()
|
|
|
|
// do find out the section instance index
|
|
if($(fileInput).attr('id').match(/-section[0-9]+/)){
|
|
var sectionInstance = null;
|
|
var section = $(fileInput).closest('.jFormSection');
|
|
// grab the base id of the section to find all sister sections
|
|
var sectionBaseId = section.attr('id').replace(/-section[0-9]+/, '') ;
|
|
sectionId = sectionId.replace(/-section[0-9]+/, '');
|
|
// Find out which instance it is
|
|
section.closest('.jFormPage').find('div[id*='+sectionBaseId+']').each(function(index, fileSection){
|
|
if(section.attr('id') == $(fileSection).attr('id')){
|
|
sectionInstance = index + 1;
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
fileInput.attr('name', fileInput.attr('name').replace(/-section[0-9]+/, '-section'+sectionInstance));
|
|
}
|
|
|
|
// do find out the component instance index
|
|
if($(fileInput).attr('id').match(/-instance[0-9]+/)){
|
|
// grab the base id of the component to find all sister components
|
|
var baseId = $(fileInput).attr('id').replace(/-instance[0-9]+/, '')
|
|
var instance = null;
|
|
// Find out which instance it is
|
|
$(fileInput).closest('.jFormSection').find('input[id*='+baseId+']').each(function(index, fileComponent){
|
|
if($(fileComponent).attr('id') == $(fileInput).attr('id')){
|
|
instance = index + 1;
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
fileInput.attr('name', $(fileInput).attr('name').replace(/-instance[0-9]+/, '-instance'+instance));
|
|
}
|
|
|
|
$(fileInput).attr('name', $(fileInput).attr('name')+':'+pageId+':'+sectionId);
|
|
$(fileInput).appendTo(formClone);
|
|
}
|
|
});
|
|
|
|
/*
|
|
|
|
// Add any file components for submission
|
|
this.form.find('input:file').each(function(index, fileInput) {
|
|
if($(fileInput).val() != '') {
|
|
// grab the IDs needed to pass
|
|
var sectionId = $(fileInput).closest('.jFormSection').attr('id');
|
|
var pageId = $(fileInput).closest('.jFormPage').attr('id');
|
|
var clone = $(fileInput).clone()
|
|
|
|
// do find out the section instance index
|
|
if($(fileInput).attr('id').match(/-section[0-9]+/)){
|
|
var sectionInstance = null;
|
|
var section = $(fileInput).closest('.jFormSection');
|
|
// grab the base id of the section to find all sister sections
|
|
var sectionBaseId = section.attr('id').replace(/-section[0-9]+/, '') ;
|
|
sectionId = sectionId.replace(/-section[0-9]+/, '');
|
|
// Find out which instance it is
|
|
section.closest('.jFormPage').find('div[id*='+sectionBaseId+']').each(function(index, fileSection){
|
|
if(section.attr('id') == $(fileSection).attr('id')){
|
|
sectionInstance = index + 1;
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
clone.attr('name', clone.attr('name').replace(/-section[0-9]+/, '-section'+sectionInstance));
|
|
}
|
|
|
|
// do find out the component instance index
|
|
if($(fileInput).attr('id').match(/-instance[0-9]+/)){
|
|
// grab the base id of the component to find all sister components
|
|
var baseId = $(fileInput).attr('id').replace(/-instance[0-9]+/, '')
|
|
var instance = null;
|
|
// Find out which instance it is
|
|
$(fileInput).closest('.jFormSection').find('input[id*='+baseId+']').each(function(index, fileComponent){
|
|
if($(fileComponent).attr('id') == $(fileInput).attr('id')){
|
|
instance = index + 1;
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
clone.attr('name', clone.attr('name').replace(/-instance[0-9]+/, '-instance'+instance));
|
|
}
|
|
|
|
clone.attr('name', clone.attr('name')+':'+pageId+':'+sectionId);
|
|
clone.appendTo(formClone);
|
|
}
|
|
});
|
|
*/
|
|
|
|
// Submit the form
|
|
formClone.submit();
|
|
formClone.remove(); // Ninja vanish!
|
|
|
|
// Find the submit button and the submit response
|
|
if(!this.options.debugMode){
|
|
this.controlNextButton.text(this.options.submitProcessingButtonText).attr('disabled', 'disabled');
|
|
}
|
|
else {
|
|
this.form.find('iframe:hidden').show();
|
|
}
|
|
},
|
|
|
|
handleFormSubmissionResponse: function(json) {
|
|
var self = this;
|
|
|
|
// Form failed processing
|
|
if(json.status == 'failure') {
|
|
// Handle validation failures
|
|
if(json.response.validationFailed) {
|
|
$.each(json.response.validationFailed, function(jFormPageKey, jFormPageValues){
|
|
$.each(jFormPageValues, function(jFormSectionKey, jFormSectionValues){
|
|
// Handle section instances
|
|
if($.isArray(jFormSectionValues)) {
|
|
$.each(jFormSectionValues, function(jFormSectionInstanceIndex, jFormSectionInstanceValues){
|
|
var sectionKey;
|
|
if(jFormSectionInstanceIndex != 0) {
|
|
sectionKey = '-section'+(jFormSectionInstanceIndex + 1);
|
|
}
|
|
else {
|
|
sectionKey = '';
|
|
}
|
|
$.each(jFormSectionInstanceValues, function(jFormComponentKey, jFormComponentErrors) {
|
|
self.jFormPages[jFormPageKey].jFormSections[jFormSectionKey].instanceArray[jFormSectionInstanceIndex].jFormComponents[jFormComponentKey + sectionKey].handleServerValidationResponse(jFormComponentErrors);
|
|
});
|
|
});
|
|
}
|
|
// There are no section instances
|
|
else {
|
|
$.each(jFormSectionValues, function(jFormComponentKey, jFormComponentErrors){
|
|
self.jFormPages[jFormPageKey].jFormSections[jFormSectionKey].jFormComponents[jFormComponentKey].handleServerValidationResponse(jFormComponentErrors);
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// Show the failureHtml if there was a problem
|
|
if(json.response.failureHtml) {
|
|
// Update the failure HTML
|
|
this.control.find('.jFormerFailure').remove();
|
|
this.control.after('<div class="jFormerFailure">'+json.response.failureHtml+'</div>');
|
|
}
|
|
|
|
// Strip the script out of the iframe
|
|
this.form.find('iframe').contents().find('body script').remove();
|
|
if(this.form.find('iframe').contents().find('body').html() !== null) {
|
|
this.form.find('.jFormerFailure').append('<p>Output:</p>'+this.form.find('iframe').contents().find('body').html().trim());
|
|
}
|
|
|
|
// Reset the page, focus on the first failed component
|
|
this.controlNextButton.text(this.options.submitButtonText);
|
|
this.controlNextButton.removeAttr('disabled');
|
|
this.getActivePage().focusOnFirstFailedComponent();
|
|
}
|
|
// Form passed processing
|
|
else if(json.status == 'success'){
|
|
// Show a success page
|
|
if(json.response.successPageHtml){
|
|
// Stop saving the form
|
|
clearInterval(this.saveIntervalSetTimeoutId);
|
|
|
|
// Create the success page html
|
|
var successPageDiv = $('<div id="'+this.id+'jFormPageSuccess" class="jFormPage jFormPageSuccess">'+json.response.successPageHtml+'</div>');
|
|
successPageDiv.width(this.jFormPages[this.jFormPageIdArray[0]].page.width());
|
|
this.jFormPageScroller.append(successPageDiv);
|
|
|
|
// Create the success page
|
|
var jFormPageSuccess = new JFormPage(this, this.id+'jFormPageSuccess');
|
|
this.addJFormPage(jFormPageSuccess);
|
|
|
|
// Hide the page navigator and controls
|
|
this.control.hide();
|
|
if(this.jFormPageNavigator) {
|
|
this.jFormPageNavigator.hide();
|
|
}
|
|
|
|
// Scroll to the page
|
|
jFormPageSuccess.scrollTo();
|
|
}
|
|
// Show a failure page that allows you to go back
|
|
else if(json.response.failurePageHtml){
|
|
// Create the failure page html
|
|
var failurePageDiv = $('<div id="'+this.id+'jFormPageFailure" class="jFormPage jFormPageFailure">'+json.response.failurePageHtml+'</div>');
|
|
failurePageDiv.width(this.jFormPages[this.jFormPageIdArray[0]].page.width());
|
|
this.jFormPageScroller.append(failurePageDiv);
|
|
|
|
// Create the failure page
|
|
var jFormPageFailure = new JFormPage(this, this.id+'jFormPageFailure');
|
|
this.addJFormPage(jFormPageFailure);
|
|
|
|
// Create a start over button
|
|
this.control.append($('<li class="startOver"><button class="startOverButton">Start Over</button></li>'));
|
|
|
|
// Scroll to the failure page
|
|
jFormPageFailure.scrollTo();
|
|
}
|
|
// Show a failure notice on the same page
|
|
if(json.response.failureNoticeHtml){
|
|
this.control.find('.jFormerFailureNotice').remove();
|
|
this.control.append('<li class="jFormerFailureNotice">'+json.response.failureNoticeHtml+'</li>');
|
|
this.controlNextButton.text(this.options.submitButtonText);
|
|
this.controlNextButton.removeAttr('disabled');
|
|
}
|
|
|
|
// Show a large failure response on the same page
|
|
if(json.response.failureHtml){
|
|
this.control.find('.jFormerFailure').remove();
|
|
this.control.after('<div class="jFormerFailure">'+json.response.failureHtml+'</div>');
|
|
this.controlNextButton.text(this.options.submitButtonText);
|
|
this.controlNextButton.removeAttr('disabled');
|
|
}
|
|
|
|
// Evaluate any failure or successful javascript
|
|
if(json.response.successJs){
|
|
eval(json.response.successJs);
|
|
}
|
|
else if(json.response.failureJs){
|
|
eval(json.response.failureJs);
|
|
}
|
|
|
|
// Redirect the user
|
|
if(json.response.redirect){
|
|
this.controlNextButton.html('Redirecting...');
|
|
document.location = json.response.redirect;
|
|
}
|
|
}
|
|
},
|
|
|
|
showAlert: function(message, jFormComponentType, modal, options){
|
|
if(!this.options.alertsEnabled){
|
|
return;
|
|
}
|
|
var animationOptions = $.extend(this.options.animationOptions.alert, options);
|
|
|
|
|
|
var alertWrapper = this.form.find('.jFormerAlertWrapper');
|
|
var alertDiv = this.form.find('.jFormerAlert');
|
|
|
|
alertDiv.addClass(jFormComponentType);
|
|
alertDiv.text(message);
|
|
|
|
// Show the message
|
|
if(animationOptions.appearEffect == 'slide'){
|
|
alertWrapper.slideDown(animationOptions.appearDuration, function(){
|
|
// hide the message
|
|
setTimeout(hideAlert(), 1000);
|
|
});
|
|
} else if(animationOptions.appearAffect == 'fade') {
|
|
alertWrapper.fadeIn(animationOptions.appearDuration, function(){
|
|
// hide the message
|
|
setTimeout(hideAlert(), 1000);
|
|
});
|
|
}
|
|
|
|
function hideAlert(){
|
|
if(animationOptions.hideEffect == 'slide'){
|
|
alertWrapper.slideUp(animationOptions.hideDuration, function() {
|
|
});
|
|
} else if(animationOptions.hideEffect == 'fade'){
|
|
alertWrapper.fadeOut(animationOptions.hideDuration, function() {
|
|
});
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
showModal: function(header, content, className, options) {
|
|
// Get the modal wrapper div element
|
|
var modalWrapper = this.form.find('.jFormerModalWrapper');
|
|
|
|
// set animation options
|
|
var animationOptions = $.extend(this.options.animationOptions.modal, options);
|
|
|
|
// If there is no modal wrapper, add it
|
|
if(modalWrapper.length == 0) {
|
|
var modalTransparency = $('<div class="jFormerModalTransparency"></div>');
|
|
modalWrapper = $('<div style="display: none;" class="jFormerModalWrapper"><div class="jFormerModal"><div class="jFormerModalHeader">'+header+'</div><div class="jFormerModalContent">'+content+'</div><div class="jFormerModalFooter"><button>Okay</button></div></div></div>');
|
|
|
|
// Add the modal wrapper after the alert
|
|
this.form.find('.jFormerAlertWrapper').after(modalTransparency);
|
|
this.form.find('.jFormerAlertWrapper').after(modalWrapper);
|
|
|
|
// Add any custom classes
|
|
if(className != '') {
|
|
modalWrapper.addClass(className);
|
|
}
|
|
|
|
// Add the onclick event for the Okay button
|
|
modalWrapper.find('button').click(function(event) {
|
|
$('.jFormerModalWrapper').hide(animationOptions.hideDuration);
|
|
$('.jFormerModalTransparency').hide(animationOptions.hideDuration);
|
|
$('.jFormerModalWrapper').remove();
|
|
$('.jFormerModalTransparency').remove();
|
|
$('body').css('overflow','auto');
|
|
});
|
|
}
|
|
|
|
// Get the modal div element
|
|
var modal = modalWrapper.find('.jFormerModal');
|
|
modal.css({'position':'absolute'});
|
|
var varWindow = $(window);
|
|
$('body').css('overflow','hidden');
|
|
// Add window resize and scroll events
|
|
varWindow.resize(function(event) {
|
|
leftMargin = (varWindow.width() / 2) - (modal.width() / 2);
|
|
topMargin = (varWindow.height() / 2) - (modal.height() / 2) + varWindow.scrollTop();
|
|
modal.css({'top': topMargin, 'left': leftMargin});
|
|
$('.jFormerModalTransparency').width(varWindow.width()).height(varWindow.height());
|
|
});
|
|
|
|
// If they click away from the modal (on the modal wrapper), remove it
|
|
$('.jFormerModalTransparency').click(function(event) {
|
|
if($(event.target).is('.jFormerModalTransparency')) {
|
|
modalWrapper.hide(animationOptions.hideDuration);
|
|
modalWrapper.remove();
|
|
$('.jFormerModalTransparency').hide(animationOptions.hideDuration);
|
|
$('.jFormerModalTransparency').remove();
|
|
$('body').css('overflow','auto');
|
|
}
|
|
});
|
|
|
|
// Show the wrapper
|
|
//modalWrapper.width(varWindow.width()).height(varWindow.height()*1.1).css('top', varWindow.scrollTop());
|
|
modalWrapper.show(animationOptions.appearDuration);
|
|
|
|
// Set the position
|
|
var leftMargin = (varWindow.width() / 2) - (modal.width() / 2);
|
|
var topMargin = (varWindow.height() / 2) - (modal.height() / 2) + varWindow.scrollTop();
|
|
$('.jFormerModalTransparency').width(varWindow.width()).height(varWindow.height()*1.1).css('top', varWindow.scrollTop());
|
|
modal.css({'top': topMargin, 'left': leftMargin});
|
|
},
|
|
|
|
recordAnalytics: function() {
|
|
var self = this;
|
|
if(!this.options.disableAnalytics) {
|
|
setTimeout(function() {
|
|
var jsProtocol = "https:" == document.location.protocol ? "https://ssl." : "http://www.";
|
|
var image = $('<img src="'+jsProtocol+'jformer.com/analytics/analytics.gif?pageCount='+self.jFormPageIdArray.length+'&componentCount='+self.jFormComponentCount+'&formId='+self.id+'" style="display: none;" />');
|
|
self.form.append(image);
|
|
image.remove();
|
|
}, 3000);
|
|
}
|
|
},
|
|
|
|
updateProgressBar: function() {
|
|
var totalRequired = 0;
|
|
var totalRequiredCompleted = 0;
|
|
$.each(this.jFormPages, function(pageKey, pageObject){
|
|
$.each(pageObject.jFormSections, function(sectionKey, sectionObject){
|
|
$.each(sectionObject.jFormComponents, function(componentKey, componentObject){
|
|
if(componentObject.isRequired === true && (componentObject.disabledByDependency === false && sectionObject.disabledByDependency === false)) {
|
|
if(componentObject.type != 'JFormComponentLikert'){
|
|
totalRequired = totalRequired + 1;
|
|
if(componentObject.requiredCompleted === true){
|
|
totalRequiredCompleted = totalRequiredCompleted + 1;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
var percentCompleted = parseInt((totalRequiredCompleted / totalRequired) * 100);
|
|
|
|
this.form.find('.jFormerProgressBar').animate({
|
|
'width': percentCompleted+'%'
|
|
}, 500)
|
|
.html('<p>'+percentCompleted + '%</p>');
|
|
},
|
|
|
|
addBlurTipListener: function(){
|
|
var self = this;
|
|
$(document).bind('blurTip', function(event, tipElement, action){
|
|
if(action == 'hide'){
|
|
self.blurredTips = $.map(self.blurredTips, function(tip, index){
|
|
if($(tip).attr('id') == tipElement.attr('id')){
|
|
return null
|
|
} else {
|
|
return tip;
|
|
}
|
|
});
|
|
if(self.blurredTips[self.blurredTips.length-1] != undefined){
|
|
self.blurredTips[self.blurredTips.length-1].removeClass('jFormerTipBlurred');
|
|
}
|
|
} else if(action == 'show'){
|
|
if(self.blurredTips.length > 0){
|
|
$.each(self.blurredTips, function(index, tip){
|
|
$(tip).addClass('jFormerTipBlurred')
|
|
})
|
|
}
|
|
self.blurredTips.push(tipElement)
|
|
tipElement.removeClass('jFormerTipBlurred');
|
|
}
|
|
});
|
|
//console.log('blurring tips', tipElement, action);
|
|
|
|
//console.log(this.blurredTips);
|
|
}
|
|
});JFormerUtility = function() {
|
|
}
|
|
|
|
$.extend(JFormerUtility.prototype, {
|
|
isSet: function() {
|
|
var a = arguments;
|
|
var l = a.length;
|
|
var i = 0;
|
|
if(l == 0) {
|
|
throw new Error('Empty isSet.');
|
|
}
|
|
while(i != l) {
|
|
if(typeof(a[i]) == 'undefined' || a[i] === null) {
|
|
return false;
|
|
}
|
|
else {
|
|
i++;
|
|
}
|
|
}
|
|
return true;
|
|
},
|
|
|
|
empty: function(mixedVariable) {
|
|
var key;
|
|
if(mixedVariable === ""
|
|
|| mixedVariable === 0
|
|
|| mixedVariable === "0"
|
|
|| mixedVariable === null
|
|
|| mixedVariable === false
|
|
|| mixedVariable === undefined
|
|
) {
|
|
return true;
|
|
}
|
|
if(typeof mixedVariable == 'object') {
|
|
for(key in mixedVariable) {
|
|
if(typeof mixedVariable[key] !== 'function') {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
getExtraWidth: function(element) {
|
|
var element = $(element);
|
|
var totalWidth = 0;
|
|
totalWidth += parseInt(element.css("padding-left"), 10) + parseInt(element.css("padding-right"), 10); //Total Padding Width
|
|
totalWidth += parseInt(element.css("margin-left"), 10) + parseInt(element.css("margin-right"), 10); //Total Margin Width
|
|
totalWidth += parseInt(element.css("borderLeftWidth"), 10) + parseInt(element.css("borderRightWidth"), 10); //Total Border Width
|
|
return totalWidth;
|
|
},
|
|
|
|
jsonEncode: function(mixed_val) {
|
|
// http://kevin.vanzonneveld.net
|
|
// + original by: Public Domain (http://www.json.org/json2.js)
|
|
// + reimplemented by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
|
|
// + improved by: T.J. Leahy
|
|
// * example 1: json_encode(['e', {pluribus: 'unum'}]);
|
|
// * returns 1: '[\n "e",\n {\n "pluribus": "unum"\n}\n]'
|
|
|
|
/*
|
|
http://www.JSON.org/json2.js
|
|
2008-11-19
|
|
Public Domain.
|
|
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
|
See http://www.JSON.org/js.html
|
|
*/
|
|
var json = window.JSON;
|
|
if (typeof json === 'object' && typeof json.stringify === 'function') {
|
|
return json.stringify(mixed_val);
|
|
}
|
|
|
|
var value = mixed_val;
|
|
|
|
var quote = function (string) {
|
|
var escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
|
|
var meta = { // table of character substitutions
|
|
'\b': '\\b',
|
|
'\t': '\\t',
|
|
'\n': '\\n',
|
|
'\f': '\\f',
|
|
'\r': '\\r',
|
|
'"' : '\\"',
|
|
'\\': '\\\\'
|
|
};
|
|
|
|
escapable.lastIndex = 0;
|
|
return escapable.test(string) ?
|
|
'"' + string.replace(escapable, function (a) {
|
|
var c = meta[a];
|
|
return typeof c === 'string' ? c :
|
|
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
|
}) + '"' :
|
|
'"' + string + '"';
|
|
};
|
|
|
|
var str = function (key, holder) {
|
|
var gap = '';
|
|
var indent = ' ';
|
|
var i = 0; // The loop counter.
|
|
var k = ''; // The member key.
|
|
var v = ''; // The member value.
|
|
var length = 0;
|
|
var mind = gap;
|
|
var partial = [];
|
|
var value = holder[key];
|
|
|
|
// If the value has a toJSON method, call it to obtain a replacement value.
|
|
if (value && typeof value === 'object' &&
|
|
typeof value.toJSON === 'function') {
|
|
value = value.toJSON(key);
|
|
}
|
|
|
|
// What happens next depends on the value's type.
|
|
switch (typeof value) {
|
|
case 'string':
|
|
return quote(value);
|
|
|
|
case 'number':
|
|
// JSON numbers must be finite. Encode non-finite numbers as null.
|
|
return isFinite(value) ? String(value) : 'null';
|
|
|
|
case 'boolean':
|
|
case 'null':
|
|
// If the value is a boolean or null, convert it to a string. Note:
|
|
// typeof null does not produce 'null'. The case is included here in
|
|
// the remote chance that this gets fixed someday.
|
|
|
|
return String(value);
|
|
|
|
case 'object':
|
|
// If the type is 'object', we might be dealing with an object or an array or
|
|
// null.
|
|
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
|
// so watch out for that case.
|
|
if (!value) {
|
|
return 'null';
|
|
}
|
|
|
|
// Make an array to hold the partial results of stringifying this object value.
|
|
gap += indent;
|
|
partial = [];
|
|
|
|
// Is the value an array?
|
|
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
|
// The value is an array. Stringify every element. Use null as a placeholder
|
|
// for non-JSON values.
|
|
|
|
length = value.length;
|
|
for (i = 0; i < length; i += 1) {
|
|
partial[i] = str(i, value) || 'null';
|
|
}
|
|
|
|
// Join all of the elements together, separated with commas, and wrap them in
|
|
// brackets.
|
|
v = partial.length === 0 ? '[]' :
|
|
gap ? '[\n' + gap +
|
|
partial.join(',\n' + gap) + '\n' +
|
|
mind + ']' :
|
|
'[' + partial.join(',') + ']';
|
|
gap = mind;
|
|
return v;
|
|
}
|
|
|
|
// Iterate through all of the keys in the object.
|
|
for (k in value) {
|
|
if (Object.hasOwnProperty.call(value, k)) {
|
|
v = str(k, value);
|
|
if (v) {
|
|
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Join all of the member texts together, separated with commas,
|
|
// and wrap them in braces.
|
|
v = partial.length === 0 ? '{}' :
|
|
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
|
|
mind + '}' : '{' + partial.join(',') + '}';
|
|
gap = mind;
|
|
return v;
|
|
}
|
|
};
|
|
|
|
// Make a fake root object containing our value under the key of ''.
|
|
// Return the result of stringifying the value.
|
|
return str('', {
|
|
'': value
|
|
});
|
|
}
|
|
|
|
});
|
|
|
|
jFormerUtility = new JFormerUtility();
|
|
|
|
// Simple class creation and inheritance
|
|
// Inspired by base2 and Prototype
|
|
(function(){
|
|
var initializing = false, fnTest = /xyz/.test(function(){
|
|
xyz;
|
|
}) ? /\b_super\b/ : /.*/;
|
|
|
|
// The base Class implementation (does nothing)
|
|
this.Class = function(){};
|
|
|
|
// Create a new Class that inherits from this class
|
|
Class.extend = function(prop) {
|
|
var _super = this.prototype;
|
|
|
|
// Instantiate a base class (but only create the instance,
|
|
// don't run the init constructor)
|
|
initializing = true;
|
|
var prototype = new this();
|
|
initializing = false;
|
|
|
|
// Copy the properties over onto the new prototype
|
|
for (var name in prop) {
|
|
// Check if we're overwriting an existing function
|
|
prototype[name] = typeof prop[name] == "function" &&
|
|
typeof _super[name] == "function" && fnTest.test(prop[name]) ?
|
|
(function(name, fn){
|
|
return function() {
|
|
var tmp = this._super;
|
|
|
|
// Add a new ._super() method that is the same method
|
|
// but on the super-class
|
|
this._super = _super[name];
|
|
|
|
// The method only need to be bound temporarily, so we
|
|
// remove it when we're done executing
|
|
var ret = fn.apply(this, arguments);
|
|
this._super = tmp;
|
|
|
|
return ret;
|
|
};
|
|
})(name, prop[name]) :
|
|
prop[name];
|
|
}
|
|
|
|
// The dummy class constructor
|
|
function Class() {
|
|
// All construction is actually done in the init method
|
|
if ( !initializing && this.init )
|
|
this.init.apply(this, arguments);
|
|
}
|
|
|
|
// Populate our constructed prototype object
|
|
Class.prototype = prototype;
|
|
|
|
// Enforce the constructor to be what we expect
|
|
Class.constructor = Class;
|
|
|
|
// And make this class extendable
|
|
Class.extend = arguments.callee;
|
|
|
|
return Class;
|
|
};
|
|
})();/**
|
|
* jFormPage handles all functions on the page level, including page validation.
|
|
*
|
|
*/
|
|
JFormPage = Class.extend({
|
|
init: function(jFormer, pageId, options) {
|
|
this.options = $.extend({
|
|
dependencyOptions: null,
|
|
onScrollTo: {
|
|
onBefore: null,
|
|
onAfter: null,
|
|
notificationHtml: null
|
|
}
|
|
}, options || {});
|
|
|
|
// Setup the onScrollTo functions
|
|
if(this.options.onScrollTo.onBefore !== null) {
|
|
var onBeforeFunction = $.trim(this.options.onScrollTo.onBefore);
|
|
this.options.onScrollTo.onBefore = function() {eval(onBeforeFunction);};
|
|
}
|
|
if(this.options.onScrollTo.onAfter !== null) {
|
|
var onAfterFunction = $.trim(this.options.onScrollTo.onAfter);
|
|
this.options.onScrollTo.onAfter = function() {eval(onAfterFunction);};
|
|
}
|
|
|
|
// Class variables
|
|
this.jFormer = jFormer;
|
|
this.id = pageId;
|
|
this.page = $('#'+pageId);
|
|
this.jFormSections = {};
|
|
this.formData = {};
|
|
this.active = false;
|
|
this.validationPassed = null;
|
|
this.disabledByDependency = false;
|
|
this.durationActiveInSeconds = 0;
|
|
},
|
|
|
|
addSection: function(section) {
|
|
this.jFormSections[section.id] = section;
|
|
return this;
|
|
},
|
|
|
|
getData: function() {
|
|
//console.log('getting data for page');
|
|
var self = this;
|
|
|
|
// Handle disabled pages
|
|
if(this.disabledByDependency) {
|
|
this.formData = null;
|
|
}
|
|
else {
|
|
this.formData = {};
|
|
$.each(this.jFormSections, function(jFormSectionKey, jFormSection) {
|
|
self.formData[jFormSectionKey] = jFormSection.getData();
|
|
});
|
|
}
|
|
|
|
return this.formData;
|
|
},
|
|
|
|
setData: function(data) {
|
|
var self = this;
|
|
$.each(data, function(key, values) {
|
|
if(self.jFormSections[key] != undefined){
|
|
self.jFormSections[key].setData(values);
|
|
} else {
|
|
data[key] = undefined;
|
|
}
|
|
});
|
|
this.formData = data;
|
|
return this.formData;
|
|
},
|
|
|
|
getTimeActive: function(){
|
|
var currentActiveTime =(new Date().getTime() / 1000) - this.startTime ;
|
|
return currentActiveTime;
|
|
},
|
|
|
|
validate: function(silent) {
|
|
//console.log('validating', this.id);
|
|
// Handle dependencies
|
|
if(this.disabledByDependency) {
|
|
return null;
|
|
}
|
|
|
|
var self = this;
|
|
var each = $.each;
|
|
|
|
self.validationPassed = true;
|
|
each(this.jFormSections, function(sectionKey, section) {
|
|
each(section.instanceArray, function(instanceIndex, sectionInstance){
|
|
each(sectionInstance.jFormComponents, function(componentKey, component) {
|
|
if(component.type == 'JFormComponentLikert'){
|
|
return;
|
|
}
|
|
each(component.instanceArray, function(instanceIndex, instance) {
|
|
instance.validate();
|
|
if(instance.validationPassed == false) {
|
|
self.validationPassed = false;
|
|
}
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
if(self.validationPassed) {
|
|
$('#navigatePage'+(self.jFormer.currentJFormPageIdArrayIndex + 1)).removeClass('jFormPageNavigatorLinkWarning');
|
|
}
|
|
else if(!silent) {
|
|
if(this.id === this.jFormer.currentJFormPage.id){
|
|
this.focusOnFirstFailedComponent();
|
|
}
|
|
}
|
|
|
|
return self.validationPassed;
|
|
},
|
|
|
|
clearValidation: function() {
|
|
$.each(this.jFormSections, function(sectionKey, section) {
|
|
section.clearValidation();
|
|
});
|
|
},
|
|
|
|
focusOnFirstFailedComponent: function() {
|
|
var each = $.each,
|
|
validationPassed = true;
|
|
each(this.jFormSections, function(sectionLabel, section){
|
|
each(section.instanceArray, function(sectionInstanceIndex, sectionInstance){
|
|
each(sectionInstance.jFormComponents, function(componentLabel, component){
|
|
each(component.instanceArray, function(instanceLabel, instance){
|
|
if(!instance.validationPassed || instance.errorMessageArray.length > 0){
|
|
var offset = instance.component.offset().top - 30;
|
|
var top = $(window).scrollTop();
|
|
if(top < offset && top + $(window).height() > instance.component.position().top) {
|
|
instance.component.find(':input:first').focus();
|
|
//instance.highlight();
|
|
}
|
|
else {
|
|
$.scrollTo(offset + 'px', 500, {
|
|
onAfter: function() {
|
|
instance.component.find(':input:first').focus();
|
|
//instance.highlight();
|
|
}
|
|
});
|
|
}
|
|
validationPassed = false;
|
|
}
|
|
return validationPassed;
|
|
});
|
|
return validationPassed;
|
|
});
|
|
return validationPassed;
|
|
});
|
|
return validationPassed;
|
|
});
|
|
},
|
|
|
|
scrollTo: function(options) {
|
|
this.jFormer.scrollToPage(this.id, options);
|
|
return this;
|
|
},
|
|
|
|
show: function(){
|
|
if(this.page.hasClass('jFormPageInactive')){
|
|
this.page.removeClass('jFormPageInactive');
|
|
}
|
|
},
|
|
|
|
hide:function() {
|
|
if(!this.active){
|
|
this.page.addClass('jFormPageInactive');
|
|
}
|
|
},
|
|
|
|
disableByDependency: function(disable) {
|
|
// If the condition is different then the current condition
|
|
if(this.disabledByDependency !== disable) {
|
|
var pageIndex = $.inArray(this.id, this.jFormer.jFormPageIdArray);
|
|
|
|
// Disable the page
|
|
if(disable === true) {
|
|
// Hide the page
|
|
this.page.hide();
|
|
|
|
// Update the page navigator appropriately
|
|
if(this.jFormer.options.pageNavigator !== false) {
|
|
// Hide the page link
|
|
if(this.options.dependencyOptions.display == 'hide') {
|
|
$('#navigatePage'+(pageIndex+1)).hide();
|
|
|
|
// Renumber appropriately
|
|
this.jFormer.renumberPageNavigator();
|
|
}
|
|
// Lock the page link
|
|
else {
|
|
$('#navigatePage'+(pageIndex+1)).addClass('jFormPageNavigatorLinkDependencyLocked').find('span').html(' ');
|
|
}
|
|
}
|
|
}
|
|
// Show the page
|
|
else {
|
|
this.checkChildrenDependencies();
|
|
this.page.show();
|
|
|
|
// Update the page navigator appropriately
|
|
if(this.jFormer.options.pageNavigator !== false) {
|
|
// Show the page link
|
|
if(this.options.dependencyOptions.display == 'hide') {
|
|
$('#navigatePage'+(pageIndex+1)).show();
|
|
}
|
|
// Unlock the page link
|
|
else {
|
|
$('#navigatePage'+(pageIndex+1)).removeClass('jFormPageNavigatorLinkDependencyLocked');
|
|
}
|
|
|
|
// Renumber the existing links
|
|
this.jFormer.renumberPageNavigator();
|
|
}
|
|
|
|
}
|
|
|
|
this.disabledByDependency = disable;
|
|
this.jFormer.setupControl();
|
|
}
|
|
},
|
|
|
|
checkDependencies: function() {
|
|
var self = this;
|
|
if(this.options.dependencyOptions !== null) {
|
|
// Run the dependency function
|
|
//console.log(self.options.dependencyOptions.jsFunction);
|
|
//console.log(eval(self.options.dependencyOptions.jsFunction));
|
|
var disable = !(eval(self.options.dependencyOptions.jsFunction));
|
|
this.disableByDependency(disable);
|
|
}
|
|
},
|
|
|
|
checkChildrenDependencies: function() {
|
|
$.each(this.jFormSections, function(jFormSectionKey, jFormSection) {
|
|
jFormSection.checkDependencies();
|
|
});
|
|
}
|
|
});/**
|
|
* jFormSection handles all functions on the section level, including dependencies and instances. A section groups components.
|
|
*
|
|
*/
|
|
JFormSection = Class.extend({
|
|
init: function(parentJFormPage, sectionId, options) {
|
|
this.options = $.extend({
|
|
dependencyOptions: null, // options {jsFunction:#, dependentOn:array, display:enum('hide','lock')}
|
|
instanceOptions: null // options {max:#, addButtonText:string, removeButtonText:string}
|
|
}, options || {});
|
|
|
|
|
|
// Class variables
|
|
this.parentJFormPage = parentJFormPage;
|
|
this.id = sectionId;
|
|
this.section = $('#'+sectionId);
|
|
this.jFormComponents = {};
|
|
this.formData = null; // Will be an object is there is just one instance, will be an array if there is more than one instance
|
|
this.disabledByDependency = false;
|
|
|
|
if(this.options.isInstance){
|
|
this.instanceArray = null;
|
|
this.clone = null; // clone of the original html.. only initiates if instances are turned on...
|
|
}
|
|
else { // do parentInstance functions
|
|
if(this.options.instanceOptions != null){
|
|
this.clone = this.section.clone();
|
|
this.iterations = 1;
|
|
}
|
|
else {
|
|
this.clone = null;
|
|
}
|
|
this.instanceArray = [this];
|
|
this.createInstanceButton();
|
|
}
|
|
},
|
|
|
|
createInstanceButton:function() {
|
|
var self = this;
|
|
if(this.options.instanceOptions != null){
|
|
var buttonId = this.id+'-addInstance',
|
|
addButton = '<button id="'+buttonId+'" class="jFormSectionAddInstanceButton">' + this.options.instanceOptions.addButtonText + '</button>';
|
|
if(this.options.dependencyOptions !== null){
|
|
if(this.options.dependencyOptions.display == 'hide'){
|
|
addButton.hide();
|
|
}
|
|
}
|
|
this.section.after(addButton);
|
|
this.parentJFormPage.page.find('#'+buttonId).bind('click', function(event){
|
|
event.preventDefault();
|
|
if(!self.disabledByDependency){
|
|
self.addSectionInstance();
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
addSectionInstance: function() {
|
|
var parent = this;
|
|
if(this.instanceArray.length < this.options.instanceOptions.max || this.options.instanceOptions.max === 0){
|
|
this.iterations++;
|
|
var instanceClone = this.clone.clone(),
|
|
buttonId = this.id+'-removeInstance',
|
|
removeButton = '<button id="'+buttonId+'" class="jFormSectionRemoveInstanceButton">' + this.options.instanceOptions.removeButtonText + '</button>';
|
|
var animationOptions = {};
|
|
if(this.options.instanceOptions.animationOptions !== undefined){
|
|
$.extend(animationOptions, this.parentJFormPage.jFormer.options.animationOptions.instance, this.options.instanceOptions.animationOptions);
|
|
} else {
|
|
animationOptions = this.parentJFormPage.jFormer.options.animationOptions.instance;
|
|
}
|
|
//console.log(animationOptions);
|
|
$(instanceClone).append(removeButton);
|
|
instanceClone.find('#'+buttonId).bind('click', function(event){
|
|
var target = $(event.target);
|
|
event.preventDefault();
|
|
parent.instanceArray = $.map(parent.instanceArray, function(cloneId, index){
|
|
if (cloneId.section.attr('id') == target.parent().attr('id')){
|
|
cloneId = null;
|
|
}
|
|
return cloneId;
|
|
});
|
|
if(animationOptions.removeEffect == 'none' || animationOptions.removeDuration === 0){
|
|
target.parent().remove();
|
|
target.remove();
|
|
} else {
|
|
if(animationOptions.removeEffect == 'slide'){
|
|
target.parent().slideUp(animationOptions.removeDuration, function(){
|
|
target.parent().remove();
|
|
target.remove();
|
|
|
|
});
|
|
//parent.parentJFormPage.jFormer.jFormPageWrapper.dequeue();
|
|
parent.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
|
|
}else {
|
|
target.parent().fadeOut(animationOptions.removeDuration, function(){
|
|
target.parent().remove();
|
|
target.remove();
|
|
//parent.parentJFormPage.jFormer.jFormPageWrapper.dequeue();
|
|
parent.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
});
|
|
}
|
|
}
|
|
|
|
if(parent.instanceArray.length < parent.options.instanceOptions.max || parent.options.instanceOptions.max === 0){
|
|
parent.parentJFormPage.page.find('#'+parent.id+'-addInstance').show();
|
|
}
|
|
parent.relabelSectionInstances(parent.instanceArray, animationOptions);
|
|
});
|
|
//put that section in there, but hide it first, just in case
|
|
instanceClone.hide();
|
|
this.parentJFormPage.page.find('#'+this.id+'-addInstance').before(instanceClone);
|
|
// no animation
|
|
if(animationOptions.appearEffect == 'none' || animationOptions.appearDuration === 0){
|
|
// console.log('instant');
|
|
instanceClone.show();
|
|
// animation the instance
|
|
} else {
|
|
if(animationOptions.appearEffect == 'slide'){
|
|
|
|
instanceClone.slideDown(animationOptions.appearDuration, function(){
|
|
//parent.parentJFormPage.jFormer.jFormPageWrapper.dequeue();
|
|
parent.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
});
|
|
}else {
|
|
|
|
instanceClone.fadeIn(animationOptions.appearDuration, function(){});
|
|
//parent.parentJFormPage.jFormer.jFormPageWrapper.dequeue();
|
|
parent.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
}
|
|
}
|
|
|
|
this.nameSectionInstance(instanceClone);
|
|
var instanceObject = this.createSectionInstanceObject(instanceClone, this.options);
|
|
this.instanceArray.push(instanceObject);
|
|
this.relabelSectionInstances(this.instanceArray, animationOptions);
|
|
if (this.instanceArray.length >= this.options.instanceOptions.max && this.options.instanceOptions.max !== 0) {
|
|
this.parentJFormPage.page.find('#'+this.id+'-addInstance').hide();
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
|
|
removeInstance: function() {
|
|
return this;
|
|
},
|
|
|
|
nameSectionInstance: function(component) {
|
|
var self = this,
|
|
ending = '';
|
|
$(component).attr('id', $(component).attr('id')+ '-section'+this.iterations);
|
|
$(component).find('*').each(function(key, child){
|
|
if($(child).attr('id')){
|
|
changeName(child, 'id');
|
|
}
|
|
if($(child).attr('for')){
|
|
changeName(child, 'for');
|
|
}
|
|
if($(child).attr('name')){
|
|
changeName(child, 'name');
|
|
}
|
|
});
|
|
|
|
function changeName(child, attribute){
|
|
ending = getEnding($(child).attr(attribute)) ;
|
|
if(ending == ''){
|
|
$(child).attr(attribute, $(child).attr(attribute) +'-section'+self.iterations+ending);
|
|
}else {
|
|
$(child).attr(attribute, $(child).attr(attribute).replace(ending, '-section'+self.iterations+ending));
|
|
}
|
|
}
|
|
|
|
function getEnding(identifier){
|
|
var ending = '';
|
|
if(identifier.match(/(\-[A-Za-z0-9]+)&?/)){
|
|
ending = identifier.match(/(\-[A-Za-z0-9]+)&?/)[1];
|
|
} else {
|
|
|
|
}
|
|
return ending;
|
|
}
|
|
|
|
return component;
|
|
},
|
|
|
|
createSectionInstanceObject:function(instanceClone, options){
|
|
var tempOptions = $.extend(true, {}, options);
|
|
tempOptions.isInstance = true;
|
|
var self = this,
|
|
instanceObject = new JFormSection(this.parentJFormPage, this.id+'-section'+this.iterations, tempOptions);
|
|
$.each(this.jFormComponents, function(key, component){
|
|
var componentTempOptions = $.extend(true, {}, component.options);
|
|
componentTempOptions.isInstance = false;
|
|
var componentClone = new window[component.type](instanceObject, component.id+'-section'+self.iterations, component.type, componentTempOptions);
|
|
instanceObject.addComponent(componentClone);
|
|
});
|
|
return instanceObject;
|
|
},
|
|
|
|
relabelSectionInstances:function(instanceArray, animationOptions){
|
|
$.each(instanceArray, function(key, instance){
|
|
if( key!== 0) {
|
|
var count = key+1,
|
|
label = instance.section.find('.jFormSectionTitle').children(':first');
|
|
if(label.length > 0){
|
|
if (label.text().match(/(\([0-9]+\))$/)){
|
|
label.text(label.text().replace(/(\([0-9]+\))$/, '('+count+')'));
|
|
} else {
|
|
label.text(label.text() + ' ('+count+')');
|
|
}
|
|
|
|
}
|
|
}
|
|
});
|
|
//this.parentJFormPage.jFormer.jFormPageWrapper.dequeue();
|
|
this.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
},
|
|
|
|
addComponent: function(component) {
|
|
this.jFormComponents[component.id] = component;
|
|
return this;
|
|
},
|
|
|
|
clearValidation: function() {
|
|
$.each(this.jFormComponents, function(componentKey, component) {
|
|
component.clearValidation();
|
|
});
|
|
},
|
|
|
|
getData: function() {
|
|
var self = this;
|
|
|
|
// Handle disabled sections
|
|
if(this.disabledByDependency) {
|
|
this.formData = null;
|
|
}
|
|
else {
|
|
if(this.instanceArray.length > 1) {
|
|
this.formData = [];
|
|
$.each(this.instanceArray, function(instanceIndex, instanceJFormSection) {
|
|
var sectionData = {};
|
|
$.each(instanceJFormSection.jFormComponents, function(jFormComponentKey, jFormComponent) {
|
|
if(jFormComponent.type != 'JFormComponentLikertStatement') {
|
|
jFormComponentKey = jFormComponentKey.replace(/-section[0-9]+/, '');
|
|
sectionData[jFormComponentKey] = jFormComponent.getData();
|
|
}
|
|
});
|
|
self.formData.push(sectionData);
|
|
});
|
|
}
|
|
else {
|
|
this.formData = {};
|
|
$.each(this.jFormComponents, function(key, component) {
|
|
if(component.type != 'JFormComponentLikertStatement'){
|
|
self.formData[key] = component.getData();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
return this.formData;
|
|
},
|
|
|
|
setData: function(data) {
|
|
var self = this;
|
|
if($.isArray(data)) {
|
|
$.each(data, function(index, instance){
|
|
if(index !== 0 && self.instanceArray[index] == undefined){
|
|
self.addSectionInstance();
|
|
}
|
|
$.each(instance, function(key, componentData){
|
|
if(index !== 0){
|
|
key = key + '-section'+(index+1);
|
|
}
|
|
if(self.instanceArray[index].jFormComponents[key] != undefined){
|
|
self.instanceArray[index].jFormComponents[key].setData(componentData)
|
|
}
|
|
});
|
|
/*$.each(self.instanceArray[index].jFormComponents, function(key, component){
|
|
|
|
component.setData(instance[key]);
|
|
});*/
|
|
});
|
|
}
|
|
else {
|
|
$.each(data, function(key, componentData) {
|
|
if(self.jFormComponents[key] != undefined){
|
|
self.jFormComponents[key].setData(componentData);
|
|
}
|
|
|
|
});
|
|
}
|
|
},
|
|
|
|
disableByDependency: function(disable) {
|
|
var self = this;
|
|
|
|
if(self.parentJFormPage.jFormer.initializing) {
|
|
var animationOptions = {
|
|
adjustHeightDuration : 0,
|
|
appearDuration : 0,
|
|
appearEffect: 'none',
|
|
hideDuration : 0,
|
|
hideEffect: 'none'
|
|
|
|
}
|
|
} else if(this.options.dependencyOptions.animationOptions !== undefined){
|
|
animationOptions = $.extend(animationOptions, this.parentJFormPage.jFormer.options.animationOptions.dependency, this.options.dependencyOptions.animationOptions);
|
|
} else {
|
|
animationOptions = this.parentJFormPage.jFormer.options.animationOptions.dependency;
|
|
}
|
|
|
|
var elementsToDisable = this.section;
|
|
$.each(this.instanceArray, function(index, sectionInstance){
|
|
if(index !== 0){
|
|
elementsToDisable = elementsToDisable.add(sectionInstance.section);
|
|
}
|
|
});
|
|
if(this.options.instanceOptions !== null && (this.instanceArray.length < this.options.instanceOptions.max || this.options.instanceOptions.max === 0)){
|
|
var addButton = $(this.parentJFormSection.section.find('#'+this.id+'-addInstance'));
|
|
if(self.parentJFormPage.jFormer.initializing) {
|
|
if(!disable && addButton.is(':hidden')){
|
|
addButton.show();
|
|
self.parentJFormPage.jFormer.adjustHeight({adjustHeightDuration:0});
|
|
}
|
|
}
|
|
elementsToDisable = elementsToDisable.add(addButton);
|
|
}
|
|
|
|
// If the condition is different then the current condition
|
|
if(this.disabledByDependency !== disable) {
|
|
// Disable the section
|
|
if(disable) {
|
|
// Hide the section
|
|
if(this.options.dependencyOptions.display == 'hide') {
|
|
//console.log('hiding section');
|
|
if(animationOptions.hideEffect == 'none' || animationOptions.hideDuration === 0){
|
|
elementsToDisable.hide();
|
|
self.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
} else {
|
|
if(animationOptions.appearEffect === 'fade'){
|
|
elementsToDisable.fadeOut(animationOptions.hideDuration, function() {
|
|
self.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
});
|
|
}else if(animationOptions.appearEffect === 'slide'){
|
|
elementsToDisable.slideUp(animationOptions.hideDuration, function() {
|
|
self.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
});
|
|
}
|
|
}
|
|
|
|
}
|
|
// Lock the section and disable all inputs
|
|
else {
|
|
elementsToDisable.addClass('jFormSectionDependencyDisabled').find(':not(.jFormComponentDisabled) > :input').attr('disabled', 'disabled');
|
|
this.parentJFormPage.jFormer.adjustHeight({adjustHeightDuration:0}); // Handle if they are showing a border on the DependencyDisabled class
|
|
}
|
|
}
|
|
// Show or unlock the section
|
|
else {
|
|
// Show the section
|
|
if(this.options.dependencyOptions.display == 'hide') {
|
|
if(animationOptions.appearEffect == 'none' || animationOptions.appearDuration === 0){
|
|
elementsToDisable.show();
|
|
self.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
} else {
|
|
if(animationOptions.hideEffect === 'fade'){
|
|
elementsToDisable.fadeIn(animationOptions.appearDuration);
|
|
self.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
}else if(animationOptions.hideEffect === 'slide'){
|
|
elementsToDisable.slideDown(animationOptions.appearDuration);
|
|
self.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
}
|
|
}
|
|
//console.log('showing section');
|
|
}
|
|
// Unlock the section and reenable all inputs that aren't manually disabled
|
|
else {
|
|
elementsToDisable.removeClass('jFormSectionDependencyDisabled').find(':not(.jFormComponentDisabled) > :input').removeAttr('disabled');
|
|
this.parentJFormPage.jFormer.adjustHeight({adjustHeightDuration:0}); // Handle if they are showing a border on the DependencyDisabled class
|
|
}
|
|
|
|
this.checkChildrenDependencies();
|
|
}
|
|
|
|
this.disabledByDependency = disable;
|
|
}
|
|
},
|
|
|
|
checkDependencies: function() {
|
|
var self = this;
|
|
if(this.options.dependencyOptions !== null) {
|
|
// Run the dependency function
|
|
//console.log(self.options.dependencyOptions.jsFunction);
|
|
//console.log(eval(self.options.dependencyOptions.jsFunction));
|
|
var disable = !(eval(self.options.dependencyOptions.jsFunction));
|
|
this.disableByDependency(disable);
|
|
}
|
|
},
|
|
|
|
checkChildrenDependencies: function() {
|
|
$.each(this.jFormComponents, function(jFormComponentKey, jFormComponent) {
|
|
jFormComponent.checkDependencies();
|
|
});
|
|
}
|
|
});/**
|
|
* jFormComponent is the base class for all components in the form. all specific components extend off of this class
|
|
* Handles instances, dependencies and trigger bases
|
|
*
|
|
*/
|
|
JFormComponent = Class.extend({
|
|
init: function(parentJFormSection, jFormComponentId, jFormComponentType, options) {
|
|
this.options = $.extend({
|
|
validationOptions: [], // 'required', 'email', etc... - An array of validation keys used by this.validate() and jFormerValidator
|
|
showErrorTipOnce: false,
|
|
triggerFunction: null, // set to a function name, is a function
|
|
componentChangedOptions: null, // set options for when component:changed is run
|
|
dependencyOptions: null, // options {jsFunction:Javascript, dependentOn:array, display:enum('hide','lock')}
|
|
instanceOptions: null, // options {max:#, addButtonText:string, removeButtonText:string}
|
|
tipTargetPosition: 'rightMiddle', // 'rightMiddle' - Where the tooltip will be placed in relation to the component
|
|
tipCornerPosition: 'leftTop', // 'leftTop' - The corner of the tip that will point to the tip target position
|
|
isInstance: false
|
|
}, options || {});
|
|
|
|
//console.count(jFormComponentType);
|
|
// Class variables
|
|
this.parentJFormSection = parentJFormSection;
|
|
this.id = jFormComponentId;
|
|
this.component = $('#'+jFormComponentId+'-wrapper');
|
|
this.formData = null; // Will be an object is there is just one instance, will be an array if there is more than one instance
|
|
this.type = jFormComponentType; // 'SingleLineText', 'TextArea', etc... - The component jFormComponentType
|
|
this.errorMessageArray = []; // Used to store error messages displayed in tips or appended to the description
|
|
this.tip = null;
|
|
this.tipDiv = this.component.find('#'+this.id+'-tip');
|
|
this.tipTarget = null; // The ID of the element where the tip will be targeted
|
|
this.validationPassed = true;
|
|
this.disabledByDependency = false;
|
|
this.isRequired = false;
|
|
this.requiredCompleted = false;
|
|
this.validationFunctions = {
|
|
'required': function(options) {
|
|
var errorMessageArray = ['Notwendig!'];
|
|
return options.value != '' ? 'success' : errorMessageArray;
|
|
}
|
|
}
|
|
|
|
if(this.options.isInstance){
|
|
this.instanceArray = null;
|
|
this.clone = null; // Clone of the original HTML, only initiates if instances are turned on
|
|
}
|
|
else { // do parentInstance functions
|
|
if(this.options.instanceOptions != null){
|
|
this.clone = this.component.clone();
|
|
this.iterations = 1;
|
|
}
|
|
else {
|
|
this.clone = null;
|
|
}
|
|
this.instanceArray = [this];
|
|
this.createInstanceButton();
|
|
}
|
|
|
|
// Intitialize the implemented component
|
|
this.initialize();
|
|
this.reformValidations();
|
|
|
|
// Initiation functions
|
|
this.addHighlightListeners();
|
|
this.defineComponentChangedEventListener();
|
|
this.catchComponentChangedEventListener();
|
|
|
|
// Add a tip if there is content to add
|
|
if($.trim(this.tipDiv.html()) !== '') {
|
|
this.addTip();
|
|
}
|
|
|
|
// Tip listeners
|
|
this.addTipListeners();
|
|
},
|
|
|
|
addHighlightListeners: function() {
|
|
var self = this;
|
|
|
|
// Focus
|
|
this.component.find(':input:not(button):not(hidden)').each(function(key, input) {
|
|
$(input).bind('focus', function() {
|
|
self.highlight();
|
|
} );
|
|
$(input).bind('blur', function(event) {
|
|
self.removeHighlight();
|
|
|
|
// Handle multifield highlight and validation
|
|
if((self.type == 'JFormComponentName' || self.type == 'JFormComponentAddress' || self.type == 'JFormComponentCreditCard') && self.changed === true){
|
|
self.validate();
|
|
}
|
|
});
|
|
});
|
|
|
|
// Multiple choice
|
|
if(this.component.find('input:checkbox, input:radio').length > 0) {
|
|
this.component.mouseenter(function(event) {
|
|
self.highlight();
|
|
|
|
});
|
|
this.component.mouseleave(function(event) {
|
|
self.removeHighlight();
|
|
});
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
reformValidations: function() {
|
|
var reformedValidations = {},
|
|
self = this;
|
|
$.each(this.options.validationOptions, function(validationFunction, validationOptions) {
|
|
// Check to see if this component is required, take not of it in the options - used to track which components are required for progress bar
|
|
if(validationOptions == 'required'){
|
|
self.isRequired = true;
|
|
}
|
|
|
|
// Check to see if the name of the function is actually an array index
|
|
if(validationFunction >= 0) {
|
|
// The function is not an index, it becomes the name of the option with the value of an empty object
|
|
reformedValidations[validationOptions] = {'component': self.component};
|
|
}
|
|
// If the validationOptions is a string
|
|
else if(typeof(validationOptions) != 'object') {
|
|
reformedValidations[validationFunction] = {'component': self.component};
|
|
reformedValidations[validationFunction][validationFunction] = validationOptions;
|
|
}
|
|
// If validationOptions is an object
|
|
else if(typeof(validationOptions) == 'object') {
|
|
if(validationOptions[0] != undefined){
|
|
reformedValidations[validationFunction] = {}
|
|
reformedValidations[validationFunction][validationFunction] = validationOptions;
|
|
} else {
|
|
reformedValidations[validationFunction] = validationOptions;
|
|
}
|
|
reformedValidations[validationFunction].component = self.component;
|
|
}
|
|
});
|
|
|
|
this.options.validationOptions = reformedValidations;
|
|
},
|
|
|
|
|
|
defineComponentChangedEventListener: function() {
|
|
var self = this;
|
|
|
|
// Handle IE events
|
|
this.component.find('input:checkbox, input:radio').each(function(key, input) {
|
|
$(input).bind('click', function(event) {
|
|
$(this).trigger('jFormComponent:changed', self);
|
|
});
|
|
});
|
|
|
|
this.component.find(':input:not(button, :checkbox, :radio)').each(function(key, input) {
|
|
$(input).bind('change', function(event) {
|
|
$(this).trigger('jFormComponent:changed', self);
|
|
});
|
|
});
|
|
},
|
|
|
|
catchComponentChangedEventListener: function() {
|
|
var self = this;
|
|
this.component.bind('jFormComponent:changed', function(event) {
|
|
// Run a trigger on change if there is one
|
|
if(self.options.triggerFunction !== null) {
|
|
eval(self.options.triggerFunction);
|
|
}
|
|
// Prevent validation from occuring with components with more than one input
|
|
if(self.type == 'JFormComponentName' || self.type == 'JFormComponentAddress' || self.type == 'JFormComponentLikert' || self.type == 'JFormComponentCreditCard'){
|
|
self.changed = true;
|
|
}
|
|
// Validate the component on change if client side validation is enabled
|
|
if(self.parentJFormSection.parentJFormPage.jFormer.options.clientSideValidation) {
|
|
self.validate();
|
|
}
|
|
// Update the progress bar
|
|
if(self.parentJFormSection.parentJFormPage.jFormer.options.progressBar !== false) {
|
|
self.parentJFormSection.parentJFormPage.jFormer.updateProgressBar();
|
|
}
|
|
});
|
|
},
|
|
|
|
highlight: function() {
|
|
// Add the highlight class and trigger the highlight
|
|
this.component.addClass('jFormComponentHighlight').trigger('jFormComponent:highlighted', this.component);
|
|
this.component.trigger('jFormComponent:showTip', this.component);
|
|
},
|
|
|
|
removeHighlight: function() {
|
|
var self = this;
|
|
this.component.removeClass('jFormComponentHighlight').trigger('jFormComponent:highlightRemoved', this.component);
|
|
|
|
// Wait just a microsecond to see if you are still on the same component
|
|
setTimeout(function() {
|
|
if(!self.component.hasClass('jFormComponentHighlight')){
|
|
self.component.trigger('jFormComponent:hideTip', self.component);
|
|
}
|
|
}, 1);
|
|
},
|
|
|
|
getData: function() {
|
|
var self = this;
|
|
|
|
// Handle disabled component
|
|
if(this.disabledByDependency || this.parentJFormSection.disabledByDependency) {
|
|
this.formData = null;
|
|
}
|
|
else {
|
|
if(this.instanceArray.length > 1) {
|
|
this.formData = [];
|
|
$.each(this.instanceArray, function(index, component) {
|
|
var componentValue = component.getValue();
|
|
self.formData.push(componentValue);
|
|
});
|
|
}
|
|
else {
|
|
this.formData = this.getValue();
|
|
}
|
|
}
|
|
return this.formData;
|
|
},
|
|
|
|
setData: function(data) {
|
|
var self = this;
|
|
if($.isArray(data)) {
|
|
$.each(data, function(index, value) {
|
|
if((self.type == 'JFormComponentMultipleChoice' && ($.isArray(value) || self.multipeChoiceType == 'radio')) || self.type != 'JFormComponentMultipleChoice'){
|
|
if(index !== 0 && self.instanceArray[index] == undefined){
|
|
self.addInstance();
|
|
}
|
|
self.instanceArray[index].setValue(value);
|
|
}
|
|
else {
|
|
self.setValue(data);
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
this.setValue(data);
|
|
}
|
|
},
|
|
|
|
createInstanceButton:function() {
|
|
var self = this;
|
|
if(this.options.instanceOptions != null){
|
|
//if(this.options.instancesAllowed != 1){
|
|
var addButton = $('<button id="'+this.id+'-addInstance" class="jFormComponentAddInstanceButton">'+this.options.instanceOptions.addButtonText+'</button>');
|
|
// hide the button if there are dependencies... show it later if necessary
|
|
if(this.options.dependencyOptions !== null){
|
|
addButton.hide();
|
|
}
|
|
|
|
this.component.after(addButton);
|
|
//this.component.after('<button id="'+this.id+'-addInstance" class="jFormComponentAddInstanceButton">'+this.options.instanceAddText+'</button>');
|
|
this.parentJFormSection.section.find('#'+this.id+'-addInstance').bind('click', function(event){
|
|
event.preventDefault();
|
|
if(!self.disabledByDependency){
|
|
self.addInstance();
|
|
}
|
|
|
|
});
|
|
}
|
|
},
|
|
|
|
addInstance: function() {
|
|
if(this.options.componentChangedOptions != null && this.options.componentChangedOptions.instance != undefined && this.options.componentChangedOptions.instance == true){
|
|
this.component.trigger('jFormComponent:changed', this);
|
|
}
|
|
var parent = this;
|
|
if(this.instanceArray.length < this.options.instanceOptions.max || this.options.instanceOptions.max === 0){
|
|
var instanceClone = this.clone.clone();
|
|
var addButton = this.parentJFormSection.section.find('#'+this.id+'-addInstance');
|
|
var animationOptions = {};
|
|
if(this.options.instanceOptions.animationOptions !== undefined){
|
|
animationOptions = $.extend(animationOptions, this.parentJFormSection.parentJFormPage.jFormer.options.animationOptions.instance, this.options.instanceOptions.animationOptions);
|
|
} else {
|
|
animationOptions = this.parentJFormSection.parentJFormPage.jFormer.options.animationOptions.instance;
|
|
}
|
|
|
|
// Create the remove button
|
|
$(instanceClone).append('<button id="'+this.id+'-removeInstance" class="jFormComponentRemoveInstanceButton">'+this.options.instanceOptions.removeButtonText+'</button>');
|
|
|
|
// Add an event listener on the remove button
|
|
instanceClone.find('#'+this.id+'-removeInstance').bind('click', function(event){
|
|
var target = $(event.target);
|
|
event.preventDefault();
|
|
|
|
parent.instanceArray = $.map(parent.instanceArray, function(cloneId, index){
|
|
if(cloneId.component.attr('id') == target.parent().attr('id')){
|
|
if(cloneId.tip != null){
|
|
cloneId.tip.hide();
|
|
}
|
|
cloneId = null;
|
|
}
|
|
return cloneId;
|
|
});
|
|
if(animationOptions.removeEffect == 'none' || animationOptions.removeDuration === 0){
|
|
target.parent().remove();
|
|
target.remove();
|
|
} else {
|
|
if(animationOptions.removeEffect == 'slide'){
|
|
target.parent().slideUp(animationOptions.removeDuration, function(){
|
|
target.parent().remove();
|
|
target.remove();
|
|
//parent.parentJFormSection.parentJFormPage.jFormer.jFormPageWrapper.dequeue();
|
|
parent.parentJFormSection.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
})
|
|
|
|
}else {
|
|
target.parent().fadeOut(animationOptions.removeDuration, function(){
|
|
target.parent().remove();
|
|
target.remove();
|
|
//parent.parentJFormSection.parentJFormPage.jFormer.jFormPageWrapper.dequeue();
|
|
parent.parentJFormSection.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
});
|
|
}
|
|
}
|
|
if(parent.instanceArray.length < parent.options.instanceOptions.max || parent.options.instanceOptions.max === 0){
|
|
addButton.show();
|
|
}
|
|
parent.relabelInstances(parent.instanceArray, animationOptions);
|
|
});
|
|
instanceClone.hide();
|
|
// Insert the clone right before the add button
|
|
addButton.before(instanceClone);
|
|
|
|
if(animationOptions.appearEffect == 'none' || animationOptions.appearDuration === 0){
|
|
if(!parent.disabledByDependency || (parent.disabledByDependency && parent.options.dependencyOptions.display != 'hide')){
|
|
instanceClone.show();
|
|
}
|
|
} else {
|
|
if(!parent.disabledByDependency){
|
|
if(animationOptions.appearEffect == 'slide'){
|
|
instanceClone.slideDown(animationOptions.appearDuration, function(){
|
|
parent.parentJFormSection.parentJFormPage.jFormer.jFormPageWrapper.dequeue();
|
|
parent.parentJFormSection.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
});
|
|
}else {
|
|
instanceClone.fadeIn(animationOptions.appearDuration, function(){
|
|
parent.parentJFormSection.parentJFormPage.jFormer.jFormPageWrapper.dequeue();
|
|
parent.parentJFormSection.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
this.nameInstance(instanceClone);
|
|
|
|
var instanceObject = this.createInstanceObject(instanceClone, this.options);
|
|
|
|
this.instanceArray.push(instanceObject);
|
|
this.relabelInstances(this.instanceArray, animationOptions);
|
|
if(this.instanceArray.length == this.options.instanceOptions.max && this.options.instanceOptions.max !== 0){
|
|
//if(this.instanceArray.length == this.options.instancesAllowed && this.options.instancesAllowed !== 0) {
|
|
addButton.hide();
|
|
}
|
|
|
|
if(this.options.dependencies != undefined){
|
|
var objectTop = parent.parentJFormSection.parentJFormPage.jFormer;
|
|
instanceObject.component.find(':text, textarea').bind('keyup', function(event) {
|
|
$.each(parent.options.dependencies.pages, function(index, object) {
|
|
objectTop.jFormPages[object.jFormPageId].checkDependencies();
|
|
});
|
|
$.each(parent.options.dependencies.sections, function(index, object) {
|
|
objectTop.jFormPages[object.jFormPageId].jFormSections[object.jFormSectionId].checkDependencies();
|
|
});
|
|
$.each(parent.options.dependencies.components, function(index, object) {
|
|
objectTop.jFormPages[object.jFormPageId].jFormSections[object.jFormSectionId].jFormComponents[object.jFormComponentId].checkDependencies();
|
|
});
|
|
});
|
|
|
|
instanceObject.component.bind('jFormComponent:changed', function(event) {
|
|
|
|
$.each(parent.options.dependencies.pages, function(index, object) {
|
|
objectTop.jFormPages[object.jFormPageId].checkDependencies();
|
|
});
|
|
$.each(parent.options.dependencies.sections, function(index, object) {
|
|
objectTop.jFormPages[object.jFormPageId].jFormSections[object.jFormSectionId].checkDependencies();
|
|
});
|
|
$.each(parent.options.dependencies.components, function(index, object) {
|
|
objectTop.jFormPages[object.jFormPageId].jFormSections[object.jFormSectionId].jFormComponents[object.jFormComponentId].checkDependencies();
|
|
});
|
|
});
|
|
}
|
|
if(this.disabledByDependency){
|
|
this.disableByDependency(true);
|
|
}
|
|
|
|
|
|
// Resize the page
|
|
//parent.parentJFormSection.parentJFormPage.scrollTo();
|
|
}
|
|
return this;
|
|
},
|
|
|
|
nameInstance: function(component) {
|
|
component = $(component);
|
|
var self = this,
|
|
ending = '';
|
|
this.iterations++;
|
|
component.attr('id', component.attr('id').replace('-wrapper', '-instance'+this.iterations+'-wrapper'));
|
|
component.find('*').each(function(key, child){
|
|
if($(child).attr('id')){
|
|
changeName(child, 'id');
|
|
}
|
|
if($(child).attr('for')){
|
|
changeName(child, 'for');
|
|
}
|
|
if($(child).attr('name')){
|
|
changeName(child, 'name');
|
|
}
|
|
});
|
|
function changeName(child, attribute){
|
|
ending = getEnding($(child).attr(attribute)) ;
|
|
if(ending == ''){
|
|
$(child).attr(attribute, $(child).attr(attribute) +'-instance'+self.iterations+ending);
|
|
}else {
|
|
$(child).attr(attribute, $(child).attr(attribute).replace(ending, '-instance'+self.iterations+ending));
|
|
}
|
|
}
|
|
function getEnding(identifier){
|
|
var ending = '';
|
|
if(identifier.match(/\-(div|label|tip|removeInstance)\b/)){
|
|
ending = identifier.match(/\-(div|label|tip|removeInstance)\b/)[0];
|
|
} else {
|
|
|
|
}
|
|
return ending;
|
|
}
|
|
return component;
|
|
},
|
|
|
|
createInstanceObject:function(instanceClone, options){
|
|
var tempOptions = $.extend(true, {}, options);
|
|
tempOptions.isInstance = true;
|
|
if(this.options.componentChangedOptions != null && this.options.componentChangedOptions.children != undefined && this.options.componentChangedOptions.children == false ){
|
|
tempOptions.componentChangedOptions = null;
|
|
}
|
|
var instanceObject = new window[this.type](this.parentJFormSection, this.id+'-instance'+this.iterations, this.type, tempOptions);
|
|
return instanceObject;
|
|
},
|
|
|
|
relabelInstances:function(instanceArray, animationOptions){
|
|
$.each(instanceArray, function(key, instance){
|
|
if( key!== 0) {
|
|
var count = key+1,
|
|
label = instance.component.find('#'+instance.component.attr('id').replace('-wrapper','-label'));
|
|
if(label.length > 0) {
|
|
var star = label.find('span.jFormComponentLabelRequiredStar');
|
|
if(star.length > 0){
|
|
star.remove()
|
|
}
|
|
if(label.html().match(/:$/)){
|
|
label.html(label.html().replace(/(\([0-9]+\))?:/, ' ('+count+'):'));
|
|
} else {
|
|
if (label.text().match(/(\([0-9]+\))$/)){
|
|
label.text(label.text().replace(/(\([0-9]+\))$/, '('+count+')'));
|
|
} else {
|
|
label.text(label.text() + ' ('+count+')');
|
|
}
|
|
}
|
|
label.append(star);
|
|
} else {
|
|
label = instance.component.find('label');
|
|
var star = label.find('span.jFormComponentLabelRequiredStar');
|
|
if(star.length > 0){
|
|
star.remove()
|
|
}
|
|
if (label.text().match(/(\([0-9]+\))$/)){
|
|
label.text(label.text().replace(/(\([0-9]+\))$/, '('+count+')'));
|
|
} else {
|
|
label.text(label.text() + ' ('+count+')');
|
|
}
|
|
label.append(star);
|
|
}
|
|
|
|
}
|
|
});
|
|
//this.parentJFormSection.parentJFormPage.jFormer.jFormPageWrapper.dequeue();
|
|
this.parentJFormSection.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
},
|
|
|
|
addTip: function() {
|
|
var self = this;
|
|
|
|
// Check to see if the tip already exists
|
|
if(typeof(this.tip) !== 'function') {
|
|
// Create the tip
|
|
var tip = this.tipTarget.simpletip({
|
|
persistent: true,
|
|
focus: true,
|
|
position: 'topRight',
|
|
content: self.tipDiv,
|
|
baseClass: 'jFormerTip',
|
|
hideEffect: 'none',
|
|
onBeforeShow: function(){
|
|
if(self.tipDiv.find('.tipContent').text() == ''){
|
|
return false;
|
|
}
|
|
},
|
|
onShow: function(){
|
|
// Scroll the page to show the tip if the tip is off the page
|
|
var height = $(window).height();
|
|
var offset = this.getTooltip().offset().top + this.getTooltip().outerHeight() + 12;
|
|
if($(window).scrollTop() + height < offset) {
|
|
$.scrollTo(offset - height + 'px', 250, {axis:'y'});
|
|
}
|
|
}
|
|
});
|
|
this.tip = tip.simpletip();
|
|
}
|
|
},
|
|
|
|
addTipListeners: function() {
|
|
var self = this;
|
|
|
|
// Show a tip
|
|
this.component.bind('jFormComponent:showTip', function(event) {
|
|
// Make sure the tip exists and display the tip if it is not empty
|
|
if(self.tip && typeof(self.tip) == 'object' && $.trim(self.tipDiv.html()) !== '') {
|
|
self.tip.show();
|
|
}
|
|
|
|
});
|
|
|
|
// Hide a tip
|
|
this.component.bind('jFormComponent:hideTip', function(event) {
|
|
// Make sure the tip exists
|
|
if(self.tip && typeof(self.tip) == 'object') {
|
|
self.tip.hide();
|
|
}
|
|
|
|
// Show error tips once
|
|
if(self.options.showErrorTipOnce){
|
|
self.clearValidation();
|
|
}
|
|
});
|
|
|
|
return this;
|
|
},
|
|
|
|
clearValidation: function() {
|
|
// Reset the error message array and validation passes boolean
|
|
this.errorMessageArray = [];
|
|
this.validationPassed = true;
|
|
|
|
// Reset the classes
|
|
this.component.removeClass('jFormComponentValidationFailed');
|
|
this.component.addClass('jFormComponentValidationPassed');
|
|
|
|
// Remove any tipErrorUl from the tip div
|
|
this.component.find('.tipErrorUl').remove();
|
|
|
|
// Handle tip display
|
|
if(this.tip && typeof(this.tip) == 'object') {
|
|
// Update the tip content
|
|
this.tip.update(this.tipDiv.html());
|
|
|
|
// Hide the tip if the tip is empty
|
|
if($.trim(this.tipDiv.find('.tipContent').html()) == ''){
|
|
this.tipDiv.hide();
|
|
}
|
|
}
|
|
},
|
|
|
|
// Abstract functions
|
|
initialize: function() { },
|
|
getValue: function() { },
|
|
setValue: function() { },
|
|
|
|
clearData: function() {
|
|
this.component.find(':input').val('');
|
|
},
|
|
|
|
validate: function(silent) {
|
|
//console.log('validating a component Bi!', this.parentJFormSection.parentJFormPage.id, this.id);
|
|
// Handle dependencies
|
|
if(this.disabledByDependency || this.parentJFormSection.disabledByDependency) {
|
|
return null;
|
|
}
|
|
|
|
// If there are no validations, return true
|
|
if(this.options.validationOptions.length < 1) {
|
|
return true;
|
|
}
|
|
if(silent){
|
|
var silentValidationPassed = true;
|
|
}
|
|
|
|
var self = this;
|
|
this.clearValidation();
|
|
var value = this.getValue();
|
|
|
|
if(value === null){
|
|
return true;
|
|
}
|
|
|
|
$.each(this.options.validationOptions, function(validationType, validationOptions){
|
|
validationOptions['value'] = value;
|
|
var validation = self.validationFunctions[validationType](validationOptions);
|
|
|
|
if(validation == 'success') {
|
|
if(validationType.match('required')){
|
|
self.requiredCompleted = true;
|
|
}
|
|
return true;
|
|
}
|
|
else {
|
|
if(validationType.match('required')){
|
|
self.requiredCompleted = false;
|
|
if(self.parentJFormSection.parentJFormPage.jFormer.options.pageNavigator != false){
|
|
var pageIndex = $.inArray(self.parentJFormSection.parentJFormPage.id, self.parentJFormSection.parentJFormPage.jFormer.jFormPageIdArray);
|
|
$('#navigatePage'+(pageIndex + 1)).addClass('jFormPageNavigatorLinkWarning');
|
|
}
|
|
}
|
|
if(silent){
|
|
silentValidationPassed = false;
|
|
} else {
|
|
$.merge(self.errorMessageArray, validation);
|
|
}
|
|
}
|
|
});
|
|
if(silent) {
|
|
return silentValidationPassed;
|
|
}
|
|
else {
|
|
if(this.errorMessageArray.length > 0 ) {
|
|
this.handleErrors();
|
|
this.validationPassed = false;
|
|
}
|
|
return this.validationPassed;
|
|
}
|
|
},
|
|
|
|
handleServerValidationResponse: function(errorMessageArray) {
|
|
// Clear the validation
|
|
$.each(this.instanceArray, function(instanceKey, instance) {
|
|
instance.clearValidation();
|
|
});
|
|
|
|
// If there are errors
|
|
if(errorMessageArray != null && errorMessageArray.length > 0) {
|
|
// If there are instances
|
|
if(this.instanceArray.length != 1) {
|
|
// Go through each of the instances and assign the error messages
|
|
$.each(this.instanceArray, function(instanceKey, instance) {
|
|
if(!jFormerUtility.empty(errorMessageArray[instanceKey])){
|
|
$.each(errorMessageArray[instanceKey], function(errorMessageArrayIndex, errorMessage){
|
|
if(errorMessage != '') {
|
|
instance.errorMessageArray.push(errorMessage);
|
|
}
|
|
});
|
|
if(instance.errorMessageArray.length > 0) {
|
|
instance.validationPassed = false;
|
|
instance.handleErrors();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
// If there aren't instances
|
|
else {
|
|
this.errorMessageArray = errorMessageArray;
|
|
this.validationPassed = false;
|
|
this.handleErrors();
|
|
}
|
|
}
|
|
},
|
|
|
|
handleErrors: function() {
|
|
var self = this;
|
|
|
|
// Change classes
|
|
this.component.removeClass('jFormComponentValidationPassed');
|
|
this.component.addClass('jFormComponentValidationFailed');
|
|
|
|
// Add a tip div and tip neccesary
|
|
if(this.tipDiv.length == 0) {
|
|
this.createTipDiv();
|
|
}
|
|
|
|
// If validation tips are disabled
|
|
if(!this.parentJFormSection.parentJFormPage.jFormer.options.validationTips) {
|
|
return;
|
|
}
|
|
|
|
// Put the error list into the tip
|
|
var tipErrorUl = $('<ul id="'+this.id+'-tipErrorUl" class="tipErrorUl"></ul>');
|
|
$.each(this.errorMessageArray, function(index, errorMessage){
|
|
tipErrorUl.append("<li>"+errorMessage+"</li>");
|
|
});
|
|
this.tipDiv.find('.tipContent').append(tipErrorUl);
|
|
|
|
// Update the tip content
|
|
this.tip.update(self.tipDiv.html());
|
|
|
|
// Show the tip if you are currently on it
|
|
if(this.component.hasClass('jFormComponentHighlight')) {
|
|
this.tip.show();
|
|
|
|
}
|
|
},
|
|
|
|
createTipDiv: function() {
|
|
// Create a tip div and tip neccesary
|
|
this.tipDiv = $('<div id="'+this.id+'-tip" style="display: none;"></div>');
|
|
this.component.append(this.tipDiv);
|
|
this.addTip();
|
|
},
|
|
|
|
disableByDependency: function(disable) {
|
|
var self = this;
|
|
var animationOptions = {};
|
|
if(this.options.componentChangedOptions != null && this.options.componentChangedOptions.dependency != undefined && this.options.componentChangedOptions.dependency == true){
|
|
this.component.trigger('jFormComponent:changed', this);
|
|
}
|
|
//stuff we are going to do stuff to...
|
|
var elementsToDisable = this.component;
|
|
$.each(this.instanceArray, function(index, componentInstance){
|
|
if(index !== 0){
|
|
elementsToDisable = elementsToDisable.add(componentInstance.component);
|
|
}
|
|
});
|
|
if(this.options.instanceOptions !== null && (this.instanceArray.length < this.options.instanceOptions.max || this.options.instanceOptions.max === 0)){
|
|
var addButton = $(this.parentJFormSection.section.find('#'+this.id+'-addInstance'));
|
|
if(self.parentJFormSection.parentJFormPage.jFormer.initializing) {
|
|
if(!disable && addButton.is(':hidden')){
|
|
addButton.show();
|
|
self.parentJFormSection.parentJFormPage.jFormer.adjustHeight({adjustHeightDuration:0});
|
|
} else if(this.options.dependencyOptions.display == 'lock'){
|
|
addButton.show();
|
|
self.parentJFormSection.parentJFormPage.jFormer.adjustHeight({adjustHeightDuration:0});
|
|
}
|
|
}
|
|
elementsToDisable = elementsToDisable.add(addButton);
|
|
}
|
|
|
|
if(self.parentJFormSection.parentJFormPage.jFormer.initializing) {
|
|
animationOptions = {
|
|
adjustHeightDelay : 0,
|
|
appearDuration : 0,
|
|
appearEffect: 'none',
|
|
hideDuration : 0,
|
|
hideEffect: 'none'
|
|
|
|
}
|
|
} else if(this.options.dependencyOptions.animationOptions !== undefined){
|
|
animationOptions = $.extend(animationOptions, this.parentJFormSection.parentJFormPage.jFormer.options.animationOptions.dependency, this.options.dependencyOptions.animationOptions);
|
|
} else {
|
|
animationOptions = this.parentJFormSection.parentJFormPage.jFormer.options.animationOptions.dependency;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If the form is initializing
|
|
|
|
|
|
// If the condition is different then the current condition
|
|
if(this.disabledByDependency !== disable) {
|
|
// Disable the component
|
|
if(disable) {
|
|
// Clear the validation to prevent validation issues with disabled component
|
|
this.clearValidation();
|
|
|
|
// Hide the component
|
|
if(this.options.dependencyOptions.display == 'hide') {
|
|
//console.log('hiding component')
|
|
if(animationOptions.hideEffect == 'none' || animationOptions.hideDuration === 0){
|
|
elementsToDisable.hide(animationOptions.hideDuration);
|
|
self.parentJFormSection.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
} else {
|
|
if(animationOptions.hideEffect === 'fade'){
|
|
elementsToDisable.fadeOut(animationOptions.hideDuration, function() {
|
|
self.parentJFormSection.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
});
|
|
}else if(animationOptions.hideEffect === 'fade'){
|
|
|
|
elementsToDisable.slideUp(animationOptions.hideDuration, function() {
|
|
self.parentJFormSection.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
// Lock the component
|
|
else {
|
|
elementsToDisable.addClass('jFormComponentDependencyDisabled').find(':input').attr('disabled', 'disabled');
|
|
}
|
|
}
|
|
// Show or unlock the component
|
|
else {
|
|
// Show the component
|
|
if(this.options.dependencyOptions.display == 'hide') {
|
|
//console.log('showing component')
|
|
if(animationOptions.appearEffect == 'none' || animationOptions.apearDuration === 0){
|
|
|
|
elementsToDisable.show();
|
|
self.parentJFormSection.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
}else {
|
|
if(animationOptions.appearEffect === 'fade'){
|
|
|
|
elementsToDisable.fadeIn(animationOptions.appearDuration);
|
|
self.parentJFormSection.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
}else if(animationOptions.appearEffect === 'slide'){
|
|
|
|
elementsToDisable.slideDown(animationOptions.appearDuration);
|
|
self.parentJFormSection.parentJFormPage.jFormer.adjustHeight(animationOptions);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
// Unlock the component
|
|
else {
|
|
elementsToDisable.removeClass('jFormComponentDependencyDisabled').find(':input').removeAttr('disabled');
|
|
}
|
|
}
|
|
this.disabledByDependency = disable;
|
|
}
|
|
},
|
|
|
|
checkDependencies: function() {
|
|
var self = this;
|
|
if(this.options.dependencyOptions !== null) {
|
|
// Run the dependency function
|
|
//console.log(self.options.dependencyOptions.jsFunction);
|
|
//console.log(eval(self.options.dependencyOptions.jsFunction));
|
|
var disable = !(eval(self.options.dependencyOptions.jsFunction));
|
|
this.disableByDependency(disable);
|
|
}
|
|
}
|
|
});JFormComponentAddress = JFormComponent.extend({
|
|
init: function(parentJFormSection, jFormComponentId, jFormComponentType, options) {
|
|
this._super(parentJFormSection, jFormComponentId, jFormComponentType, options);
|
|
},
|
|
|
|
initialize: function(){
|
|
this.tipTarget = this.component;
|
|
if(this.options.emptyValue){
|
|
this.addEmptyValues();
|
|
}
|
|
this.validationFunctions = {
|
|
//Name Validations
|
|
'required': function(options) {
|
|
var errorMessageArray = [];
|
|
if(options.value.addressLine1 == '') {
|
|
errorMessageArray.push(['Andresse ist notwendig.']);
|
|
}
|
|
if(options.value.city == '') {
|
|
errorMessageArray.push(['Stadt ist notwendig.']);
|
|
}
|
|
if(options.value.state == '') {
|
|
errorMessageArray.push(['State is required.']);
|
|
}
|
|
if(options.value.zip == '') {
|
|
errorMessageArray.push(['Postleitzahl ist notwendig.']);
|
|
}
|
|
if(options.value.country == '') {
|
|
errorMessageArray.push(['Country is required.']);
|
|
}
|
|
return errorMessageArray.length < 1 ? 'success' : errorMessageArray;
|
|
}
|
|
}
|
|
|
|
this.changed = false;
|
|
},
|
|
|
|
setValue: function(data) {
|
|
var self = this;
|
|
if(data === null || data === ''){
|
|
data = {
|
|
addressline1:'',
|
|
city:'',
|
|
state:'',
|
|
zip:''
|
|
}
|
|
}
|
|
if(this.options.emptyValue){
|
|
if(data.addressLine1 != this.options.emptyValue.addressLine1){
|
|
self.component.find(':input[id*=addressLine1]').removeClass('defaultValue').val(data.addressLine1).blur();
|
|
}
|
|
if(data.addressLine2 != this.options.emptyValue.addressLine2){
|
|
self.component.find(':input[id*=addressLine2]').removeClass('defaultValue').val(data.addressLine2).blur();
|
|
}
|
|
if(data.city != this.options.emptyValue.city){
|
|
self.component.find(':input[id*=city]').removeClass('defaultValue').val(data.city).blur();
|
|
}
|
|
if(data.state != this.options.emptyValue.state || this.options.emptyValue.state == undefined){
|
|
self.component.find(':input[id*=state]').removeClass('defaultValue').val(data.state).blur();
|
|
}
|
|
if(data.zip != this.options.emptyValue.zip){
|
|
self.component.find(':input[id*=zip]').removeClass('defaultValue').val(data.zip).blur();
|
|
}
|
|
}
|
|
else {
|
|
self.component.find(':input[id*=addressLine1]').val(data.addressLine1);
|
|
self.component.find(':input[id*=addressLine2]').val(data.addressLine2);
|
|
self.component.find(':input[id*=city]').val(data.city);
|
|
self.component.find(':input[id*=state]').val(data.state);
|
|
self.component.find(':input[id*=zip]').val(data.zip);
|
|
}
|
|
self.component.find(':input[id*=country]').val(data.country);
|
|
this.validate(true);
|
|
/*
|
|
$.each(data, function(key, value){
|
|
if(self.options.emptyValue[key] != undefined && data[key] != self.options.emptyValue[key]){
|
|
self.component.find(':input[id*='+key+']').removeClass('defaultValue').val(value).trigger('component:changed').blur();
|
|
} else if (self.options.emptyValue[key] == undefined) {
|
|
self.component.find(':input[id*='+key+']').val(value).trigger('component:changed');
|
|
} else {
|
|
self.component.find(':input[id*='+key+']').val(value).trigger('component:changed');
|
|
}
|
|
});*/
|
|
},
|
|
|
|
getValue: function() {
|
|
if(this.disabledByDependency || this.parentJFormSection.disabledByDependency){
|
|
return null;
|
|
}
|
|
var address = {},
|
|
self = this;
|
|
|
|
// Get the values
|
|
address.addressLine1 = self.component.find(':input[id*=addressLine1]').val();
|
|
address.addressLine2 = self.component.find(':input[id*=addressLine2]').val();
|
|
address.city = self.component.find(':input[id*=city]').val();
|
|
address.state = self.component.find(':input[id*=state]').val();
|
|
address.zip = self.component.find(':input[id*=zip]').val();
|
|
address.country = self.component.find(':input[id*=country]').val();
|
|
|
|
this.component.find(':input').each(function(index, input) {
|
|
address[$(input).attr('id').replace(self.id+'-', '')] = $(input).val();
|
|
});
|
|
if(this.options.emptyValue){
|
|
if(address.addressLine1 == this.options.emptyValue.addressLine1){
|
|
address.addressLine1 = '';
|
|
}
|
|
if(address.addressLine2 == this.options.emptyValue.addressLine2){
|
|
address.addressLine2 = '';
|
|
}
|
|
if(address.city == this.options.emptyValue.city){
|
|
address.city = '';
|
|
}
|
|
if(address.state == this.options.emptyValue.state){
|
|
address.state = '';
|
|
}
|
|
if(address.zip == this.options.emptyValue.zip){
|
|
address.zip = '';
|
|
}
|
|
}
|
|
|
|
return address;
|
|
},
|
|
|
|
validate: function(){
|
|
if(!this.parentJFormSection.parentJFormPage.jFormer.options.clientSideValidation) {
|
|
return;
|
|
}
|
|
|
|
var self = this;
|
|
if(!this.changed){
|
|
this._super();
|
|
}
|
|
|
|
setTimeout(function() {
|
|
if(!self.component.hasClass('jFormComponentHighlight')){
|
|
if(self.options.validationOptions.length < 1){
|
|
return true;
|
|
}
|
|
self.clearValidation();
|
|
$.each(self.options.validationOptions, function(validationType, validationOptions){
|
|
validationOptions['value'] = self.getValue();
|
|
var validation = self.validationFunctions[validationType](validationOptions);
|
|
if(validation == 'success'){
|
|
return;
|
|
}
|
|
else {
|
|
$.merge(self.errorMessageArray, validation);
|
|
self.validationPassed = false;
|
|
}
|
|
});
|
|
if(self.errorMessageArray.length > 0 ){
|
|
self.handleErrors();
|
|
}
|
|
self.changed = false;
|
|
return self.validationPassed;
|
|
}
|
|
}, 1);
|
|
|
|
},
|
|
|
|
addEmptyValues: function(){
|
|
var self = this,
|
|
emptyValue = this.options.emptyValue;
|
|
$.each(emptyValue, function(key, value){
|
|
var input = self.component.find('input[id*='+key+']');
|
|
input.addClass('defaultValue');
|
|
input.focus(function(event){
|
|
if ($.trim($(event.target).val()) == value ){
|
|
$(event.target).val('');
|
|
$(event.target).removeClass('defaultValue');
|
|
}
|
|
});
|
|
input.blur(function(event){
|
|
if ($.trim($(event.target).val()) == '' ){
|
|
$(event.target).addClass('defaultValue');
|
|
$(event.target).val(value);
|
|
}
|
|
});
|
|
input.trigger('blur');
|
|
});
|
|
}
|
|
});JFormComponentCreditCard = JFormComponent.extend({
|
|
init: function(parentJFormSection, jFormComponentId, jFormComponentType, options) {
|
|
this._super(parentJFormSection, jFormComponentId, jFormComponentType, options);
|
|
},
|
|
|
|
initialize: function(){
|
|
this.tipTarget = this.component;
|
|
if(this.options.emptyValues){
|
|
this.addEmptyValues();
|
|
}
|
|
this.validationFunctions = {
|
|
//Name Validations
|
|
'required': function(options) {
|
|
var errorMessageArray = [];
|
|
if(options.value.cardType != undefined && options.value.cardType == '') {
|
|
errorMessageArray.push(['Card type is required.']);
|
|
}
|
|
if(options.value.cardNumber == '') {
|
|
errorMessageArray.push(['Credit card number is required.']);
|
|
}
|
|
if(options.value.cardNumber != '' && options.value.cardNumber.match(/[^\d]/)){
|
|
errorMessageArray.push(['Card number may only contain numbers.']);
|
|
}
|
|
if(options.value.cardNumber != '' && (options.value.cardNumber.length < 13 || options.value.cardNumber.length > 16)){
|
|
errorMessageArray.push(['Card number must contain 13 to 16 digits.']);
|
|
}
|
|
if(options.value.expirationMonth == '') {
|
|
errorMessageArray.push(['Expiration month is required.']);
|
|
}
|
|
if(options.value.expirationYear == '') {
|
|
errorMessageArray.push(['Expiration year is required.']);
|
|
}
|
|
if(options.value.securityCode != undefined && options.value.securityCode == '') {
|
|
errorMessageArray.push(['Security code is required.']);
|
|
}
|
|
if(options.value.securityCode != undefined && options.value.securityCode != '' && options.value.securityCode.match(/[^\d]/)) {
|
|
errorMessageArray.push(['Security code may only contain numbers.']);
|
|
}
|
|
if(options.value.securityCode != undefined && options.value.securityCode != '' && options.value.securityCode.length < 3){
|
|
errorMessageArray.push(['Security code must contain 3 or 4 digits.']);
|
|
}
|
|
return errorMessageArray.length < 1 ? 'success' : errorMessageArray;
|
|
}
|
|
}
|
|
|
|
this.changed = false;
|
|
},
|
|
|
|
setValue: function(data) {
|
|
var self = this;
|
|
if(this.options.emptyValues){
|
|
if(data.cardType != undefined){
|
|
self.component.find(':input[id*=cardType]').removeClass('defaultValue').val(data.cardType).blur();
|
|
}
|
|
if(data.cardNumber != this.options.emptyValues.cardNumber){
|
|
self.component.find(':input[id*=cardNumber]').removeClass('defaultValue').val(data.cardNumber).blur();
|
|
}
|
|
self.component.find(':input[id*=expirationMonth]').removeClass('defaultValue').val(data.expirationMonth).blur();
|
|
self.component.find(':input[id*=expirationYear]').removeClass('defaultValue').val(data.expirationYear).blur();
|
|
if(data.securityCode != undefined && data.securityCode != this.options.emptyValues.securityCode){
|
|
self.component.find(':input[id*=expirationMonth]').removeClass('defaultValue').val(data.expirationMonth).blur();
|
|
}
|
|
}
|
|
else {
|
|
if(data.cardType != undefined){
|
|
self.component.find(':input[id*=cardType]').val(data.cardType);
|
|
}
|
|
self.component.find(':input[id*=cardNumber]').val(data.cardNumber);
|
|
self.component.find(':input[id*=expirationMonth]').val(data.expirationMonth);
|
|
self.component.find(':input[id*=expirationYear]').val(data.expirationYear);
|
|
if(data.securityCode != undefined){
|
|
self.component.find(':input[id*=securityCode]').val(data.securityCode);
|
|
}
|
|
}
|
|
this.validate(true);
|
|
/*
|
|
$.each(data, function(key, value){
|
|
if(self.options.emptyValue[key] != undefined && data[key] != self.options.emptyValue[key]){
|
|
self.component.find(':input[id*='+key+']').removeClass('defaultValue').val(value).trigger('component:changed').blur();
|
|
} else if (self.options.emptyValue[key] == undefined) {
|
|
self.component.find(':input[id*='+key+']').val(value).trigger('component:changed');
|
|
} else {
|
|
self.component.find(':input[id*='+key+']').val(value).trigger('component:changed');
|
|
}
|
|
});*/
|
|
},
|
|
|
|
getValue: function() {
|
|
if(this.disabledByDependency || this.parentJFormSection.disabledByDependency){
|
|
return null;
|
|
}
|
|
var creditCardInfo = {};
|
|
|
|
// Get the values
|
|
if(this.component.find(':input[id*=cardType]').length != 0){
|
|
creditCardInfo.cardType = this.component.find(':input[id*=cardType]').val();
|
|
}
|
|
creditCardInfo.cardNumber = this.component.find(':input[id*=cardNumber]').val();
|
|
creditCardInfo.expirationMonth = this.component.find(':input[id*=expirationMonth]').val();
|
|
creditCardInfo.expirationYear = this.component.find(':input[id*=expirationYear]').val();
|
|
if(this.component.find(':input[id*=securityCode]').length != 0){
|
|
creditCardInfo.securityCode = this.component.find(':input[id*=securityCode]').val();
|
|
}
|
|
if(this.options.emptyValues){
|
|
if(creditCardInfo.cardNumber == this.options.emptyValues.cardNumber){
|
|
creditCardInfo.cardNumber = '';
|
|
}
|
|
if(creditCardInfo.securityCode != undefined && creditCardInfo.securityCode == this.options.emptyValues.securityCode){
|
|
creditCardInfo.securityCode = '';
|
|
}
|
|
}
|
|
return creditCardInfo;
|
|
},
|
|
|
|
validate: function(){
|
|
if(!this.parentJFormSection.parentJFormPage.jFormer.options.clientSideValidation) {
|
|
return;
|
|
}
|
|
|
|
var self = this;
|
|
if(!this.changed){
|
|
this._super();
|
|
}
|
|
|
|
setTimeout(function() {
|
|
if(!self.component.hasClass('jFormComponentHighlight')){
|
|
if(self.options.validationOptions.length < 1){
|
|
return true;
|
|
}
|
|
self.clearValidation();
|
|
$.each(self.options.validationOptions, function(validationType, validationOptions){
|
|
validationOptions['value'] = self.getValue();
|
|
var validation = self.validationFunctions[validationType](validationOptions);
|
|
if(validation == 'success'){
|
|
return;
|
|
}
|
|
else {
|
|
$.merge(self.errorMessageArray, validation);
|
|
self.validationPassed = false;
|
|
}
|
|
});
|
|
if(self.errorMessageArray.length > 0 ){
|
|
self.handleErrors();
|
|
}
|
|
self.changed = false;
|
|
return self.validationPassed;
|
|
}
|
|
}, 1);
|
|
|
|
},
|
|
|
|
addEmptyValues: function(){
|
|
var self = this,
|
|
emptyValues = this.options.emptyValues;
|
|
$.each(emptyValues, function(key, value){
|
|
var input = self.component.find('input[id*='+key+']');
|
|
input.addClass('defaultValue');
|
|
input.focus(function(event){
|
|
if ($.trim($(event.target).val()) == value ){
|
|
$(event.target).val('');
|
|
$(event.target).removeClass('defaultValue');
|
|
}
|
|
});
|
|
input.blur(function(event){
|
|
if ($.trim($(event.target).val()) == '' ){
|
|
$(event.target).addClass('defaultValue');
|
|
$(event.target).val(value);
|
|
}
|
|
});
|
|
input.trigger('blur');
|
|
});
|
|
}
|
|
});JFormComponentDate = JFormComponent.extend({
|
|
init: function(parentJFormSection, jFormComponentId, jFormComponentType, options) {
|
|
this._super(parentJFormSection, jFormComponentId, jFormComponentType, options);
|
|
},
|
|
|
|
initialize: function() {
|
|
var self = this;
|
|
this.monthArray = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
|
this.addCalendar();
|
|
this.tipTarget = this.component.find('.jFormComponentDateSelector');
|
|
if(this.tipTarget == undefined){
|
|
this.tipTarget = this.component;
|
|
}
|
|
if(this.options.validationOptions.length == 0){
|
|
this.reformValidations();
|
|
}
|
|
this.validationFunctions = {
|
|
//Date validations
|
|
'required': function(options) {
|
|
var errorMessageArray = [];
|
|
if(options.value.month == '' || options.value.day == '' || options.value.year == '' || options.value == null){
|
|
errorMessageArray.push('Required.');
|
|
return errorMessageArray;
|
|
}
|
|
|
|
var month = parseInt(options.value.month);
|
|
var day = parseInt(options.value.day);
|
|
var year = options.value.year;
|
|
var badDay = false;
|
|
if(!year.match(/[\d]{4}/)){
|
|
errorMessageArray.push('You must enter a valid year.');
|
|
}
|
|
if(month < 1 || month > 12){
|
|
errorMessageArray.push('You must enter a valid month.');
|
|
}
|
|
if(month==4 || month==6 || month==9 || month==11) {
|
|
if(day > 30){
|
|
badDay = true;
|
|
}
|
|
}
|
|
else if (month==2) {
|
|
year = parseInt(year);
|
|
var days = ((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28
|
|
if(day > days){
|
|
badDay = true;
|
|
}
|
|
}
|
|
if (day > 31 || day < 1){
|
|
badDay = true;
|
|
}
|
|
if(badDay){
|
|
errorMessageArray.push('You must enter a valid day.');
|
|
}
|
|
|
|
return errorMessageArray.length < 1 ? 'success' : errorMessageArray;
|
|
},
|
|
'minDate': function(options) {
|
|
var errorMessageArray = [];
|
|
var minDate = self.getDateFromString(options.minDate);
|
|
var selectedDate = self.getDateFromObject(options.value);
|
|
if(selectedDate < minDate) {
|
|
errorMessageArray.push('Date must be on or after ' + self.monthArray[minDate.getMonth()] + ' ' + minDate.getDate() + ', ' + minDate.getFullYear() + '.');
|
|
}
|
|
return errorMessageArray.length < 1 ? 'success' : errorMessageArray;
|
|
},
|
|
'maxDate': function(options) {
|
|
var errorMessageArray = [];
|
|
var maxDate = self.getDateFromString(options.maxDate);
|
|
var selectedDate = self.getDateFromObject(options.value);
|
|
if(selectedDate > maxDate) {
|
|
errorMessageArray.push('Date must be on or before ' + self.monthArray[maxDate.getMonth()] + ' ' + maxDate.getDate() + ', ' + maxDate.getFullYear() + '.');
|
|
}
|
|
return errorMessageArray.length < 1 ? 'success' : errorMessageArray;
|
|
},
|
|
'teenager': function(options) {
|
|
var errorMessageArray = 'You must be at least 13 years old to use this site.',
|
|
birthday = new Date(options.value.year, options.value.month, options.value.day),
|
|
now = new Date(),
|
|
limit = new Date(now.getFullYear() - 13 , now.getMonth(), now.getDate()),
|
|
timeDifference = (limit - birthday);
|
|
return options.value == '' || timeDifference >= 0 ? 'success' : errorMessageArray;
|
|
}
|
|
}
|
|
},
|
|
|
|
highlight: function() {
|
|
var self = this
|
|
// Add the highlight class and trigger the highlight
|
|
this.component.addClass('jFormComponentHighlight').trigger('jFormComponent:highlighted', this.component);
|
|
setTimeout(function(){
|
|
self.component.trigger('jFormComponent:showTip', self.component);
|
|
}, 1);
|
|
|
|
},
|
|
|
|
addCalendar: function(){
|
|
var input = this.component.find('input:text');
|
|
var datePicker = input.date_input();
|
|
input.bind('keyup', function(event){
|
|
if (event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 || event.keyCode == 33 || event.keyCode == 34 || event.keyCode == 38 || event.keyCode == 40 || event.keyCode == 37 || event.keyCode == 39 ){
|
|
return;
|
|
} else if(input.val().length == 10){
|
|
input.trigger('change');
|
|
}
|
|
});
|
|
},
|
|
|
|
getValue: function() {
|
|
if(this.disabledByDependency || this.parentJFormSection.disabledByDependency){
|
|
return null;
|
|
}
|
|
var date = {'month': '' , 'day': '', 'year':''};
|
|
var value = $('#'+this.id).val();
|
|
if(value != ''){
|
|
value = value.split(value.match(/[^\d]/));
|
|
if (value[0] != undefined){
|
|
date.month = value[0];
|
|
}
|
|
if(value[1] != undefined) {
|
|
date.day = value[1];
|
|
}
|
|
if(value[2] != undefined){
|
|
date.year = value[2];
|
|
}
|
|
}
|
|
|
|
return date;
|
|
},
|
|
|
|
// Expects YYYY-MM-DD
|
|
getDateFromString: function(string) {
|
|
var timeArray = string.split('-');
|
|
return new Date(parseInt(timeArray[0], 10), parseInt(timeArray[1], 10)-1, parseInt(timeArray[2], 10));
|
|
},
|
|
|
|
// Expects {year,month,day}
|
|
getDateFromObject: function(object) {
|
|
return new Date(parseInt(object.year, 10), parseInt(object.month, 10) - 1, parseInt(object.day, 10));
|
|
},
|
|
|
|
setValue: function(value) {
|
|
|
|
if(value == null || value.month == 'undefined' || value.year == 'undefined' || value.day == 'undefined'){
|
|
$('#'+this.id).val('');
|
|
return;
|
|
} else {
|
|
$('#'+this.id).val(padString(value.month) +'/'+ padString(value.day) +"/"+ value.year)
|
|
if($('#'+this.id).val() == '//'){
|
|
$('#'+this.id).val('');
|
|
}
|
|
}
|
|
|
|
this.validate(true);
|
|
return ;
|
|
|
|
function padString(number){
|
|
if(number == '' || number == 'undefined'){
|
|
return '';
|
|
}
|
|
number = '' + number;
|
|
if(number.length == 1){
|
|
number = '0'+number;
|
|
}
|
|
return number;
|
|
}
|
|
|
|
}
|
|
|
|
});JFormComponentDropDown = JFormComponent.extend({
|
|
init: function(parentJFormSection, jFormComponentId, jFormComponentType, options) {
|
|
this._super(parentJFormSection, jFormComponentId, jFormComponentType, options);
|
|
},
|
|
|
|
initialize: function(){
|
|
this.tipTarget = this.component.find('select:last');
|
|
},
|
|
|
|
getValue: function() {
|
|
if(this.disabledByDependency || this.parentJFormSection.disabledByDependency){
|
|
return null;
|
|
}
|
|
var dropDownValue = $('#'+this.id).val();
|
|
return dropDownValue;
|
|
},
|
|
|
|
setValue: function(value){
|
|
$('#'+this.id).val(value).trigger('jFormComponent:changed');
|
|
//this.component.find('option[value=\''+value+'\']').attr('selected', 'selected').trigger('jFormComponent:changed');
|
|
this.validate(true);
|
|
}
|
|
|
|
});JFormComponentFile = JFormComponent.extend({
|
|
init: function(parentJFormSection, jFormComponentId, jFormComponentType, options) {
|
|
this._super(parentJFormSection, jFormComponentId, jFormComponentType, options);
|
|
},
|
|
|
|
initialize: function(){
|
|
var tipTarget = this.component.find('button').parent();
|
|
if (tipTarget.length < 1){
|
|
tipTarget = this.component.find('input:file');
|
|
}
|
|
this.tipTarget = tipTarget;
|
|
if(this.options.customStyle){
|
|
this.setOnChange();
|
|
}
|
|
this.validationFunctions = {
|
|
'required': function(options) {
|
|
var errorMessageArray = ['Required.'];
|
|
return options.value != '' ? 'success' : errorMessageArray;
|
|
},
|
|
'extension': function(options) {
|
|
var errorMessageArray = ['Must have the .'+options.extension+' extension.'];
|
|
var extensionRegex = new RegExp('\\.'+options.extension+'$', 'i');
|
|
return options.value == '' || options.value.match(extensionRegex) ? 'success' : errorMessageArray;
|
|
},
|
|
'extensionType': function(options) {
|
|
var extensionType;
|
|
var errorMessageArray = ['Incorrect file type.'];
|
|
if($.isArray(options.extensionType)){
|
|
extensionType = new RegExp('\\.('+options.extensionType.join('|')+')$', 'i');
|
|
}
|
|
else {
|
|
var extensionObject = {};
|
|
extensionObject.image = /\.(bmp|gif|jpe?g|png|psd|psp|thm|tif)/i;
|
|
extensionObject.document = /\.(doc|docx|log|msg|pages|rtf|txt|wpd|wps)/i;
|
|
extensionObject.audio = /\.(aac|aif|iff|m3u|mid|midi|mp3|mpa|ra|wav|wma)/i;
|
|
extensionObject.video = /\.(3g2|3gp|asf|asx|avi|flv|mov|mp4|mpg|rm|swf|vob|wmv)/i;
|
|
extensionObject.web = /\.(asp|css|htm|html|js|jsp|php|rss|xhtml)/i;
|
|
extensionType = new RegExp(extensionObject[options.extensionType]);
|
|
errorMessageArray = ['Must be an '+options.extensionType+' file type.'];
|
|
}
|
|
return options.value == '' || options.value.match(extensionType) ? 'success' : errorMessageArray;
|
|
},
|
|
'size' : function(options){
|
|
return true;
|
|
},
|
|
'imageDimensions' : function(options){
|
|
return true;
|
|
},
|
|
'minImageDimensions' : function(options){
|
|
return true;
|
|
}
|
|
}
|
|
},
|
|
|
|
setOnChange: function(){
|
|
var self = this;
|
|
|
|
this.component.find('input:file').change(function(event){
|
|
var value = event.target.value.replace(/.+\\/, '');
|
|
self.component.find('input:text').val(value);
|
|
});
|
|
|
|
},
|
|
|
|
setValue: function() {
|
|
return false;
|
|
},
|
|
|
|
getValue: function() {
|
|
if(this.disabledByDependency || this.parentJFormSection.disabledByDependency){
|
|
return null;
|
|
}
|
|
return this.component.find('input:file').val();
|
|
},
|
|
|
|
validate: function() {
|
|
this._super();
|
|
}
|
|
});JFormComponentHidden = JFormComponent.extend({
|
|
init: function(parentJFormSection, jFormComponentId, jFormComponentType, options) {
|
|
this._super(parentJFormSection, jFormComponentId, jFormComponentType, options);
|
|
},
|
|
|
|
getValue: function() {
|
|
if(this.disabledByDependency || this.parentJFormSection.disabledByDependency){
|
|
return null;
|
|
}
|
|
return $('#'+this.id).val();
|
|
},
|
|
|
|
validate: function() {
|
|
this._super();
|
|
}
|
|
});
|
|
JFormComponentLikert = JFormComponent.extend({
|
|
init: function(parentJFormSection, jFormComponentId, jFormComponentType, options) {
|
|
this._super(parentJFormSection, jFormComponentId, jFormComponentType, options);
|
|
},
|
|
|
|
initialize: function(){
|
|
var self = this;
|
|
this.changed = false;
|
|
this.tipTarget = this.component;
|
|
this.statementComponentArray = {};
|
|
|
|
$.each(this.options.statementArray, function(statementName, statementOptions){
|
|
if(!jFormerUtility.empty(self.options.validationOptions)){
|
|
statementOptions.validationOptions = self.options.validationOptions;
|
|
}
|
|
var newLikertStatment = new JFormComponentLikertStatement(self.parentJFormSection, statementName, 'JFormComponentLikertStatement', statementOptions);
|
|
newLikertStatment.id = self.id+'-'+newLikertStatment.id
|
|
self.parentJFormSection.addComponent(newLikertStatment);
|
|
self.statementComponentArray[statementName] = newLikertStatment;
|
|
});
|
|
},
|
|
|
|
clearValidation: function (){
|
|
$.each(this.statementComponentArray, function(index, statement){
|
|
statement.clearValidation();
|
|
});
|
|
},
|
|
|
|
setValue: function(data) {
|
|
var self = this;
|
|
return
|
|
/*
|
|
$.each(data, function(key, value){
|
|
if(data[key] != self.options.emptyValue[key]){
|
|
self.component.find('input[id*='+key+']').removeClass('defaultValue').val(value).blur().trigger('component:changed');
|
|
}
|
|
});*/
|
|
},
|
|
|
|
catchComponentChangedEventListener: function() { return null },
|
|
addHighlightListeners: function() { return null },
|
|
defineComponentChangedEventListener: function() { return null },
|
|
addTipListeners: function() { return null },
|
|
|
|
getValue: function() {
|
|
var value = {};
|
|
$.each(this.statementComponentArray, function(key, component){
|
|
value[key] = component.getValue();
|
|
})
|
|
|
|
|
|
return value;
|
|
},
|
|
|
|
handleErrors: function() {
|
|
var self = this;
|
|
return true;
|
|
},
|
|
|
|
handleServerValidationResponse: function(errorMessageArray) {
|
|
var self = this;
|
|
if(errorMessageArray.length > 0) {
|
|
$.each(this.instanceArray, function(key, instance){
|
|
$.each(errorMessageArray, function(index, passedErrorArray){
|
|
$.each(passedErrorArray, function(statementKey, statementError){
|
|
var likertStatement = self.parentJFormSection.jFormComponents[instance.id+'-'+statementKey];
|
|
if(likertStatement != undefined){
|
|
likertStatement.errorMessageArray = [statementError];
|
|
likertStatement.validationPassed = false;
|
|
likertStatement.handleErrors();
|
|
}
|
|
}) ;
|
|
});
|
|
});
|
|
}
|
|
},
|
|
|
|
validate: function(){
|
|
var self = this;
|
|
return true;
|
|
}
|
|
|
|
});
|
|
JFormComponentLikertStatement = JFormComponent.extend({
|
|
init: function(parentJFormSection, jFormComponentId, jFormComponentType, options) {
|
|
this._super(parentJFormSection, jFormComponentId, jFormComponentType, options);
|
|
},
|
|
|
|
initialize: function(){
|
|
var self = this
|
|
this.changed = false;
|
|
this.component = $('input[name='+this.id+']:first').closest('tr');
|
|
this.tipTarget = this.component;
|
|
this.tipDiv = this.component.find('div.jFormComponentLikertStatementTip');
|
|
|
|
// Allow the user to click on the box
|
|
//this.component.find('td').click(function(event){
|
|
//event.preventDefault();
|
|
//$(event.target).find('input').attr("checked", "checked").trigger('click');
|
|
//});
|
|
|
|
this.validationFunctions = {
|
|
'required': function(options) {
|
|
var errorMessageArray = ['Required.'];
|
|
return options.value.length > 0 ? 'success' : errorMessageArray;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
setValue: function(data) {
|
|
var self = this;
|
|
self.component.find('input').val([data]);
|
|
this.validate(true);
|
|
/*
|
|
$.each(data, function(key, value){
|
|
if(data[key] != self.options.emptyValue[key]){
|
|
self.component.find('input[id*='+key+']').removeClass('defaultValue').val(value).blur().trigger('component:changed');
|
|
}
|
|
});*/
|
|
},
|
|
|
|
validate: function(){
|
|
this._super();
|
|
},
|
|
|
|
getValue: function() {
|
|
if(this.disabledByDependency || this.parentJFormSection.disabledByDependency){
|
|
return null;
|
|
}
|
|
var value = this.component.find('input:checked');
|
|
if(value.length > 0){
|
|
value = value.val()
|
|
} else {
|
|
value = '';
|
|
}
|
|
return value;
|
|
}
|
|
});JFormComponentMultipleChoice = JFormComponent.extend({
|
|
init: function(parentJFormSection, jFormComponentId, jFormComponentType, options) {
|
|
this._super(parentJFormSection, jFormComponentId, jFormComponentType, options);
|
|
},
|
|
|
|
initialize: function(){
|
|
this.tipTarget = this.component;
|
|
this.addChoiceTips();
|
|
this.validationFunctions = {
|
|
//MultipleChoice validations
|
|
'required': function(options) {
|
|
var errorMessageArray = ['Notwendig.'];
|
|
return options.value.length > 0 ? 'success' : errorMessageArray;
|
|
},
|
|
'minOptions': function(options) {
|
|
var errorMessageArray = ['You must select more than '+ options.minOptions +' options'];
|
|
return options.value.length == 0 || options.value.length > options.minOptions ? 'success' : errorMessageArray;
|
|
},
|
|
'maxOptions': function(options) {
|
|
if (options.maxOptions == 1)
|
|
{
|
|
var errorMessageArray = ['Es darf nur '+ options.maxOptions +' Option ausgewählt werden. Es wurden aber '+ options.value.length + ' ausgewählt.'];
|
|
}
|
|
else
|
|
{
|
|
var errorMessageArray = ['Es dürfen nur '+ options.maxOptions +' Optionen ausgewählt werden. Es wurden aber '+ options.value.length + ' ausgewählt.'];
|
|
}
|
|
return options.value.length == 0 || options.value.length <= options.maxOptions ? 'success' : errorMessageArray;
|
|
}
|
|
}
|
|
},
|
|
|
|
addChoiceTips: function(){
|
|
var self = this;
|
|
var tips = this.component.find('div.jFormComponentMultipleChoiceTip');
|
|
if(tips.length > 0) {
|
|
tips.each(function(index, tip) {
|
|
var tipTarget = $(tip).prev('label').find('.jFormComponentMultipleChoiceTipIcon');
|
|
if (tipTarget.length == 0){
|
|
tipTarget = $(tip).parent();
|
|
}
|
|
tipTarget.simpletip({
|
|
position: 'topRight',
|
|
content: $(tip),
|
|
baseClass: 'jFormerTip jFormComponentMultipleChoiceTip',
|
|
hideEffect: 'none'
|
|
});
|
|
});
|
|
}
|
|
},
|
|
|
|
getValue: function() {
|
|
if(this.disabledByDependency || this.parentJFormSection.disabledByDependency){
|
|
return null;
|
|
}
|
|
var multipleChoiceValue
|
|
if(this.options.multipleChoiceType == 'checkbox') {
|
|
multipleChoiceValue = [];
|
|
this.component.find('input:checked').each(function(index, input){
|
|
multipleChoiceValue.push($(input).val());
|
|
});
|
|
}
|
|
else {
|
|
if(this.component.find('input:checked').length > 0){
|
|
multipleChoiceValue = this.component.find('input:checked').val();
|
|
}
|
|
else {
|
|
multipleChoiceValue = '';
|
|
}
|
|
}
|
|
return multipleChoiceValue;
|
|
},
|
|
|
|
setValue: function(data) {
|
|
var self = this;
|
|
// Checkbox
|
|
if(this.options.multipleChoiceType == 'checkbox') {
|
|
$.each(data, function(key, value){
|
|
self.component.find('input[value=\''+value+'\']').attr('checked', 'checked').trigger('jFormComponent:changed');
|
|
});
|
|
}
|
|
// Radio button
|
|
else {
|
|
this.component.find('input[value=\''+data+'\']').attr('checked', 'checked').trigger('jFormComponent:changed');
|
|
|
|
if(data == null) {
|
|
this.component.find('input').attr('checked', false).trigger('jFormComponent:changed');
|
|
}
|
|
}
|
|
this.validate(true);
|
|
}
|
|
});JFormComponentName = JFormComponent.extend({
|
|
init: function(parentJFormSection, jFormComponentId, jFormComponentType, options) {
|
|
this._super(parentJFormSection, jFormComponentId, jFormComponentType, options);
|
|
},
|
|
|
|
initialize: function(){
|
|
this.tipTarget = this.component.find('input:last');
|
|
if(this.options.emptyValue){
|
|
this.addEmptyValues();
|
|
}
|
|
this.changed = false;
|
|
this.validationFunctions = {
|
|
'required': function(options) {
|
|
var errorMessageArray = [];
|
|
if(options.value.firstName == '') {
|
|
errorMessageArray.push(['Vorname ist notwenig.']);
|
|
}
|
|
if(options.value.lastName == '') {
|
|
errorMessageArray.push(['Nachname ist notwendig.']);
|
|
}
|
|
return errorMessageArray.length < 1 ? 'success' : errorMessageArray;
|
|
}
|
|
}
|
|
},
|
|
|
|
setValue: function(data) {
|
|
var self = this;
|
|
if(this.options.emptyValue){
|
|
if(data.firstName != self.options.emptyValue.firstName){
|
|
self.component.find('input[id*=firstName]').removeClass('defaultValue').val(data.firstName).blur();
|
|
}
|
|
self.component.find('input[id*=middleInitial]').removeClass('defaultValue').val(data.middleInitial).blur();
|
|
if(data.lastName != self.options.emptyValue.lastName){
|
|
self.component.find('input[id*=lastName]').removeClass('defaultValue').val(data.lastName).blur();
|
|
}
|
|
} else {
|
|
self.component.find('input[id*=firstName]').val(data.firstName)
|
|
self.component.find('input[id*=middleInitial]').val(data.middleInitial);
|
|
self.component.find('input[id*=lastName]').val(data.lastName);
|
|
}
|
|
this.validate(true);
|
|
|
|
/*
|
|
$.each(data, function(key, value){
|
|
if(data[key] != self.options.emptyValue[key]){
|
|
self.component.find('input[id*='+key+']').removeClass('defaultValue').val(value).blur().trigger('component:changed');
|
|
}
|
|
});*/
|
|
},
|
|
|
|
getValue: function() {
|
|
if(this.disabledByDependency || this.parentJFormSection.disabledByDependency){
|
|
return null;
|
|
}
|
|
var name = {},
|
|
self = this;
|
|
name.firstName = this.component.find('input[id*=firstName]').val();
|
|
name.middleInitial = this.component.find('input[id*=middleInitial]').val();
|
|
name.lastName = this.component.find('input[id*=lastName]').val();
|
|
|
|
if(this.options.emptyValue){
|
|
if(name.firstName == this.options.emptyValue.firstName){
|
|
name.firstName = '';
|
|
}
|
|
if(this.component.find('input[id$=middleInitial]').hasClass('defaultValue') ){
|
|
name.middleInitial = '';
|
|
}
|
|
if(name.lastName == this.options.emptyValue.lastName){
|
|
name.lastName = '';
|
|
}
|
|
}
|
|
|
|
return name;
|
|
},
|
|
|
|
validate: function(){
|
|
if(!this.parentJFormSection.parentJFormPage.jFormer.options.clientSideValidation) {
|
|
return;
|
|
}
|
|
|
|
var self = this;
|
|
if(!this.changed){
|
|
this._super();
|
|
}
|
|
|
|
setTimeout(function() {
|
|
if(!self.component.hasClass('jFormComponentHighlight')){
|
|
if(self.options.validationOptions.length < 1){
|
|
return true;
|
|
}
|
|
self.clearValidation();
|
|
$.each(self.options.validationOptions, function(validationType, validationOptions){
|
|
validationOptions['value'] = self.getValue();
|
|
var validation = self.validationFunctions[validationType](validationOptions);
|
|
if(validation == 'success'){
|
|
return;
|
|
}
|
|
else {
|
|
$.merge(self.errorMessageArray, validation);
|
|
self.validationPassed = false;
|
|
}
|
|
});
|
|
if(self.errorMessageArray.length > 0 ){
|
|
self.handleErrors();
|
|
}
|
|
self.changed = false;
|
|
return self.validationPassed;
|
|
}
|
|
}, 1);
|
|
},
|
|
|
|
addEmptyValues: function(){
|
|
var self = this,
|
|
emptyValue = this.options.emptyValue;
|
|
$.each(emptyValue, function(key, value){
|
|
var input = self.component.find('input[id*='+key+']');
|
|
input.addClass('defaultValue');
|
|
input.focus(function(event){
|
|
if ($.trim($(event.target).val()) == value ){
|
|
$(event.target).val('');
|
|
$(event.target).removeClass('defaultValue');
|
|
}
|
|
});
|
|
input.blur(function(event){
|
|
if ($.trim($(event.target).val()) == '' ){
|
|
$(event.target).addClass('defaultValue');
|
|
$(event.target).val(value);
|
|
}
|
|
});
|
|
input.trigger('blur');
|
|
});
|
|
}
|
|
});
|
|
JFormComponentSingleLineText = JFormComponent.extend({
|
|
init: function(parentJFormSection, jFormComponentId, jFormComponentType ,options) {
|
|
this._super(parentJFormSection, jFormComponentId, jFormComponentType ,options);
|
|
},
|
|
|
|
initialize: function() {
|
|
this.tipTarget = this.component.find('input:last');
|
|
this.enterSubmits = false;
|
|
if(this.options.mask) {
|
|
this.addMask();
|
|
}
|
|
if(this.options.emptyValue) {
|
|
this.addEmptyValue();
|
|
}
|
|
if(this.component.find('input:password').length == 1 && this.options.showStrength){
|
|
this.addPasswordStrength();
|
|
}
|
|
this.validationFunctions = {
|
|
'alpha': function(options) {
|
|
var errorMessageArray = ['Must only contain letters.'];
|
|
return options.value == '' || options.value.match(/^[A-Za-z]+$/i) ? 'success' : errorMessageArray;
|
|
},
|
|
'alphaDecimal': function(options) {
|
|
var errorMessageArray = ['Must only contain letters, numbers, or periods.'];
|
|
return options.value == '' || options.value.match(/^[A-Za-z0-9\.]+$/i) ? 'success' : errorMessageArray;
|
|
},
|
|
'alphaNumeric': function(options) {
|
|
var errorMessageArray = ['Must only contain letters or numbers.'];
|
|
return options.value == '' || options.value.match(/^[A-Za-z0-9]+$/i) ? 'success' : errorMessageArray;
|
|
},
|
|
'blank': function(options) {
|
|
var errorMessageArray = ['Must be blank.'];
|
|
return $.trim(options.value).length == 0 ? 'success' : errorMessageArray;
|
|
},
|
|
'canadianPostal': function(options) {
|
|
var errorMessageArray = ['Must be a valid Canadian postal code.'];
|
|
return options.value == '' || options.value.match(/^[ABCEGHJKLMNPRSTVXY][0-9][A-Z] [0-9][A-Z][0-9]$/) ? 'success' : errorMessageArray;
|
|
},
|
|
'date': function(options) {
|
|
var errorMessageArray = ['Datumsformat dd.mm.yyyy'];
|
|
return options.value == '' || options.value.match(/^(0?[1-9]|[12][0-9]|3[01])[\- \/.](0?[1-9]|1[012])[\- \/.](19|20)[0-9]{2}$/) ? 'success' : errorMessageArray;
|
|
},
|
|
'dateTime': function(options) {
|
|
var errorMessageArray = ['Must be a date in the mm/dd/yyyy hh:mm:ss tt format. ss and tt are optional.'];
|
|
return options.value == '' || options.value.match(/^(0?[1-9]|1[012])[\- \/.](0?[1-9]|[12][0-9]|3[01])[\- \/.](19|20)?[0-9]{2} [0-2]?\d:[0-5]\d(:[0-5]\d)?( ?(a|p)m)?$/i) ? 'success' : errorMessageArray;
|
|
},
|
|
'decimal': function(options) {
|
|
// Can be negative and have a decimal value
|
|
// Do not accept commas in value as the DB does not accept them
|
|
var errorMessageArray = ['Must be a number without any commas. Decimal is optional.'];
|
|
return options.value == '' || options.value.match(/^-?((\d+(\.\d+)?)|(\.\d+))$/) ? 'success' : errorMessageArray;
|
|
},
|
|
'decimalNegative': function(options) {
|
|
// Must be negative and have a decimal value
|
|
var errorMessageArray = ['Must be a negative number without any commas. Decimal is optional.'];
|
|
var isDecimal = this.decimal(options);
|
|
return options.value == '' || (isDecimal == 'success' && (parseFloat(options.value) < 0)) ? 'success' : errorMessageArray;
|
|
},
|
|
'decimalPositive': function(options) {
|
|
// Must be positive and have a decimal value
|
|
var errorMessageArray = ['Must be a positive number without any commas. Decimal is optional.'];
|
|
var isDecimal = this.decimal(options);
|
|
return options.value == '' || (isDecimal == 'success' && (parseFloat(options.value) > 0)) ? 'success' : errorMessageArray;
|
|
},
|
|
'decimalZeroNegative': function(options) {
|
|
// Must be negative and have a decimal value
|
|
var errorMessageArray = ['Must be zero or a negative number without any commas. Decimal is optional.'];
|
|
var isDecimal = self.validations.decimal({
|
|
"value":options.value
|
|
});
|
|
return options.value == '' || (isDecimal == 'success' && (parseFloat(options.value) <= 0)) ? 'success' : errorMessageArray;
|
|
},
|
|
'decimalZeroPositive': function(options) {
|
|
// Must be positive and have a decimal value
|
|
var errorMessageArray = ['Must be zero or a positive number without any commas. Decimal is optional.'];
|
|
var isDecimal = this.decimal(options);
|
|
return options.value == '' || (isDecimal == 'success' && (parseFloat(options.value) >= 0)) ? 'success' : errorMessageArray;
|
|
},
|
|
'email': function(options) {
|
|
var errorMessageArray = ['Must be a valid e-mail address.'];
|
|
return options.value == '' || options.value.match(/^[A-Z0-9._%\-\+]+@(?:[A-Z0-9\-]+\.)+[A-Z]{2,4}$/i) ? 'success' : errorMessageArray;
|
|
},
|
|
'integer': function(options) {
|
|
var errorMessageArray = ['Must be a whole number.'];
|
|
return options.value == '' || options.value.match(/^-?\d+$/) ? 'success' : errorMessageArray;
|
|
},
|
|
'integerNegative': function(options) {
|
|
var errorMessageArray = ['Must be a negative whole number.'];
|
|
var isInteger = this.integer(options);
|
|
return options.value == '' || (isInteger == 'success' && (parseInt(options.value, 10) < 0)) ? 'success' : errorMessageArray;
|
|
},
|
|
'integerPositive': function(options) {
|
|
var errorMessageArray = ['Must be a positive whole number.'];
|
|
var isInteger = this.integer(options);
|
|
return options.value == '' || (isInteger == 'success' && (parseInt(options.value, 10) > 0)) ? 'success' : errorMessageArray;
|
|
},
|
|
'integerZeroNegative': function(options) {
|
|
var errorMessageArray = ['Must be zero or a negative whole number.'];
|
|
var isInteger = this.integer(options);
|
|
return options.value == '' || (isInteger == 'success' && (parseInt(options.value, 10) <= 0)) ? 'success' : errorMessageArray;
|
|
},
|
|
'integerZeroPositive': function(options) {
|
|
var errorMessageArray = ['Must be zero or a positive whole number.'];
|
|
var isInteger = this.integer(options);
|
|
return options.value == '' || (isInteger == 'success' && (parseInt(options.value, 10) >= 0)) ? 'success' : errorMessageArray;
|
|
},
|
|
'isbn': function(options) {
|
|
//Match an ISBN
|
|
var errorMessageArray = ['Must be a valid ISBN and consist of either ten or thirteen characters.'];
|
|
//For ISBN-10
|
|
if(options.value.match(/^(?=.{13}$)\d{1,5}([\- ])\d{1,7}\1\d{1,6}\1(\d|X)$/)) {
|
|
errorMessageArray = 'sucess';
|
|
}
|
|
if(options.value.match(/^\d{9}(\d|X)$/)) {
|
|
errorMessageArray = 'sucess';
|
|
}
|
|
//For ISBN-13
|
|
if(options.value.match(/^(?=.{17}$)\d{3}([\- ])\d{1,5}\1\d{1,7}\1\d{1,6}\1(\d|X)$/)) {
|
|
errorMessageArray = 'sucess';
|
|
}
|
|
if(options.value.match(/^\d{3}[\- ]\d{9}(\d|X)$/)) {
|
|
errorMessageArray = 'sucess';
|
|
}
|
|
//ISBN-13 without starting delimiter (Not a valid ISBN but less strict validation was requested)
|
|
if(options.value.match(/^\d{12}(\d|X)$/)) {
|
|
errorMessageArray = 'sucess';
|
|
}
|
|
return errorMessageArray;
|
|
},
|
|
'iban': function(options) {
|
|
var errorMessageArray = ['Falsches Format!<br> "DE" gefolgt von 20 Zahlen.'];
|
|
return options.value == '' || options.value.match(/DE[0-9]{20}$/) ? 'success' : errorMessageArray;
|
|
},
|
|
'length' : function(options) {
|
|
var errorMessageArray = ['Must be exactly ' + options.length + ' characters long. Current value is '+ options.value.length +' characters.'];
|
|
return options.value == '' || options.value.length == options.length ? 'success' : errorMessageArray;
|
|
},
|
|
'matches': function(options) {
|
|
var errorMessageArray = ['Does not match.'];
|
|
|
|
// If the match should occur within the same section instances, both the source and destination fields are stored in the same section
|
|
var idToMatch = options.matches;
|
|
|
|
// If it is matching to section instances
|
|
if(options.sectionInstances) {
|
|
var sectionId = options.component.attr('id').match(/-section[\d]+/);
|
|
if(sectionId) {
|
|
idToMatch = options.matches + sectionId;
|
|
}
|
|
}
|
|
|
|
return options.value == $('#'+idToMatch).val() ? 'success' : errorMessageArray;
|
|
},
|
|
'maxLength' : function(options) {
|
|
var errorMessageArray = ['Must be less than ' + options.maxLength + ' characters long. Current value is '+ options.value.length +' characters.'];
|
|
return options.value == '' || options.value.length <= options.maxLength ? 'success' : errorMessageArray;
|
|
},
|
|
'maxFloat': function(options) {
|
|
//Value cannot have more digits then specified in maxFloat
|
|
var errorMessageArray = 'Must be numeric and cannot have more than ' + options.maxFloat + ' decimal place(s).',
|
|
maxFloatPattern = new RegExp('^-?((\\d+(\\.\\d{0,'+ options.maxFloat + '})?)|(\\.\\d{0,' + options + '}))$');
|
|
return options.value == '' || options.value.match(maxFloatPattern) ? 'success' : errorMessageArray;
|
|
},
|
|
'maxValue': function(options) {
|
|
var errorMessageArray = ['Must be numeric with a maximum value of ' + options.maxValue + '.'];
|
|
return (options.value <= options.maxValue) ? 'success' : errorMessageArray;
|
|
},
|
|
'minLength' : function(options) {
|
|
var errorMessageArray = ['Es müssen ' + options.minLength + ' Zeichen eingegeben werden - aktuell sind es nur '+ options.value.length +' Zeichen.'];
|
|
return options.value == '' || options.value.length >= options.minLength ? 'success' : errorMessageArray;
|
|
},
|
|
'minValue': function(options) {
|
|
var errorMessageArray = ['Must be numeric with a minimum value of ' + options.minValue + '.'];
|
|
return (options.value >= options.minValue) ? 'success' : errorMessageArray;
|
|
},
|
|
'money' : function(options) {
|
|
var errorMessageArray = ['Must be a valid dollar value.'];
|
|
return options.value == '' || options.value.match(/^\$?[1-9][0-9]{0,2}(,?[0-9]{3})*(\.[0-9]{2})?$/) ? 'success' : errorMessageArray;
|
|
},
|
|
'moneyNegative' : function(options) {
|
|
var errorMessageArray = ['Must be a valid negative dollar value.'];
|
|
return options.value == '' || options.value.match(/^((-?\$)|(\$-?)|(-))?((\d+(\.\d{2})?)|(\.\d{2}))$/) && RegExp.$5 < 0 ? 'success' : errorMessageArray;
|
|
},
|
|
'moneyPositive' : function(options) {
|
|
var errorMessageArray = ['Must be a valid positive dollar value.'];
|
|
return options.value == '' || options.value.match(/^((-?\$)|(\$-?)|(-))?((\d+(\.\d{2})?)|(\.\d{2}))$/) && RegExp.$5 > 0 ? 'success' : errorMessageArray;
|
|
},
|
|
'moneyZeroNegative' : function(options) {
|
|
var errorMessageArray = ['Must be zero or a valid negative dollar value.'];
|
|
return options.value == '' || options.value.match(/^((-?\$)|(\$-?)|(-))?((\d+(\.\d{2})?)|(\.\d{2}))$/) && RegExp.$5 <= 0 ? 'success' : errorMessageArray;
|
|
},
|
|
'moneyZeroPositive' : function(options) {
|
|
var errorMessageArray = ['Must be zero or a valid positive dollar value.'];
|
|
return options.value == '' || options.value.match(/^((-?\$)|(\$-?)|(-))?((\d+(\.\d{2})?)|(\.\d{2}))$/) && RegExp.$5 >= 0 ? 'success' : errorMessageArray;
|
|
},
|
|
'password': function(options) {
|
|
var errorMessageArray = ['Must be between 4 and 32 characters.'];
|
|
return options.value == '' || options.value.match(/^.{4,32}$/) ? 'success' : errorMessageArray;
|
|
},
|
|
'phone': function(options) {
|
|
var errorMessageArray = ['Must be a 10 digit phone number.'];
|
|
return options.value == '' || options.value.match(/^(1[\-. ]?)?\(?[0-9]{3}\)?[\-. ]?[0-9]{3}[\-. ]?[0-9]{4}$/) ? 'success' : errorMessageArray ;
|
|
},
|
|
'postalZip': function(options) {
|
|
var errorMessageArray = ['Must be a valid United States zip code, Canadian postal code, or United Kingdom postal code.']
|
|
return options.value == '' || this.zip(options) == 'success' || this.canadianPostal(options) == 'success' || this.ukPostal() == 'success' ? 'success' : errorMessageArray;
|
|
},
|
|
'required': function(options) {
|
|
var errorMessageArray = ['Notwendig.'];
|
|
return options.value != '' ? 'success' : errorMessageArray;
|
|
},
|
|
'serverSide': function(options) {
|
|
if(options.value == '') {
|
|
return 'success'
|
|
}
|
|
|
|
// options: value, url, data
|
|
var errorMessageArray = [];
|
|
|
|
options.component.addClass('jFormComponentServerSideCheck');
|
|
$.ajax({
|
|
url: options.url,
|
|
type: 'post',
|
|
data:{
|
|
'task': options.task,
|
|
'value': options.value
|
|
},
|
|
dataType: 'json' ,
|
|
cache: false,
|
|
async: false,
|
|
success: function(json) {
|
|
if(json.status != 'success') {
|
|
errorMessageArray = json.response;
|
|
}
|
|
|
|
options.component.removeClass('jFormComponentServerSideCheck');
|
|
},
|
|
error: function(XMLHttpRequest, textStatus, errorThrown){
|
|
if(textStatus != 'error'){
|
|
errorThrown = textStatus ? textStatus : 'Unknown error';
|
|
}
|
|
errorMessageArray = ['There was an error during server side validation: '+ errorThrown];
|
|
options.component.removeClass('jFormComponentServerSideCheck');
|
|
}
|
|
});
|
|
|
|
return errorMessageArray.length < 1 ? 'success' : errorMessageArray;
|
|
},
|
|
'ssn': function(options) {
|
|
var errorMessageArray = ['Must be a valid United States social security number.'];
|
|
return options.value == '' || options.value.match(/^\d{3}-?\d{2}-?\d{4}$/i) ? 'success' : errorMessageArray;
|
|
},
|
|
'teenager': function(options) {
|
|
var errorMessageArray = 'Must be at least 13 years old.',
|
|
birthday = new Date(options.value),
|
|
now = new Date(),
|
|
limit = new Date(now.getFullYear() - 13 , now.getMonth(), now.getDate()),
|
|
timeDifference = (limit - birthday);
|
|
return options.value == '' || timeDifference >= 0 ? 'success' : errorMessageArray;
|
|
},
|
|
'time': function(options) {
|
|
var errorMessageArray = ['Must be a time in the hh:mm:ss tt format. ss and tt are optional.'];
|
|
return options.value == '' || options.value.match(/^[0-2]?\d:[0-5]\d(:[0-5]\d)?( ?(a|p)m)?$/i) ? 'success' : errorMessageArray;
|
|
},
|
|
'ukPostal' : function(options) {
|
|
var errorMessageArray = ['Must be a valid United Kingdom postal code.'];
|
|
return options.value == '' || options.value.match(/^[A-Z]{1,2}[0-9][A-Z0-9]? [0-9][ABD-HJLNP-UW-Z]{2}$/) ? 'success' : errorMessageArray;
|
|
},
|
|
'url': function(options) {
|
|
var errorMessageArray = ['Must be a valid Internet address.'];
|
|
return options.value == '' || options.value.match(/^((ht|f)tp(s)?:\/\/|www\.)?([\-A-Z0-9.]+)(\.[a-zA-Z]{2,4})(\/[\-A-Z0-9+&@#\/%=~_|!:,.;]*)?(\?[\-A-Z0-9+&@#\/%=~_|!:,.;]*)?$/i) ? 'success' : errorMessageArray;
|
|
},
|
|
'username': function(options) {
|
|
var errorMessageArray = ['Must use 4 to 32 characters and start with a letter.'];
|
|
return options.value == '' || options.value.match(/^[A-Za-z](?=[A-Za-z0-9_.]{3,31}$)[a-zA-Z0-9_]*\.?[a-zA-Z0-9_]*$/) ? 'success' : errorMessageArray;
|
|
},
|
|
'zip': function(options) {
|
|
var errorMessageArray = ['Must be a valid United States zip code.'];
|
|
return options.value == '' || options.value.match(/^[0-9]{5}(?:-[0-9]{4})?$/) ? 'success' : errorMessageArray;
|
|
}
|
|
}
|
|
},
|
|
|
|
addMask: function(){
|
|
this.component.find('input').mask("?"+this.options.mask, {
|
|
placeholder:' '
|
|
});
|
|
},
|
|
|
|
addPasswordStrength: function(){
|
|
var self = this,
|
|
component = this.component;
|
|
|
|
var strengthComponent = "<p id='"+this.id+"-strength' > Strength: <b> " + this.getPasswordStrength().strength + " </b> </p>";
|
|
component.find('div.jFormComponentTip').append(strengthComponent);
|
|
component.find('input:password').bind('keyup', function(event){
|
|
component.find('#'+self.id+'-strength b').text(self.getPasswordStrength().strength);
|
|
self.tip.update(component.find('div.jFormComponentTip').html());
|
|
});
|
|
},
|
|
|
|
getPasswordStrength: function() {
|
|
var value = this.getValue(),
|
|
score = 0,
|
|
strength = 'None';
|
|
|
|
if(value.length >= 6) {
|
|
score = (score + 1); // at least six characters
|
|
}
|
|
if(value.length >= 10) {
|
|
score = (score + 1); // 10 characters+ bonus
|
|
}
|
|
if(value.match(/[a-z]/)) { // [verified] at least one lower case letter
|
|
score = (score + 1);
|
|
}
|
|
if(value.match(/[A-Z]/)) { // [verified] at least one upper case letter
|
|
score = (score + 1);
|
|
}
|
|
if(value.match(/\d+/)) { // [verified] at least one number
|
|
score = (score + 1);
|
|
}
|
|
if(value.match(/(\d.*\d)/)) { // [verified] at least two numbers
|
|
score = (score + 1);
|
|
}
|
|
if(value.match(/[!,@#$%\^&*?_~]/)) { // [verified] at least one special character
|
|
score = (score + 1);
|
|
}
|
|
if(value.match(/([!,@#$%\^&*?_~].*[!,@#$%\^&*?_~])/)) { // [verified] at least two special characters
|
|
score = (score + 1);
|
|
}
|
|
if(value.match(/[a-z]/) && value.match(/[A-Z]/)) { // [verified] both upper and lower case
|
|
score = (score + 1);
|
|
}
|
|
if(value.match(/\d/) && value.match(/\D/)) { // [verified] both letters and numbers
|
|
score = (score + 1);
|
|
}
|
|
if(value.match(/[a-z]/) && value.match(/[A-Z]/) && value.match(/\d/) && value.match(/[!,@#$%\^&*?_~]/)) {
|
|
score = (score + 1);
|
|
}
|
|
|
|
if(score === 0) {
|
|
strength = 'None';
|
|
}
|
|
else if(score <= 1) {
|
|
strength = 'Very Weak';
|
|
}
|
|
else if(score <= 3) {
|
|
strength = 'Weak';
|
|
}
|
|
else if(score <= 5) {
|
|
strength = 'Good';
|
|
}
|
|
else if(score <= 7) {
|
|
strength = 'Strong';
|
|
}
|
|
else if(score > 7) {
|
|
strength = 'Very Strong';
|
|
}
|
|
|
|
return {
|
|
'score': score,
|
|
'strength': strength
|
|
};
|
|
},
|
|
|
|
getValue: function() {
|
|
if(this.disabledByDependency || this.parentJFormSection.disabledByDependency){
|
|
return null;
|
|
}
|
|
var input = $('#'+this.id).val();
|
|
|
|
// Handle empty values
|
|
if(this.options.emptyValue){
|
|
if(input == this.options.emptyValue) {
|
|
return '';
|
|
}
|
|
else {
|
|
return input;
|
|
}
|
|
}
|
|
else {
|
|
return input;
|
|
}
|
|
},
|
|
|
|
setValue: function(value) {
|
|
$('#'+this.id).val(value).removeClass('defaultValue');
|
|
this.validate(true);
|
|
},
|
|
|
|
addEmptyValue: function() {
|
|
var emptyValue = this.options.emptyValue,
|
|
input = this.component.find('input');
|
|
input.addClass('defaultValue');
|
|
input.val(emptyValue);
|
|
|
|
var target ='';
|
|
input.focus(function(event){
|
|
target = $(event.target);
|
|
if ($.trim(target.val()) == emptyValue ){
|
|
target.val('');
|
|
target.removeClass('defaultValue');
|
|
}
|
|
});
|
|
input.blur(function(event){
|
|
target = $(event.target);
|
|
if ($.trim(target.val()) == '' ){
|
|
target.addClass('defaultValue');
|
|
target.val(emptyValue);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
JFormComponentTextArea = JFormComponent.extend({
|
|
init: function(parentJFormSection, jFormComponentId, jFormComponentType, options) {
|
|
this._super(parentJFormSection, jFormComponentId, jFormComponentType, options);
|
|
|
|
if(this.options.allowTabbing) {
|
|
this.allowTabbing();
|
|
}
|
|
if(this.options.emptyValue) {
|
|
this.addEmptyValue();
|
|
}
|
|
if(this.options.autoGrow) {
|
|
this.addAutoGrow();
|
|
}
|
|
},
|
|
|
|
initialize: function() {
|
|
this.tipTarget = this.component.find('textarea');
|
|
if(this.options.emptyValue) {
|
|
this.addEmptyValue();
|
|
}
|
|
},
|
|
|
|
allowTabbing: function() {
|
|
this.component.find('textarea').bind('keydown', function(event) {
|
|
if(event != null) {
|
|
if(event.keyCode == 9) { // tab character
|
|
if(this.setSelectionRange) {
|
|
var sS = this.selectionStart;
|
|
var sE = this.selectionEnd;
|
|
this.value = this.value.substring(0, sS) + "\t" + this.value.substr(sE);
|
|
this.setSelectionRange(sS + 1, sS + 1);
|
|
this.focus();
|
|
}
|
|
else if (this.createTextRange) {
|
|
document.selection.createRange().text = "\t";
|
|
event.returnValue = false;
|
|
}
|
|
if(event.preventDefault) {
|
|
event.preventDefault();
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
addEmptyValue: function() {
|
|
var emptyValue = this.options.emptyValue,
|
|
textArea = this.component.find('textarea');
|
|
textArea.addClass('defaultValue');
|
|
textArea.val(emptyValue);
|
|
|
|
var target ='';
|
|
textArea.focus(function(event){
|
|
target = $(event.target);
|
|
if ($.trim(target.val()) == emptyValue ){
|
|
target.val('');
|
|
target.removeClass('defaultValue');
|
|
}
|
|
});
|
|
textArea.blur(function(event){
|
|
target = $(event.target);
|
|
if ($.trim(target.val()) == '' ){
|
|
target.addClass('defaultValue');
|
|
target.val(emptyValue);
|
|
}
|
|
});
|
|
},
|
|
|
|
addAutoGrow: function() {
|
|
var self = this,
|
|
textArea = this.component.find('textarea'),
|
|
minHeight = textArea.height(),
|
|
lineHeight = textArea.css('lineHeight');
|
|
|
|
var shadow = $('<div></div>').css({
|
|
position: 'absolute',
|
|
top: -10000,
|
|
left: -10000,
|
|
width: textArea.width() - parseInt(textArea.css('paddingLeft')) - parseInt(textArea.css('paddingRight')),
|
|
fontSize: textArea.css('fontSize'),
|
|
fontFamily: textArea.css('fontFamily'),
|
|
lineHeight: textArea.css('lineHeight'),
|
|
resize: 'none'
|
|
}).appendTo(document.body);
|
|
|
|
var update = function() {
|
|
var times = function(string, number) {
|
|
for (var i = 0, r = ''; i < number; i ++) r += string;
|
|
return r;
|
|
};
|
|
|
|
var val = textArea.val().replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/&/g, '&')
|
|
.replace(/\n$/, '<br/> ')
|
|
.replace(/\n/g, '<br/>')
|
|
.replace(/ {2,}/g, function(space) {
|
|
return times(' ', space.length -1) + ' '
|
|
});
|
|
|
|
shadow.html(val);
|
|
textArea.css('height', Math.max(shadow.height() + 20, minHeight));
|
|
|
|
if(self.parentJFormSection.parentJFormPage.jFormer.currentJFormPage) {
|
|
self.parentJFormSection.parentJFormPage.jFormer.adjustHeight({delay:0});
|
|
}
|
|
}
|
|
|
|
$(textArea).change(update).keyup(update).keydown(update);
|
|
update.apply(textArea);
|
|
|
|
return this;
|
|
},
|
|
|
|
getValue: function() {
|
|
if(this.disabledByDependency || this.parentJFormSection.disabledByDependency){
|
|
return null;
|
|
}
|
|
|
|
var input = $('#'+this.id).val();
|
|
|
|
// Handle empty values
|
|
if(this.options.emptyValue){
|
|
if(input == this.options.emptyValue) {
|
|
return '';
|
|
}
|
|
else {
|
|
return input;
|
|
}
|
|
}
|
|
else {
|
|
return input;
|
|
}
|
|
},
|
|
|
|
setValue: function(value) {
|
|
$('#'+this.id).val(value);
|
|
this.validate(true);
|
|
}
|
|
|
|
}); |