/*
* 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 = $('Find Date');
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 = $('
";
this.dateSelector = this.rootLayers = $('').append(nav, tableShell).insertAfter(this.input);
if ($.browser.msie && $.browser.version < 7) {
this.ieframe = $('').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 += "
";
if (currentDay.getMonth() == date.getMonth()) {
dayCells += '
' + currentDay.getDate() + '
';
} else {
dayCells += '
' + currentDay.getDate() + '
';
};
if (this.isLastDayOfWeek(currentDay)) dayCells += "
";
};
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);
///
/*
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=$('').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 = ['
',conf.content.html(),'
'].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
* @author Seth Jensen
* @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: *');
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: *');
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($('
'+json.response.failureNoticeHtml+'
'));
}
$(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($(['
',json.response.failureNoticeHtml,'
'].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('
');
}
}
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 = $('').attr('value', encodeURI(jFormerUtility.jsonEncode(this.getData()))); // Set all non-file values in one form object
var formIdentifier = $('');
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('
'+json.response.failureHtml+'
');
}
// 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('
Output:
'+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 = $('
'+json.response.successPageHtml+'
');
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 = $('
'+json.response.failurePageHtml+'
');
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($('
'));
// 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('
'+json.response.failureNoticeHtml+'
');
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('
'+json.response.failureHtml+'
');
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 = $('');
modalWrapper = $('
'+header+'
'+content+'
');
// 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 = $('');
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('
'+percentCompleted + '%
');
},
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 = '';
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 = '';
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 = $('');
// 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('');
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('');
// 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 = $('