(function ($) {

    $.fn.wAddressForm = function (opts) {
        var settings = $.extend(true, {
            input: {
                url: 'input[data-name="url"]',
                fieldCity: 'input[data-name="field-city"]',
                fieldCountry: 'input[data-name="field-country"]',
                fieldState: 'input[data-name="field-state"]',
                fieldPostal: 'input[data-name="field-postal"]',
                hiddenState: 'input[data-name="state-val"]'
            },
            template: '.address-template'
        }, opts);

        var vars = {
            loading: false
        }

        var $document = $(document);

        var fn = {
            init: function ($this) {
                opts = opts === undefined ? {} : opts;

                var fieldcountry = $this.find(settings.input.fieldCountry).val();
                var $country = $this.find('[name="' + fieldcountry + '"]');

                $country.unbind('change');
                $country.bind('change', function () {
                    var country = $country.val();
                    fn.get($this, country);
                });

                // make sure to update form names for address details (city, state, postal)
                var fieldcity = $this.find(settings.input.fieldCity).val();
                var fieldstate = $this.find(settings.input.fieldState).val();
                var fieldpostal = $this.find(settings.input.fieldPostal).val();

                var $city = $this.find('[name="city"], [name="City"]');
                var $state = $this.find('[name="state"], [name="State"]');
                var $postal = $this.find('[name="postalCode"], [name="PostalCode"]');

                $city.attr('name', fieldcity);
                $state.attr('name', fieldstate);
                $postal.attr('name', fieldpostal);
            },

            get: function ($this, country, callback) {
                var url = $(settings.input.url).val();
                var fieldcountry = $this.find(settings.input.fieldCountry).val();
                var $country = $this.find('[name="' + fieldcountry + '"]');
                var $hiddenState = $this.find(settings.input.hiddenState);
                var $template = $this.find(settings.template);

                if (!vars.loading) {
                    vars.loading = true;

                    var fieldcity = $this.find(settings.input.fieldCity).val();
                    var fieldstate = $this.find(settings.input.fieldState).val();
                    var fieldpostal = $this.find(settings.input.fieldPostal).val();

                    var city = $this.find('[name="' + fieldcity + '"]').val();
                    var state = $this.find('[name="' + fieldstate + '"]').val();
                    var postal = $this.find('[name="' + fieldpostal + '"]').val();

                    if (state !== undefined && state.length > 0)
                        $hiddenState.val(state);

                    $.ajax({
                        type: 'Post',
                        url: url,
                        data: { templateName: country },
                        success: function (html) {
                            $template.empty();
                            $template.append(html);

                            var $city = $template.find('[name="city"], [name="City"]');
                            var $state = $template.find('[name="state"], [name="State"]');
                            var $postal = $template.find('[name="postalCode"], [name="PostalCode"]');

                            $city.val(city);
                            $state.val($hiddenState.val());
                            $postal.val(postal);

                            $city.attr('name', fieldcity);
                            $state.attr('name', fieldstate);
                            $postal.attr('name', fieldpostal);
                        },
                        error: function () { },
                        complete: function () {
                            vars.loading = false;

                            if (typeof callback === 'function')
                                callback($this);
                        }
                    });
                }
            }
        }

        this.each(function () {
            fn.init($(this));
        });

        this.setAddress = function (addressObj) {
            addressObj = $.extend(true, {
                city: '',
                state: '',
                postal: '',
                country: ''
            }, addressObj);

            var $this = $(this);

            fn.get($this, addressObj.country, function () {
                var fieldcity = $this.find(settings.input.fieldCity).val();
                var fieldstate = $this.find(settings.input.fieldState).val();
                var fieldpostal = $this.find(settings.input.fieldPostal).val();
                var fieldcountry = $this.find(settings.input.fieldCountry).val();

                var $city = $this.find('[name="' + fieldcity + '"]');
                var $state = $this.find('[name="' + fieldstate + '"]');
                var $postal = $this.find('[name="' + fieldpostal + '"]');
                var $country = $this.find('[name="' + fieldcountry + '"]');

                $city.val(addressObj.city);
                $state.val(addressObj.state);
                $postal.val(addressObj.postal);
                $country.val(addressObj.country);
            });
        }

        return this;
    };

})(jQuery);

(function ($) {
    $(function () {
        $('.address-form').wAddressForm();
    });
})(jQuery);
;/*  spinutech namespace
*
*   v 1.4.3.1   03-17-2015  Minor fix to validation helper
*   v 1.4.3.0   12-11-2014  Added utility.formatThousands(n)
*   v 1.4.2.0   01-08-2014  Updated spinutech.hashEvent
*   v 1.3.2.0   01-06-2013  Added spinutech.imageScaler(); Added spinutech.call(); Updated spinutech.localStorage
*   v 1.1.0.0   01-03-2013  Updated spinutech.templater
*   v 1.0.0.0   12-30-2013  Initial version
*
*/

window.spinutech = window.spinutech || {};
var spinutech = window.spinutech;
var w = window.spinutech;

/* jQuery Storage API Plugin 1.5.0 https://github.com/julien-maurel/jQuery-Storage-API */
!function (e) { function t(t) { var r, n, i, o = arguments.length, s = window[t], a = arguments, u = a[1]; if (2 > o) throw Error("Minimum 2 arguments must be given"); if (e.isArray(u)) { n = {}; for (var g in u) { r = u[g]; try { n[r] = JSON.parse(s.getItem(r)) } catch (m) { n[r] = s.getItem(r) } } return n } if (2 != o) { try { n = JSON.parse(s.getItem(u)) } catch (m) { throw new ReferenceError(u + " is not defined in this storage") } for (var g = 2; o - 1 > g; g++) if (n = n[a[g]], void 0 === n) throw new ReferenceError([].slice.call(a, 1, g + 1).join(".") + " is not defined in this storage"); if (e.isArray(a[g])) { i = n, n = {}; for (var f in a[g]) n[a[g][f]] = i[a[g][f]]; return n } return n[a[g]] } try { return JSON.parse(s.getItem(u)) } catch (m) { return s.getItem(u) } } function n(t) { var r, n, i = arguments.length, o = window[t], s = arguments, a = s[1], u = s[2], g = {}; if (2 > i || !e.isPlainObject(a) && 3 > i) throw Error("Minimum 3 arguments must be given or second parameter must be an object"); if (e.isPlainObject(a)) { for (var m in a) r = a[m], e.isPlainObject(r) ? o.setItem(m, JSON.stringify(r)) : o.setItem(m, r); return a } if (3 == i) return "object" == typeof u ? o.setItem(a, JSON.stringify(u)) : o.setItem(a, u), u; try { n = o.getItem(a), null != n && (g = JSON.parse(n)) } catch (f) { } n = g; for (var m = 2; i - 2 > m; m++) r = s[m], n[r] && e.isPlainObject(n[r]) || (n[r] = {}), n = n[r]; return n[s[m]] = s[m + 1], o.setItem(a, JSON.stringify(g)), g } function i(t) { var r, n, i = arguments.length, o = window[t], s = arguments, a = s[1]; if (2 > i) throw Error("Minimum 2 arguments must be given"); if (e.isArray(a)) { for (var u in a) o.removeItem(a[u]); return !0 } if (2 == i) return o.removeItem(a), !0; try { r = n = JSON.parse(o.getItem(a)) } catch (g) { throw new ReferenceError(a + " is not defined in this storage") } for (var u = 2; i - 1 > u; u++) if (n = n[s[u]], void 0 === n) throw new ReferenceError([].slice.call(s, 1, u).join(".") + " is not defined in this storage"); if (e.isArray(s[u])) for (var m in s[u]) delete n[s[u][m]]; else delete n[s[u]]; return o.setItem(a, JSON.stringify(r)), !0 } function o(t, r) { var n = u(t); for (var o in n) i(t, n[o]); if (r) for (var o in e.namespaceStorages) g(o) } function s(r) { var n = arguments.length, i = arguments, o = (window[r], i[1]); if (1 == n) return 0 == u(r).length; if (e.isArray(o)) { for (var a = 0; a < o.length; a++) if (!s(r, o[a])) return !1; return !0 } try { var g = t.apply(this, arguments); e.isArray(i[n - 1]) || (g = { totest: g }); for (var a in g) if (!(e.isPlainObject(g[a]) && e.isEmptyObject(g[a]) || e.isArray(g[a]) && !g[a].length) && g[a]) return !1; return !0 } catch (m) { return !0 } } function a(r) { var n = arguments.length, i = arguments, o = (window[r], i[1]); if (2 > n) throw Error("Minimum 2 arguments must be given"); if (e.isArray(o)) { for (var s = 0; s < o.length; s++) if (!a(r, o[s])) return !1; return !0 } try { var u = t.apply(this, arguments); e.isArray(i[n - 1]) || (u = { totest: u }); for (var s in u) if (void 0 === u[s] || null === u[s]) return !1; return !0 } catch (g) { return !1 } } function u(r) { var n = arguments.length, i = window[r], o = arguments, s = (o[1], []), a = {}; if (a = n > 1 ? t.apply(this, o) : i, a._cookie) for (var u in e.cookie()) "" != u && s.push(u.replace(a._prefix, "")); else for (var g in a) s.push(g); return s } function g(t) { if (!t || "string" != typeof t) throw Error("First parameter must be a string"); window.localStorage.getItem(t) || window.localStorage.setItem(t, "{}"), window.sessionStorage.getItem(t) || window.sessionStorage.setItem(t, "{}"); var r = { localStorage: e.extend({}, e.localStorage, { _ns: t }), sessionStorage: e.extend({}, e.sessionStorage, { _ns: t }) }; return e.cookie && (window.cookieStorage.getItem(t) || window.cookieStorage.setItem(t, "{}"), r.cookieStorage = e.extend({}, e.cookieStorage, { _ns: t })), e.namespaceStorages[t] = r, r } var m = "ls_", f = "ss_", c = { _type: "", _ns: "", _callMethod: function (e, t) { var r = [this._type]; return this._ns && r.push(this._ns), [].push.apply(r, t), e.apply(this, r) }, get: function () { return this._callMethod(t, arguments) }, set: function () { var t = arguments.length, i = arguments, o = i[0]; if (1 > t || !e.isPlainObject(o) && 2 > t) throw Error("Minimum 2 arguments must be given or first parameter must be an object"); if (e.isPlainObject(o) && this._ns) { for (var s in o) n(this._type, this._ns, s, o[s]); return o } return r = this._callMethod(n, i), this._ns ? r[o] : r }, remove: function () { if (arguments.length < 1) throw Error("Minimum 1 argument must be given"); return this._callMethod(i, arguments) }, removeAll: function (e) { return this._ns ? (n(this._type, this._ns, {}), !0) : o(this._type, e) }, isEmpty: function () { return this._callMethod(s, arguments) }, isSet: function () { if (arguments.length < 1) throw Error("Minimum 1 argument must be given"); return this._callMethod(a, arguments) }, keys: function () { return this._callMethod(u, arguments) } }; if (e.cookie) { window.name || (window.name = Math.floor(1e8 * Math.random())); var l = { _cookie: !0, _prefix: "", _expires: null, setItem: function (t, r) { e.cookie(this._prefix + t, r, { expires: this._expires }) }, getItem: function (t) { return e.cookie(this._prefix + t) }, removeItem: function (t) { return e.removeCookie(this._prefix + t) }, clear: function () { for (var t in e.cookie()) "" != t && (!this._prefix && -1 === t.indexOf(m) && -1 === t.indexOf(f) || this._prefix && 0 === t.indexOf(this._prefix)) && e.removeCookie(t) }, setExpires: function (e) { return this._expires = e, this } }; window.localStorage || (window.localStorage = e.extend({}, l, { _prefix: m, _expires: 3650 }), window.sessionStorage = e.extend({}, l, { _prefix: f + window.name + "_" })), window.cookieStorage = e.extend({}, l), e.cookieStorage = e.extend({}, c, { _type: "cookieStorage", setExpires: function (e) { return window.cookieStorage.setExpires(e), this } }) } e.initNamespaceStorage = function (e) { return g(e) }, e.localStorage = e.extend({}, c, { _type: "localStorage" }), e.sessionStorage = e.extend({}, c, { _type: "sessionStorage" }), e.namespaceStorages = {}, e.removeAllStorages = function (t) { e.localStorage.removeAll(t), e.sessionStorage.removeAll(t), e.cookieStorage && e.cookieStorage.removeAll(t), t || (e.namespaceStorages = {}) } } (jQuery);

// jquery.ba-hashchange.min.js: http://benalman.com/projects/jquery-hashchange-plugin/
(function (e, t, n) { "$:nomunge"; function c(e) { e = e || location.href; return "#" + e.replace(/^[^#]*#?(.*)$/, "$1") } var r = navigator.userAgent.toLowerCase(); var i = /msie/.test(r); var s = "hashchange", o = document, u, a = e.event.special, f = o.documentMode, l = "on" + s in t && (f === n || f > 7); e.fn[s] = function (e) { return e ? this.bind(s, e) : this.trigger(s) }; e.fn[s].delay = 50; a[s] = e.extend(a[s], { setup: function () { if (l) { return false } e(u.start) }, teardown: function () { if (l) { return false } e(u.stop) } }); u = function () { function d() { var n = c(), r = p(a); if (n !== a) { h(a = n, r); e(t).trigger(s) } else if (r !== a) { location.href = location.href.replace(/#.*/, "") + r } u = setTimeout(d, e.fn[s].delay) } var r = {}, u, a = c(), f = function (e) { return e }, h = f, p = f; r.start = function () { u || d() }; r.stop = function () { u && clearTimeout(u); u = n }; i && !l && function () { var t, n; r.start = function () { if (!t) { n = e.fn[s].src; n = n && n + c(); t = e('<iframe tabindex="-1" title="empty"/>').hide().one("load", function () { n || h(c()); d() }).attr("src", n || "javascript:0").insertAfter("body")[0].contentWindow; o.onpropertychange = function () { try { if (event.propertyName === "title") { t.document.title = o.title } } catch (e) { } } } }; r.stop = f; p = function () { return c(t.location.href) }; h = function (n, r) { var i = t.document, u = e.fn[s].domain; if (n !== r) { i.title = o.title; i.open(); u && i.write('<script>document.domain="' + u + '"</script>'); i.close(); t.location.hash = n } } } (); return r } () })(jQuery, this);

/* jQuery.cookie https://github.com/carhartl/jquery-cookie */
(function (e) { if (typeof define === "function" && define.amd) { define(["jquery"], e) } else { e(jQuery) } })(function (e) { function n(e) { return e } function r(e) { return decodeURIComponent(e.replace(t, " ")) } function i(e) { if (e.indexOf('"') === 0) { e = e.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\") } try { return s.json ? JSON.parse(e) : e } catch (t) { } } var t = /\+/g; var s = e.cookie = function (t, o, u) { if (o !== undefined) { u = e.extend({}, s.defaults, u); if (typeof u.expires === "number") { var a = u.expires, f = u.expires = new Date; f.setDate(f.getDate() + a) } o = s.json ? JSON.stringify(o) : String(o); return document.cookie = [s.raw ? t : encodeURIComponent(t), "=", s.raw ? o : encodeURIComponent(o), u.expires ? "; expires=" + u.expires.toUTCString() : "", u.path ? "; path=" + u.path : "", u.domain ? "; domain=" + u.domain : "", u.secure ? "; secure" : ""].join("") } var l = s.raw ? n : r; var c = document.cookie.split("; "); var h = t ? undefined : {}; for (var p = 0, d = c.length; p < d; p++) { var v = c[p].split("="); var m = l(v.shift()); var g = l(v.join("=")); if (t && t === m) { h = i(g); break } if (!t) { h[m] = i(g) } } return h }; s.defaults = {}; e.removeCookie = function (t, n) { if (e.cookie(t) !== undefined) { e.cookie(t, "", e.extend({}, n, { expires: -1 })); return true } return false } })

/* DateFormat */
var dateFormat = function () { var e = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, t = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, a = /[^-+\dA-Z]/g, m = function (e, t) { for (e += "", t = t || 2; e.length < t;) e = "0" + e; return e }; return function (d, y, n) { var r = dateFormat; if (1 != arguments.length || "[object String]" != Object.prototype.toString.call(d) || /\d/.test(d) || (y = d, d = void 0), d = d ? new Date(d) : new Date, isNaN(d)) throw SyntaxError("invalid date"); y = (r.masks[y] || y || r.masks["default"]) + "", "UTC:" == y.slice(0, 4) && (y = y.slice(4), n = !0); var s = n ? "getUTC" : "get", i = d[s + "Date"](), o = d[s + "Day"](), u = d[s + "Month"](), M = d[s + "FullYear"](), l = d[s + "Hours"](), T = d[s + "Minutes"](), h = d[s + "Seconds"](), c = d[s + "Milliseconds"](), g = n ? 0 : d.getTimezoneOffset(), D = { d: i, dd: m(i), ddd: r.i18n.dayNames[o], dddd: r.i18n.dayNames[o + 7], m: u + 1, mm: m(u + 1), mmm: r.i18n.monthNames[u], mmmm: r.i18n.monthNames[u + 12], yy: (M + "").slice(2), yyyy: M, h: l % 12 || 12, hh: m(l % 12 || 12), H: l, HH: m(l), M: T, MM: m(T), s: h, ss: m(h), l: m(c, 3), L: m(c > 99 ? Math.round(c / 10) : c), t: 12 > l ? "a" : "p", tt: 12 > l ? "am" : "pm", T: 12 > l ? "A" : "P", TT: 12 > l ? "AM" : "PM", Z: n ? "UTC" : ((d + "").match(t) || [""]).pop().replace(a, ""), o: (g > 0 ? "-" : "+") + m(100 * Math.floor(Math.abs(g) / 60) + Math.abs(g) % 60, 4), S: ["th", "st", "nd", "rd"][i % 10 > 3 ? 0 : (i % 100 - i % 10 != 10) * i % 10] }; return y.replace(e, function (e) { return e in D ? D[e] : e.slice(1, e.length - 1) }) } }(); dateFormat.masks = { "default": "ddd mmm dd yyyy HH:MM:ss", shortDate: "m/d/yy", mediumDate: "mmm d, yyyy", longDate: "mmmm d, yyyy", fullDate: "dddd, mmmm d, yyyy", shortTime: "h:MM TT", mediumTime: "h:MM:ss TT", longTime: "h:MM:ss TT Z", isoDate: "yyyy-mm-dd", isoTime: "HH:MM:ss", isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" }, dateFormat.i18n = { dayNames: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] }, Date.prototype.format = function (e, t) { return dateFormat(this, e, t) }

/* w.array.list */
Array.prototype.add = function (e) { var t = this.type; if (typeof t === "undefined") this.type = typeof e; else if (this.type !== typeof e && e !== null) throw 'Item is of type "' + typeof e + '," but this array is composed of "' + this.type + '" type objects.'; this.push(e) }; Array.prototype.addRange = function (e) { var t = this; if (e !== undefined) { e.foreach(function (e) { t.add(e) }) } return t.clone() }; Array.prototype.any = function () { return this.length > 0 }; Array.prototype.clone = function () { var e = []; this.foreach(function (t) { e.add(t) }); return e }; Array.prototype.distinct = function (e) { var t = []; var n = this; for (var r = 0; r < n.length; r++) { if (typeof e === "function" && e(n[r]) || n[r] === e) { if (typeof e === "function" && e(n[r])) { if (t.findIndex(function (t) { return t == e(n[r]) }) == -1) t.add(e(n[r])) } } else if (typeof e === "undefined") { if (t.findIndex(function (e) { return e == n[r] }) == -1) t.add(n[r]) } } return t }; Array.prototype.find = function (e) { var t; var n = this; for (var r = 0; r < n.length; r++) { if (typeof e === "function" && e(n[r]) || n[r] === e) { t = n[r]; break } } return t }; Array.prototype.findAll = function (e) { var t = []; var n = this; for (var r = 0; r < n.length; r++) { if (typeof e === "function" && e(n[r]) || n[r] === e) t.add(n[r]) } return t }; Array.prototype.findIndex = function (e) { var t = -1; var n = this; for (var r = 0; r < n.length; r++) { if (typeof e === "function" && e(n[r]) || n[r] === e) { t = r; break } } return t }; Array.prototype.first = function () { var e; if (this.length > 0) e = this[0]; return e }; Array.prototype.foreach = function (e) { for (var t = 0; t < this.length; t++) { if (typeof e === "function") { var n = e(this[t], t); if (n) break } } }; Array.prototype.last = function () { var e; if (this.length > 0) e = this[this.length - 1]; return e }; Array.prototype.longCount = function (e) { var t = 0; var n = this; for (var r = 0; r < n.length; r++) { if (typeof e === "function" && e(n[r]) || n[r] === e) t++ } return t }; Array.prototype.orderBy = function (e) { var t = Array.Utility.getCompare(this, arguments); this.sort(t) }; Array.prototype.removeAll = function (e) { var t = []; var n = this; for (var r = 0; r < n.length; r++) { if (typeof e === "function" && e(n[r]) || n[r] === e) { } else t.add(n[r]) } return t }; Array.prototype.removeAt = function (e) { var t = []; var n = this; for (var r = 0; r < n.length; r++) if (r !== e) t.push(n[r]); return t }; Array.prototype.take = function (e, t) { var n = []; var r = this; t = t !== undefined ? t : 0; for (var i = t; i < e + t; i++) { if (i < r.length) n.add(r[i]); else break } return n }; Array.prototype.type = undefined; Array.Utility = { getCompare: function () { var e = [], t = [], n = []; var r; var i = arguments.length > 1 ? arguments[1] : []; var s = arguments[0]; for (var o = 0; o < i.length; o++) { var u = i[o].del; var a = i[o].sort !== undefined ? i[o].sort : Array.SortType.ASC; var f; if (typeof u === "function") { f = function (e, t, n, r) { var i = Array.Utility.getSortValue(n(e)); var s = Array.Utility.getSortValue(n(t)); if (i < s) return r === Array.SortType.ASC ? -1 : 1; if (i > s) return r === Array.SortType.ASC ? 1 : -1; return 0 } } else if (typeof u === "string") { f = function (e, t, n, r) { var i = Array.Utility.getSortValue(e[n]); var s = Array.Utility.getSortValue(t[n]); if (i < s) return r === Array.SortType.ASC ? -1 : 1; if (i > s) return r === Array.SortType.ASC ? 1 : -1; return 0 } } if (f !== undefined) { e.push(f); t.push(u); n.push(a) } } if (e.length > 0) { r = function (r, i) { var s = 0; for (var o = 0; o < e.length; o++) { s = e[o](r, i, t[o], n[o]); if (s !== 0) break } return s } } else { var a; if (i.length === 1) { if (typeof i[0] === "number") a = i[0]; else a = Array.SortType.ASC } else a = Array.SortType.ASC; if (a === Array.SortType.DESC) { r = function (e, t) { if (e > t) return -1; if (e < t) return 1; return 0 } } else { r = function (e, t) { if (e < t) return -1; if (e > t) return 1; return 0 } } } return r }, getSortValue: function (e) { if (typeof e === "number") return parseFloat(e); else if (typeof e === "string") return e.toString(); return e } }; Array.SortType = { ASC: 1, DESC: 2 }

/* Responsive */
var Responsive = (function (d) { var g = "LARGEST", b = { NARROW: { maxWidth: 600, applySequencing: true }, MEDIUM: { maxWidth: 800 } }, e = [], c = {}, f = "/content/styles/", i, a, h = function (n) { b = n; e = d.map(b, function (p, o) { return p.maxWidth }).sort(function (o, p) { return (o == p) ? 0 : (o > p) ? -1 : 1 }); c = {}; d.each(b, function (o, p) { c[o] = o }); c[g] = g; if (i) { Responsive.LayoutType = c } }, j = function (p) { if (i) { alert("Responsive options have already been initialized; cannot call Responsive.init() more than once per page."); return } i = p; var n = i.layouts || {}, q = i.sequences || {}, o; if (!d.isPlainObject(n)) { alert('Responsive option named "layouts" must be a plain object.\n\nExample: layouts: { NARROW: { maxWidth: 650 }, MEDIUM: { maxWidth: 900 } }'); return } if (n[g]) { alert('Responsive option named "layouts" cannot contain a layout named "' + g + '"; it is a protected name.'); return } if (!d.isPlainObject(q)) { alert('Responsive option named "sequences" must be a plain object.\n\nKeys should be parent selectors, values should be arrays of child selectors.\n\nExample: sequences: { "#parent-container": [ "#container-2", "#container-1" ] }'); return } if (i.cssFolder) { f = i.cssFolder } if (!d.isEmptyObject(n)) { h(n); if (a) { m() } } for (o in q) { k.store(q[o], o) } if (i.onLayoutChange) { l.addCallback(i.onLayoutChange) } }, m = function () { var n = l.calculate(); if (a != n) { k.update(n); l.update(n); a = n } }, l = (function () { var q = false, s = {}, n = {}, p = d.Callbacks("memory unique"), o = function (u) { return f + (b[u].stylesheet || u.toLowerCase() + ".css") + (q ? "?_=" + (new Date()).valueOf() : "") }, t = function (v) { if (typeof s[v] != "undefined") { return } r(); if (typeof b[v].stylesheet != "undefined" && !b[v].stylesheet) { return } var u = n[v] || o(v); s[v] = d('<link rel="stylesheet" type="text/css" href="' + u + '" media="screen">').appendTo("head"); n[v] = u }, r = function () { for (var u in s) { s[u].remove(); delete s[u] } }; return { calculate: function () { var v = d(window).width(), x, w = g, u; d.each(e, function (z, y) { if (v <= y) { u = y } }); for (x in b) { if (u == b[x].maxWidth) { w = x } } return w }, addCallback: function (u) { if (typeof (u) == "function") { p.add(u) } else { alert("A function must be passed in that will be fired when the responsive layout changes.") } }, update: function (u) { if (u != g) { t(u) } else { r() } d("#wrapper").css({ position: "static", top: "auto", width: "auto" }); p.fire(u) } } })(), k = (function () { var o = {}, t = d.Callbacks("memory"), q, s = "#content", p = function (v, u) { return function (x) { var w = n(v); if (w.size() == 1) { r(w, u, x) } else { if (w.size() > 1) { alert("Found more than 1 parent container; parent selector must match a single unique DOM element.") } } } }, n = function (v) { var u = d(v); if (u.size() == 0 && /^#/.test(v) && v == s) { u = d(parentSelector = "." + v.substring(1, v.length - 2)) } return u }, r = function (u, w, x) { var v = d.map(w, function (z, y) { return d(z, u) }); d(v.reverse()).each(function () { var y = this.attr("id") + "__responsive_sequence_placeholder"; if (x && this.next().attr("id") != y) { this.after("<div id=" + y + "></div>") } if (x) { u.prepend(this) } else { d("#" + y).before(this) } }) }; return { store: function (u, v) { var w = v || s; if (!u || !d.isArray(u)) { alert("Each responsive sequence must be an array of unique selector strings."); return } if (o[w]) { alert("Responsive sequence has already been set!\n\nParent: " + w + "\nConfigured sequence: " + o[w]); return } o[w] = u; t.add(p(w, u)) }, update: function (v) { var u = (b[v] && b[v].applySequencing); if (!!q == !!u) { return } t.fire(u); q = u } } })(); h(b); d(function () { m(); d(window).resize(m) }); return { LayoutType: c, getLayout: function () { return l.calculate() }, init: function (n) { if (n && d.isPlainObject(n)) { j(n) } else { alert("Error: A plain object containing options must be passed in for initializing the responsive layout.") } }, onLayoutChange: function (n) { l.addCallback(n) }, addSequence: function (n, o) { k.store(n, o) }, author: "Spinutech", date: "January 2014", version: "1.2" } })(jQuery);

spinutech.responsive = Responsive;

spinutech.call = function (method, args) {
    if (typeof method === 'function') {
        var _args = [];
        if (arguments.length > 1)
            for (var i = 1; i < arguments.length; i++)
                _args.push(arguments[i]);
        return method.apply(this, _args || []);
    }
}


/*  connection
*   Spinutech
*
*   v 1.0.1.0   04-07-2014 - Updated connection check to not use image.
*   v 1.0.0.0   12-30-2013 - Initial version in the spinutech namespace.
*/
spinutech.connection = (function ($) {

    var _isIE = function () {
        var nav = navigator.userAgent.toLowerCase();
        return /msie/.test(nav);
    }

    var vars = {
        checking: false,
        connected: true,
        evtPrefix: 'w.connection.',
        img: undefined,
        imgSrc: '/content/images/connection.png',
        isIE: _isIE(),
        time: 5 * 60 * 1000 // check every 5 minutes
    };

    var fn = {
        init: function () {
            // flip it off and on to trigger event
            fn.triggerEvent(false);
            fn.triggerEvent(true);

            fn.checkConnection();

            setInterval(function () {
                fn.checkConnection();
            }, vars.time);
        },

        checkConnection: function () {
            if (!vars.checking) {
                vars.checking = true;

                $.ajax({
                    url: '/ping',
                    type: 'Head',
                    success: function (obj) {
                        fn.triggerEvent(true);
                    },
                    error: function (status) {
                        fn.triggerEvent(false);
                    },
                    complete: function () {
                        vars.checking = false;
                    }
                });
            }
        },

        removeImg: function (img) {
            if (vars.isIE) document.body.removeChild(img);
            else img.remove();
        },

        triggerEvent: function (connected) {
            var e = null;
            var eventName = connected ? spinutech.connection.events.ONLINE : spinutech.connection.events.OFFLINE;

            if (vars.connected !== connected) {
                $(document).trigger(eventName);
                vars.connected = connected;
            }

            vars.checking = false;
        },

        isOnline: function () {
            return vars.connected;
        }
    };

    return {
        init: function () {
            fn.init();
        },

        online: function () {
            return fn.isOnline();
        },

        events: {
            ONLINE: vars.evtPrefix + 'online',
            OFFLINE: vars.evtPrefix + 'offline'
        }
    }

})(jQuery);

window.onload = function () {
    spinutech.connection.init();
}

/*  dataLoader
*   Spinutech
*
*   v 3.0.0.0   12-30-2013 - Major update: part of global spinutech (spinutech) namespace.
*   v 2.0.0.1   12-18-2013 - Bug fix when forcing to reload object. Caused stack overflow.
*   v 2.0.0.0   12-13-2013 - Major update. Incompatible with earlier version.
*   v 1.2.1.0   12-03-2013 - Added updateData() method.
*   v 1.1.0.0   11-06-2013
*
*   Loads an external source and, if available, stores the result in local storage.
*
*   Dependencies:
*   jquery.js 
*   jquery.storageapi.js (https://github.com/julien-maurel/jQuery-Storage-API)
*
*   var dataLoader = new DataLoader(url, options);
*
*   Param               Type                Default                Description
*   ------------------------------------------------------------------------------------------------------------------------------------
*   options.url              string              undefined              Location of resource
*   options.data             json object         {}                     Parameters to be sent to resource url
*   options.type             string              'Get'                  Type of resource method
*   options.useLocal         bool                true                   Indicates whether to use local storage
*   options.events.loaded    func                undefined              Called after resource is loaded
*   options.events.error     func                undefined              Called after error during ajax load
*   options.events.loading   func                undefined              Called when loading of resource starts
*   options.events.complete  func                undefined              Called when ajax completed        
*
*
*   Methods
*   ------------------------------------------------------------------------------------------------------------------------------------
*   dataLoader.bind(event, func)        Bind this loader instance to an event.
*   dataLoader.load(maxAge)             Loads the resource. Param maxAge is uint, indicates number of seconds the resource can be old.
*                                       If age is older than maxAge, resource will be reloaded. Otherwise it will be read from storage.
*   dataLoader.clearItem()              Clears item saved to local storage.
*   dataLoader.age                 Gets age of item saved in local storage in seconds.
*   dataLoader.getItem()                Gets items saved to local storage.
*   dataLoader.updateData(param, value) Updates data item sent with ajax call.
*
*/
spinutech.dataLoader = (function ($) {

    var $document = $(document),
        connection = spinutech.connection,
        storage = $.localStorage;

    var cls = function (options) {
        var defaults = {
            data: {},
            events: {
                complete: function () { },
                error: function (errors) { if (typeof console !== 'undefined') console.error(errors); },
                loaded: function (obj) { },
                loading: function () { }
            },
            key: undefined,
            type: 'Get',
            url: undefined,
            useLocal: true
        };

        options = $.extend(defaults, options);

        var _loading = false;
        var _online;
        var _data = options.data;
        var _type = options.type;
        var _useLocal = options.useLocal;
        var _key = options.key !== undefined ? options.key : options.url;
        var _url = options.url;
        var _this = this;

        var $this = $(this);

        var isOnline = function () {
            _online = connection.online();
            return _online;
        }

        var getAgeFromLocalStorage = function (key) {
            var age;

            if (storage.isSet(key)) {
                var obj = storage.get(key);
                storeItem = spinutech.dataLoader.StorageObject.parse(obj);
                age = storeItem.age;
            }

            return age;
        }

        var getFromLocalStorage = function (key) {
            var value;

            if (storage.isSet(key)) {
                var obj = storage.get(key);
                storeItem = spinutech.dataLoader.StorageObject.parse(obj);
                value = storeItem;
            }

            return value;
        }

        var getRawFromLocalStorage = function (key) {
            var obj;

            if (storage.isSet(key)) {
                obj = storage.get(key);
            }

            return obj;
        }

        var saveToLocalStorage = function (args) {
            var _defaults = {
                key: undefined,
                maxAge: undefined,
                overwrite: true,
                updated: undefined,
                value: {}
            };

            args = $.extend(_defaults, args);
            args.key = args.key === undefined ? options.url : args.key;

            var storeItem = new spinutech.dataLoader.StorageObject({
                maxAge: args.maxAge,
                updated: args.updated,
                value: args.value
            });

            var storeObj = storeItem.json;

            try {
                if (args.overwrite) {
                    storage.remove(args.key);
                    storage.set(args.key, storeObj);
                }
                else {
                    if (storage.isEmpty(args.key))
                        storage.set(args.key, storeObj);
                }
            }
            catch (err) {
                // if error occurs trying to save the object to local,
                // revert to not use local storage. QuotaExceededError: DOM Exception 22.
                _useLocal = false;
            }
        }

        var call = function (method, args) {
            if (typeof method === 'function')
                method(args);
        }

        //////////////////////////////////
        // Public methods
        //////////////////////////////////
        this.bind = function (evt, f) {
            $this.bind(evt, f);
        }

        this.load = function (maxAge) {
            if (!_loading) {
                _loading = true;
                call(options.events.loading);

                var lastUpdated = spinutech.localStorage.getUpdated(_key);
                var obj = getFromLocalStorage(_key);
                var age = getAgeFromLocalStorage(_key);
                var now = spinutech.dataLoader.Now;
                var forceReload = false;
                var online = isOnline();

                if (maxAge !== undefined)
                    forceReload = true;
                if (obj === undefined && maxAge !== undefined)
                    forceReload = true;

                if ((!online || forceReload) && _useLocal) {
                    if (obj === undefined) {
                        if (isOnline()) {
                            // if object in local storage is not available and
                            // navigator is online, try to re-load object.
                            _loading = false;
                            _this.load();
                        }
                        else
                            call(options.events.error, ['Offline; Using local storage; Object is undefined.']);
                    }
                    else {
                        if (age !== undefined && obj.maxAge !== undefined && age >= obj.maxAge) {
                            _loading = false;
                            _this.load();
                        }
                        else if (obj.updated !== undefined && lastUpdated !== undefined && lastUpdated >= obj.updated) {
                            _loading = false;
                            _this.load();
                        }
                        else {
                            call(options.events.loaded, obj.value);
                        }
                    }

                    _loading = false;
                    call(options.events.complete);
                }
                else {
                    $.ajax({
                        cache: false,
                        url: _url,
                        data: _data,
                        type: _type,
                        success: function (obj) {
                            var errors = obj.Errors;
                            var model = obj.Model;
                            var updated = obj.Updated;
                            var valid = obj.Valid;

                            if (valid) {
                                if (_useLocal) {
                                    var args = {
                                        key: _key,
                                        maxAge: maxAge,
                                        overwrite: true,
                                        updated: updated,
                                        value: obj
                                    };

                                    saveToLocalStorage(args);
                                }

                                call(options.events.loaded, obj);
                            }
                            else {
                                call(options.events.error, errors);
                            }
                        },
                        error: function (status) {
                            if (_useLocal) {
                                var obj = getFromLocalStorage(_key);
                                if (obj === undefined)
                                    call(options.events.error, ['Using local storage, but object is undefined.']);
                                else
                                    call(options.events.loaded, obj.value);
                            }
                            call(options.events.error, ['Server error.']);
                        },
                        complete: function () {
                            _loading = false;
                            call(options.events.complete);
                        }
                    });
                }
            }
        }

        this.clearItem = function () {
            storage.remove(_key);
        }

        this.getItem = function () {
            var obj = getFromLocalStorage(_key);
            return obj;
        }

        this.getAge = function () {
            var rawAge = getAgeFromLocalStorage(_key);
            var now = spinutech.dataLoader.Now;
            var age = now - rawAge;
            return age;
        }

        this.updateData = function (param, value) {
            var d = _data !== undefined ? _data : {};
            d[param] = value;
            _data = d;
        }
    }

    ///////////////////////////////
    // internal private object
    ///////////////////////////////
    var _StorageObject = (function () {
        var so = function (options) {
            var defaults = {
                age: undefined,
                maxAge: undefined,
                updated: undefined,
                value: {}
            };

            options = $.extend(defaults, options);

            var _age = options.age,
                _maxAge = options.maxAge,
                _updated = options.updated,
                _value = options.value;


            // if age was not passed into constructor,
            // set age to be current seconds since epoch
            _age = _age ? _age : spinutech.dataLoader.Now;

            this.age = _age;
            this.maxAge = _maxAge;
            this.updated = _updated;
            this.value = _value;

            this.json = {
                age: _age,
                maxAge: _maxAge,
                updated: _updated,
                value: _value
            };
        }

        so.parse = function (obj) {
            var lived = spinutech.dataLoader.Now - obj.age;

            var args = {
                age: lived,
                maxAge: obj.maxAge,
                updated: obj.updated,
                value: obj.value
            }
            return new spinutech.dataLoader.StorageObject(args);
        }

        return so;
    });

    cls.StorageObject = _StorageObject();

    cls.Now = parseInt(new Date().getTime() / 1000);

    return cls;

})(jQuery);

/*  events
*
*   v 1.0.0.0   12-30-2013  Initial version.
*/
spinutech.events = (function ($) {
    return {
        tap: spinutech.utility.isTouchDevice() ? 'tap' : 'click'
    }
})(jQuery);

/*  w.file-cache.js
*   Author: Spinutech
*
*   Description:
*   Loads a local server-available file into cache and stores it in local storage as a data url.
*
*   v 1.0.1.0   12-30-2013  Updated fn.isSupported(); Added documentation section.
*   v 1.0.0.0   12-27-2013  Initial version.
*   
*   Requires HTML5 compatiblity, as well as JS FileReader, Blob, and LocalStorage. jQuery 1.8+
*
*   Methods
*
*   Name            Arguments
*   --------------------------------------------------------------------------------------------------------------------------------------------------------
*   init            options {
*                       keyPrefix: ''                                   Prefix for local storage key
*                   }
*   cachedFile      key (string)                                        Gets cached file by local storage key. Returns data url.
*   inCache         key (string)                                        Checks if file by local storage key is cached in local storage. Returns bool.
*   isSupported                                                         Checks if this plugin is supported by browser. Returns bool.
*   loader                                                              Returns a new file loader object. Used internally.
*   loadFile        options {
*                       key: '',                                        Local storage key for file to load
*                       maxAge: undefined,                              Maximum age of file in local storage. Will try to reload file on page load if age >= maxAge
*                       loaderOptions: {
*                           contentType: 'application/octet-stream',    Content type of file to be loaded.
*                           url: '',                                    Location of file (should be on same server as location of your website)
*                           events: {
*                               complete: function () { },              Called when ajax request is completed.
*                               error: function (error) { },            Called when an error occurred, either via ajax or when saving to local storage.
*                               loaded: function (result) { },          Called when file has been successfully loaded AND saved into local storage. Result = data url.
*                               loading: function () { },               Called when first trying to load the file.
*                               progress: function (e, perc) { }        Called everytime ajax request makes a loading progress. e = progressEvent, perc = percentage loaded as float.
*                           }
*                       }
*                   }
*   now                                                                 Returns current date in seconds. Returns int.
*   remove          key (string)                                        Removes file from local storage by key.
*   storageObject                                                       Returns a local storage object. Used internally.
*
*/
spinutech.fileCache = (function ($) {

    var vars = {
        keyPrefix: '',
        options: {},
        storage: $.localStorage
    };

    var fn = {
        /***************************
        * Initializers
        ***************************/
        init: function (options) {
            var defaults = {
                keyPrefix: ''
            };

            options = $.extend(defaults, options);
            vars.options = options;
            vars.keyPrefix = options.keyPrefix;
        },

        /***************************
        * Functional
        ***************************/
        call: function (method, args) {
            if (typeof method === 'function') {
                var _args = [];
                if (arguments.length > 0)
                    for (var i = 1; i < arguments.length; i++)
                        _args.push(arguments[i]);
                method.apply(this, _args || []);
            }
        },

        loadFile: function (options) {
            var defaults = {
                key: '',
                maxAge: undefined,
                loaderOptions: {}
            };

            options = $.extend(defaults, options);

            var fileObject = fn.localStorage.retrieve(options.key);

            if (fileObject === undefined) {
                var loader = new spinutech.fileCache.loader(options.loaderOptions);
                loader.load({
                    onLoaded: function (blob) {
                        fn.localStorage.save({
                            key: options.key,
                            maxAge: options.maxAge,
                            overwrite: true,
                            value: blob,
                            events: {
                                error: options.loaderOptions.events.error,
                                saved: options.loaderOptions.events.loaded
                            }
                        });
                    }
                });
            }
            else {
                if (fileObject.maxAge !== undefined && fileObject.age >= fileObject.maxAge) {
                    fn.localStorage.remove(options.key);
                    fn.loadFile(options);
                }
                else
                    fn.call(options.loaderOptions.events.loaded, fileObject.value);
            }
        },

        localStorage: {
            isSupported: function () {
                if (typeof window.FileReader === 'undefined') return false;
                if (typeof window.Blob === 'undefined') return false;
                if (typeof window.localStorage === 'undefined') return false;
                return true;
            },

            remove: function (key) {
                key = vars.keyPrefix + key;
                if (vars.storage.isSet(key))
                    vars.storage.remove(key);
            },

            retrieve: function (key) {
                var value;
                key = vars.keyPrefix + key;

                if (vars.storage.isSet(key)) {
                    var obj = vars.storage.get(key);
                    storeItem = spinutech.fileCache.storageObject.parse(obj);
                    value = storeItem;
                }

                return value;
            },

            save: function (args) {
                var _defaults = {
                    key: '',
                    maxAge: undefined,
                    overwrite: true,
                    value: {},
                    events: {
                        error: function (error) { },
                        saved: function (fileObject) { }
                    }
                };

                args = $.extend(_defaults, args);
                args.key = vars.keyPrefix + args.key;

                var storeItem = new spinutech.fileCache.storageObject({
                    maxAge: args.maxAge,
                    value: args.value
                });

                var storeObj = storeItem.json;

                try {
                    if (args.overwrite) {
                        vars.storage.remove(args.key);
                        vars.storage.set(args.key, storeObj);
                    }
                    else {
                        if (storage.isEmpty(args.key))
                            vars.storage.set(args.key, storeObj);
                    }
                    fn.call(args.events.saved, args.value);
                }
                catch (err) {
                    fn.call(args.events.error, err);
                }
            }
        }
    }

    /***************************
    * Inner classes
    ***************************/
    var _loader = (function () {
        var cls = function (options) {
            var loading = false;
            var defaults = {
                contentType: 'application/octet-stream',
                url: '',
                events: {
                    complete: function () { },
                    error: function (error) { },
                    loaded: function (dataResult) { },
                    loading: function () { },
                    progress: function (progressEvent, percentageLoaded) { }
                }
            };

            options = $.extend(defaults, options);

            this.load = function (loadOptions) {
                if (!loading) {
                    loading = true;
                    fn.call(options.events.loading);

                    var xhr = new XMLHttpRequest(),
                        blob,
                        fileReader = new FileReader();

                    xhr.open('GET', options.url, true);
                    xhr.responseType = 'arraybuffer';

                    xhr.addEventListener('load', function () {
                        if (xhr.status === 200) {
                            blob = new Blob([xhr.response], { type: options.contentType });

                            fileReader.onload = function (e) {
                                var result = e.target.result;
                                fn.call(options.events.complete);
                                fn.call(loadOptions.onLoaded, result);
                                loading = false;
                            };

                            fileReader.readAsDataURL(blob);
                        }
                        else {
                            fn.call(options.events.error, xhr);
                            fn.call(options.events.complete);
                            loading = false;
                        }
                    }, false);

                    xhr.addEventListener('progress', function (e) {
                        var perc = parseFloat((e.loaded / e.total * 100).toFixed(4));
                        fn.call(options.events.progress, e, perc);
                    }, false);

                    xhr.send();
                }
            }

            this.loading = function () {
                return loading;
            }
        }

        return cls;
    });

    var _storageObject = (function () {
        var so = function (options) {
            var defaults = {
                age: undefined,
                maxAge: undefined,
                value: {}
            };

            options = $.extend(defaults, options);

            var _age = options.age,
                _maxAge = options.maxAge,
                _value = options.value;


            // if age was not passed into constructor,
            // set age to be current seconds since epoch
            _age = _age ? _age : spinutech.fileCache.now;

            this.age = _age;
            this.maxAge = _maxAge;
            this.value = _value;

            this.json = {
                age: _age,
                maxAge: _maxAge,
                value: _value
            };
        }

        so.parse = function (obj) {
            var lived = spinutech.fileCache.now - obj.age;

            var args = {
                age: lived,
                maxAge: obj.maxAge,
                value: obj.value
            }

            return new spinutech.fileCache.storageObject(args);
        }

        return so;
    });

    /***************************
    * Public methods
    ***************************/
    return {
        init: function (options) {
            fn.init(options);
        },

        cachedFile: function (key) {
            if (spinutech.fileCache.inCache(key))
                return fn.localStorage.retrieve(key).value;
            else
                return undefined;
        },

        inCache: function (key) {
            if (fn.localStorage.isSupported()) {
                var cachedFileObject = fn.localStorage.retrieve(key);
                if (cachedFileObject !== undefined) {
                    var maxAge = cachedFileObject.maxAge;
                    var age = cachedFileObject.age;
                    if (age >= maxAge)
                        return false;
                    else
                        return true;
                }
                else
                    return false;
            }
            else
                return false;
        },

        isSupported: function () {
            return fn.localStorage.isSupported();
        },

        loader: new _loader(),

        loadFile: function (options) {
            fn.loadFile(options);
        },

        now: parseInt(new Date().getTime() / 1000),

        remove: function (key) {
            fn.localStorage.remove(key);
        },

        storageObject: new _storageObject()
    }

})(jQuery);

/*  hashEvent
*   Spinutech
*
*   v 1.1.0.0   01-08-2014  Added hashEvent.hashObject() inner class.
*   v 1.0.0.0   12-30-2013  Initial version in the spinutech namespace.
*/
spinutech.hashEvent = (function ($) {

    var $document = $(document);
    var $window = $(window);

    var data;
    var hash;
    var opts;

    var init = function (o) {
        opts = o;

        $window.hashchange(onHashChange);
        $document.hashchange(onHashChange);

        hash = location.hash;
        var hasHash = /^#/.test(hash);
        if (hasHash) {
            data = hashToKeyValues(hash);
            $document.trigger(spinutech.hashEvent.events.NEW, data);
        }
        else
            $document.trigger(spinutech.hashEvent.events.NONE);
    }

    var onHashChange = function (e) {
        hash = location.hash;
        var hasHash = /^#/.test(hash);
        if (hasHash) {
            data = hashToKeyValues(hash);
            $document.trigger(spinutech.hashEvent.events.NEW, data);
        }
        else
            $document.trigger(spinutech.hashEvent.events.NONE);
    }

    var hashToKeyValues = function (h) {
        var data = [];

        if (h != undefined) {
            h = h.replace(/^#/, '');
            try {
                var kv = h.split('&');
                if (kv.length > 0) {
                    for (var i = 0; i < kv.length; i++) {
                        var p = kv[i].split('=');

                        if ((p[0] != '' && p[0] != undefined) && (p[1] != undefined))
                            data.push([p[0], p[1]]);
                    }
                }
            }
            catch (err) { }
        }
        else
            throw "spinutech.hashEvent @hashToKeyValues: hash is undefined";

        return data;
    }

    var _evtPrefix = 'w.hash-event.';

    var _hashObject = (function () {
        var ho = function (options) {
            var vars = {
                nvp: options.nvp,
                obj: new spinutech.list()
            }

            var fn = {
                init: function () {
                    for (var i = 0; i < vars.nvp.length; i++)
                        vars.obj.add({ name: vars.nvp[i][0], value: vars.nvp[i][1] });
                }
            }

            this.toString = function () {
                var str = [];
                vars.obj.foreach(function (o) {
                    str.push(o.name + '=' + o.value);
                });
                return str.join('&');
            }

            this.param = function (args) {
                var _args = arguments;
                if (_args.length === 2) {
                    var o = vars.obj.find(function (o) { return o.name === _args[0]; });
                    _args[1] = _args[1] === undefined ? '' : _args[1];
                    if (o !== undefined) o.value = _args[1];
                    else vars.obj.add({ name: _args[0], value: _args[1] });
                }
                else if (_args.length === 1) {
                    var o = vars.obj.find(function (o) { return o.name === _args[0]; });
                    return o !== undefined ? o.value : o;
                }
            }

            this.hashObject = function () {
                return vars.obj;
            }

            fn.init();
        }

        return ho;
    });

    return {
        init: function (options) {
            init(options);
        },

        addToHash: function (obj) {
            hash += (spinutech.hashEvent.hasHash() ? '&' : '#') + (obj.key + '=' + obj.value);
            location.hash = hash;
        },

        events: {
            NEW: _evtPrefix + 'new',
            NONE: _evtPrefix + 'none'
        },

        getData: function () {
            return data;
        },

        getHashValue: function () {
            value = '';
            if (spinutech.hashEvent.hasHash())
                value = hash.substring(1);
            return value;
        },

        getValueByParam: function (param) {
            var val = undefined;

            if (data !== undefined) {
                for (var i = 0; i < data.length; i++)
                    if (data[i][0] == param)
                        val = data[i][1];
            }

            val = typeof val === 'string' ? decodeURIComponent(val) : val;
            return val;
        },

        hasHash: function () {
            if (hash !== undefined)
                return /^#/.test(hash);
            else
                return false;
        },

        hashObject: new _hashObject(),

        nvpToHash: function (nvp) {
            if (nvp !== undefined) {
                var delim = '';
                var h = '#';

                for (var i = 0; i < nvp.length; i++) {
                    var val = nvp[i][1];
                    val = typeof val === 'string' ? val.replace(/&/g, '%26') : val;
                    h += delim + nvp[i][0] + '=' + val;
                    delim = '&';
                }

                location.hash = h;
            }
        },

        nvpToHashString: function (nvp) {
            if (nvp !== undefined) {
                var delim = '';
                var h = '#';

                for (var i = 0; i < nvp.length; i++) {
                    var val = nvp[i][1];
                    val = typeof val === 'string' ? val.replace(/&/g, '%26') : val;
                    h += delim + nvp[i][0] + '=' + val;
                    delim = '&';
                }

                return h;
            }
        },

        getHash: function () {
            return hash;
        },

        setHash: function (h) {
            hash = h;
            location.hash = h;
        },

        updateHashValue: function (param, value) {
            if (spinutech.hashEvent.hasHash()) {
                var nvp = spinutech.hashEvent.getData();
                if (nvp !== undefined) {
                    var hasParam = false;
                    var index = -1;

                    for (var i = 0; i < nvp.length; i++) {
                        if (nvp[i][0] == param) {
                            index = i;
                            hasParam = true;
                        }
                    }

                    if (hasParam)
                        nvp[index][1] = value;
                    else
                        nvp.push([param, value]);

                    spinutech.hashEvent.nvpToHash(nvp);
                }
            }
        },

        updateHashValues: function (nvp) {
            if (spinutech.hashEvent.hasHash() && nvp !== undefined) {
                var _nvp = spinutech.hashEvent.getData();
                if (_nvp != undefined) {
                    for (var i = 0; i < nvp.length; i++) {
                        for (var j = 0; j < _nvp.length; j++) {
                            if (_nvp[j][0] == nvp[i][0])
                                _nvp[j][1] = nvp[i][1];
                        }
                    }

                    spinutech.hashEvent.nvpToHash(_nvp);
                }
            }
        }
    }

})(jQuery);

/*  image scaler
*   Sebastian Stefaniuk, spinutech.com
*
*   v 1.0.0.0   01-06-2013  Initial version
*/
spinutech.imageScaler = (function ($) {

    var cls = function (options) {
        var _parentHeight = options.parentHeight;
        var _parentWidth = options.parentWidth;
        var _imageHeight = options.imageHeight;
        var _imageWidth = options.imageWidth;
        var _steps = options.steps ? options.steps : 4;
        var _scaleX;
        var _scaleY;
        var _heights;
        var _widths;
        var _outOfView;

        var init = function () {
            _heights = [];
            _widths = [];
            _outOfView = true;

            _scaleX = _imageWidth / _parentWidth;
            _scaleY = _imageHeight / _parentHeight;

            if (_scaleX >= _scaleY) {
                scaleByX();
            }
            else {
                scaleByY();
            }
        }

        var scaleByY = function () {
            var minH = parseInt(_imageHeight / _scaleY);
            var minW = parseInt(_imageWidth / _scaleY);

            if (minH > _imageHeight) {
                minH = _imageHeight;
                minW = _imageWidth;
                _outOfView = false;
            }

            calculateSteps(minW, minH);
        }

        var scaleByX = function () {
            var minW = parseInt(_imageWidth / _scaleX);
            var minH = parseInt(_imageHeight / _scaleX);

            if (minW > _imageWidth) {
                minW = _imageWidth;
                minH = _imageHeight;
                _outOfView = false;
            }

            calculateSteps(minW, minH);
        }

        var calculateSteps = function (minW, minH) {
            var imgDiffWidth = _imageWidth - minW;
            var imgDiffHeight = _imageHeight - minH;
            var stepWidth = parseInt(imgDiffWidth / _steps);
            var stepHeight = parseInt(imgDiffHeight / _steps);

            for (var i = 0; i < _steps; i++) {
                if (i === 0) {
                    _widths.push(minW);
                    _heights.push(minH);
                }
                else if (i === _steps.length - 1) {
                    _widths.push(_imageWidth);
                    _heights.push(_imageHeight);
                }
                else {
                    _widths.push(minW + (stepWidth * i));
                    _heights.push(minH + (stepHeight * i));
                }
            }
        }

        this.getHeight = function () {
            return _heights[0];
        }

        this.getHeights = function () {
            return _heights;
        }

        this.getWidth = function () {
            return _widths[0];
        }

        this.getWidths = function () {
            return _widths;
        }

        this.isOutOfView = function () {
            return _outOfView;
        }

        init();
    }

    return cls;

})(jQuery);

/*  list
*   Sebastian Stefaniuk, spinutech.com
*
*   v 1.3.1.0   12-16-2013  Allow foreach() method to break loop if predicate function returns true;
*   v 1.3.0.0   12-06-2013  Added distinct() method => returns a new spinutech.list object with items selected in delegate of method.
*   v 1.2.0.0   12-03-2013  Added longCount() method; Bug fix in take() method.
*   v 1.0.1.0   11-27-2013  Allow nullable type to be added to list of non-null type.
*   v 1.0.0.0   11-10-2013  Initial version
*
*/

spinutech.list = (function () {

    var cls = function (array) {
        var _array = [];
        var _this = this;
        var _type;

        var _init = function () {
            if (array !== undefined && array instanceof Array) {
                for (var i = 0; i < array.length; i++)
                    _this.add(array[i]);
            }
        }

        this.add = function (item) {
            if ((_array.length == 0 && item !== null) || (_type === undefined && item !== null))
                _type = typeof item;

            if (_type !== typeof item && item !== null)
                throw 'Item is of type ' + (typeof item) + ', but spinutech.list is composed of ' + _type + ' type objects.';
            else
                _array.push(item);
        }

        this.addRange = function (list) {
            var _list = _this;
            if (list !== undefined) {
                list.foreach(function (item) {
                    _list.add(item);
                });
            }
            return _list
        }

        this.any = function () {
            return _array.length > 0;
        }

        this.clear = function () {
            _array = [];
        }

        this.count = function () {
            return _array.length;
        }

        this.distinct = function (predicate) {
            var _list = new spinutech.list();
            for (var i = 0; i < _array.length; i++) {
                if ((typeof predicate === 'function' && predicate(_array[i])) || (_array[i] === predicate)) {
                    if (typeof predicate === 'function' && predicate(_array[i])) {
                        if (_list.findIndex(function (x) { return x == predicate(_array[i]); }) == -1)
                            _list.add(predicate(_array[i]));
                    }
                    else if (_array[i] === predicate) {
                        if (_list.findIndex(function (x) { return x == _array[i]; }) == -1)
                            _list.add(_array[i]);
                    }
                }
            }
            return _list;
        }

        this.first = function () {
            var item
            if (_array.length > 0)
                item = _array[0];
            return item;
        }

        this.foreach = function (predicate) {
            for (var i = 0; i < _array.length; i++) {
                if (typeof predicate === 'function') {
                    var doBreak = predicate(_array[i], i);
                    if (doBreak)
                        break;
                }
            }
        }

        this.itemAt = function (index) {
            return _array[index];
        }

        this.last = function () {
            var item
            if (_array.length > 0)
                item = _array[_array.length - 1];
            return item;
        }

        this.longCount = function (predicate) {
            var count = 0;
            for (var i = 0; i < _array.length; i++) {
                if ((typeof predicate === 'function' && predicate(_array[i])) || (_array[i] === predicate))
                    count++;
            }
            return count;
        }

        this.removeAll = function (predicate) {
            var _list = new spinutech.list();
            for (var i = 0; i < _array.length; i++) {
                if ((typeof predicate === 'function' && predicate(_array[i])) || (_array[i] === predicate)) { }
                else
                    _list.add(_array[i]);
            }
            return _list;
        }

        this.removeAt = function (index) {
            var newArray = [];
            for (var i = 0; i < _array.length; i++)
                if (i !== index)
                    newArray.push(_array[i]);
            _array = newArray;
        }

        this.take = function (numOfItems, skip) {
            var list = new spinutech.list();
            skip = skip !== undefined ? skip : 0;
            for (var i = skip; i < numOfItems + skip; i++) {
                if (i < _array.length) list.add(_array[i]);
                else break;
            }
            return list;
        }

        ////////////////////////////////
        // Find functions
        ////////////////////////////////
        this.find = function (predicate) {
            var item;
            for (var i = 0; i < _array.length; i++) {
                if ((typeof predicate === 'function' && predicate(_array[i])) || (_array[i] === predicate)) {
                    item = _array[i];
                    break;
                }
            }
            return item;
        }

        this.findAll = function (predicate) {
            var _list = new spinutech.list();
            for (var i = 0; i < _array.length; i++) {
                if ((typeof predicate === 'function' && predicate(_array[i])) || (_array[i] === predicate))
                    _list.add(_array[i]);
            }
            return _list;
        }

        this.findIndex = function (predicate) {
            var index = -1;
            for (var i = 0; i < _array.length; i++) {
                if ((typeof predicate === 'function' && predicate(_array[i])) || (_array[i] === predicate)) {
                    index = i;
                    break;
                }
            }
            return index;
        }

        ////////////////////////////////
        // Order functions
        ////////////////////////////////
        this.orderBy = function (args) {
            var _list = new spinutech.list(),
                _newArray = [],
                _compareFunc = getCompare(arguments);

            for (var i = 0; i < _array.length; i++)
                _newArray.push(_array[i]);

            _newArray.sort(_compareFunc);

            for (var i = 0; i < _newArray.length; i++)
                _list.add(_newArray[i]);

            return _list;
        }

        ////////////////////////////////
        // "To" functions
        ////////////////////////////////
        this.toArray = function () {
            return _array;
        }

        ////////////////////////////////
        // Private functions
        ////////////////////////////////
        var getCompare = function () {
            var compares = [],
                predicates = [],
                types = [];

            var compareFunc;
            var args = arguments.length > 0 ? arguments[0] : [];

            for (var i = 0; i < args.length; i++) {
                var predicate = args[i].pred;
                var compareType = args[i].type !== undefined ? args[i].type : spinutech.list.CompareType.ASC;
                var compare;

                if (typeof predicate === 'function') {
                    compare = function (a, b, pred, type) {
                        var x = getSortValue(pred(a));
                        var y = getSortValue(pred(b));
                        if (x < y) return type === spinutech.list.CompareType.ASC ? -1 : 1;
                        if (x > y) return type === spinutech.list.CompareType.ASC ? 1 : -1;
                        return 0;
                    };
                }
                else if (typeof predicate === 'string') {
                    compare = function (a, b, pred, type) {
                        var x = getSortValue(a[pred]);
                        var y = getSortValue(b[pred]);
                        if (x < y) return type === spinutech.list.CompareType.ASC ? -1 : 1;
                        if (x > y) return type === spinutech.list.CompareType.ASC ? 1 : -1;
                        return 0;
                    };
                }

                if (compare !== undefined) {
                    compares.push(compare);
                    predicates.push(predicate);
                    types.push(compareType);
                }
            }

            if (compares.length > 0) {
                compareFunc = function (x, y) {
                    var val = 0;
                    for (var i = 0; i < compares.length; i++) {
                        val = compares[i](x, y, predicates[i], types[i]);
                        if (val !== 0)
                            break;
                    }
                    return val;
                }
            }
            else {
                var compareType;

                if (arguments.length == 1) {
                    if (typeof arguments[0] === 'Number') compareType = arguments[0];
                    else compareType = spinutech.list.CompareType.ASC;
                }
                else
                    compareType = spinutech.list.CompareType.ASC;

                if (compareType === spinutech.list.CompareType.DESC) {
                    compareFunc = function (a, b) {
                        if (a > b) return -1;
                        if (a < b) return 1;
                        return 0;
                    };
                }
                else {
                    compareFunc = function (a, b) {
                        if (a < b) return -1;
                        if (a > b) return 1;
                        return 0;
                    };
                }
            }

            return compareFunc;
        }

        var getSortValue = function (item) {
            if (typeof item === 'number') return parseFloat(item);
            else if (typeof item === 'string') return item.toString();
            return item;
        }

        _init();
    }

    var _compareType = function () {
        return {
            ASC: 1,
            DESC: 2
        };
    }

    cls.CompareType = _compareType();

    return cls;

})();

/*  localStorage
*   Spinutech
*
*   v 1.4.0.0   01-06-2013  Added isSupported(), remove(), retrieve(), and save() methods.
*   v 1.0.0.0   12-30-2013  Initial version in the spinutech namespace.
*/
spinutech.localStorage = (function ($) {

    var _localStorageContext,
        _localStorageKeys,
        _localStoragePrefix,
        _reloadUrl,
        _storage = $.localStorage;

    var _parseContext = function (context) {
        var keysList = new spinutech.list(context.keys);
        var keys = {};
        keysList.foreach(function (k) {
            keys[k.Key] = k.KeyEnum;
        });

        _localStorageContext = context;
        _localStorageKeys = keys;
        _localStorageContext.storage = new spinutech.list(_localStorageContext.storage);
    }

    var _storageObject = (function () {
        var so = function (options) {
            var defaults = {
                age: undefined,
                maxAge: undefined,
                value: {}
            };

            options = $.extend(defaults, options);

            var _age = options.age,
                _maxAge = options.maxAge,
                _value = options.value;


            // if age was not passed into constructor,
            // set age to be current seconds since epoch
            _age = _age ? _age : spinutech.localStorage.now;

            this.age = _age;
            this.maxAge = _maxAge;
            this.value = _value;

            this.json = {
                age: _age,
                maxAge: _maxAge,
                value: _value
            };
        }

        so.parse = function (obj) {
            var lived = spinutech.localStorage.now - obj.age;

            var args = {
                age: lived,
                maxAge: obj.maxAge,
                value: obj.value
            }

            return new spinutech.localStorage.storageObject(args);
        }

        return so;
    });

    return {
        context: function (args) {
            if (arguments.length > 0) {
                var serialized = $('<div/>').html(arguments[0]).text();
                _localStorageContext = JSON.parse(serialized);
                _parseContext(_localStorageContext);
            }
            else
                return _localStorageContext;
        },

        keys: function (args) {
            if (arguments.length > 0)
                _localStorageKeys = arguments[0];
            else
                return _localStorageKeys;
        },

        getUpdated: function (key) {
            var prefix = _localStoragePrefix;
            var updated = undefined;
            var _key;

            if (_localStorageKeys !== undefined) {
                var keyValue;
                if (typeof key === 'string')
                    keyValue = _localStorageKeys[key.replace(_localStoragePrefix, '')];
                else
                    keyValue = key;

                _localStorageContext.storage.foreach(function (s) {
                    var keySubbed = s.key.replace(_localStoragePrefix, '');
                    if (_localStorageKeys[keySubbed] === keyValue) {
                        updated = s.updated;
                    }
                });
            }

            return updated;
        },

        isSupported: function () {
            if (typeof window.localStorage === 'undefined') return false;
            return true;
        },

        now: parseInt(new Date().getTime() / 1000),

        prefix: function (args) {
            if (arguments.length > 0) _localStoragePrefix = arguments[0];
            else return _localStoragePrefix;
        },

        reload: function (options) {
            var defaults = {
                onDifferent: function () { },
                onSame: function () { }
            };

            options = $.extend(defaults, options);

            var loader = new spinutech.dataLoader({
                type: 'Post',
                url: _reloadUrl,
                useLocal: false,
                events: {
                    loaded: function (obj) {
                        var isDifferent = false;
                        var context = obj.Model;
                        var keys = new spinutech.list(context.keys);
                        var contextStorage = new spinutech.list(context.storage);

                        keys.foreach(function (key) {
                            contextStorage.foreach(function (s) {
                                if ((_localStoragePrefix + key.Key) === s.key) {
                                    var storageItem = _localStorageContext.storage.find(function (x) { return x.key === s.key; });
                                    if (storageItem === undefined || storageItem.updated !== s.updated)
                                        isDifferent = true;
                                }
                            });
                        });

                        _parseContext(context);

                        if (isDifferent)
                            options.onDifferent();
                        else
                            options.onSame();
                    },
                    error: function (errors) {
                        options.onSame();
                    }
                }
            });

            loader.load();
        },

        reloadUrl: function (args) {
            if (arguments.length > 0) _reloadUrl = arguments[0];
            else return _reloadUrl;
        },

        remove: function (key) {
            key = spinutech.localStorage.prefix() + key;
            if (_storage.isSet(key))
                _storage.remove(key);
        },

        retrieve: function (key) {
            var value;
            key = spinutech.localStorage.prefix() + key;

            if (_storage.isSet(key)) {
                var obj = _storage.get(key);
                storeItem = spinutech.localStorage.storageObject.parse(obj);
                value = storeItem;
            }

            return value;
        },

        save: function (args) {
            var _defaults = {
                key: '',
                maxAge: undefined,
                overwrite: true,
                value: {},
                events: {
                    error: function (error) { },
                    saved: function (fileObject) { }
                }
            };

            args = $.extend(_defaults, args);
            args.key = spinutech.localStorage.prefix() + args.key;

            var storeItem = new spinutech.localStorage.storageObject({
                maxAge: args.maxAge,
                value: args.value
            });

            var storeObj = storeItem.json;

            try {
                if (args.overwrite) {
                    _storage.remove(args.key);
                    _storage.set(args.key, storeObj);
                }
                else {
                    if (_storage.isEmpty(args.key))
                        _storage.set(args.key, storeObj);
                }
                spinutech.call(args.events.saved, storeObj);
            }
            catch (err) {
                spinutech.call(args.events.error, err);
            }
        },

        storageObject: new _storageObject()
    }

})(jQuery);

;/* jQuery.cookie https://github.com/carhartl/jquery-cookie */


/* store client side info */
(function ($) {
    (function (e) { if (typeof define === "function" && define.amd) { define(["jquery"], e) } else { e(jQuery) } })(function (e) { function n(e) { return e } function r(e) { return decodeURIComponent(e.replace(t, " ")) } function i(e) { if (e.indexOf('"') === 0) { e = e.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\") } try { return s.json ? JSON.parse(e) : e } catch (t) { } } var t = /\+/g; var s = e.cookie = function (t, o, u) { if (o !== undefined) { u = e.extend({}, s.defaults, u); if (typeof u.expires === "number") { var a = u.expires, f = u.expires = new Date; f.setDate(f.getDate() + a) } o = s.json ? JSON.stringify(o) : String(o); return document.cookie = [s.raw ? t : encodeURIComponent(t), "=", s.raw ? o : encodeURIComponent(o), u.expires ? "; expires=" + u.expires.toUTCString() : "", u.path ? "; path=" + u.path : "", u.domain ? "; domain=" + u.domain : "", u.secure ? "; secure" : ""].join("") } var l = s.raw ? n : r; var c = document.cookie.split("; "); var h = t ? undefined : {}; for (var p = 0, d = c.length; p < d; p++) { var v = c[p].split("="); var m = l(v.shift()); var g = l(v.join("=")); if (t && t === m) { h = i(g); break } if (!t) { h[m] = i(g) } } return h }; s.defaults = {}; e.removeCookie = function (t, n) { if (e.cookie(t) !== undefined) { e.cookie(t, "", e.extend({}, n, { expires: -1 })); return true } return false } })

    $(function () {

        var cookieName = '__clientinfo__';

        var sw = screen.width;
        var sh = screen.height;

        var nVer = navigator.appVersion;
        var nAgt = navigator.userAgent;
        var browserName = navigator.appName;
        var fullVersion = '' + parseFloat(navigator.appVersion);
        var majorVersion = parseInt(navigator.appVersion, 10);
        var nameOffset, verOffset, ix;

        // In Opera, the true version is after "Opera" or after "Version"
        if ((verOffset = nAgt.indexOf("Opera")) != -1) {
            browserName = "Opera";
            fullVersion = nAgt.substring(verOffset + 6);
            if ((verOffset = nAgt.indexOf("Version")) != -1)
                fullVersion = nAgt.substring(verOffset + 8);
        }
        // In MSIE, the true version is after "MSIE" in userAgent
        else if ((verOffset = nAgt.indexOf("MSIE")) != -1) {
            browserName = "Microsoft Internet Explorer";
            fullVersion = nAgt.substring(verOffset + 5);
        }
        // In Chrome, the true version is after "Chrome" 
        else if ((verOffset = nAgt.indexOf("Chrome")) != -1) {
            browserName = "Chrome";
            fullVersion = nAgt.substring(verOffset + 7);
        }
        // In Safari, the true version is after "Safari" or after "Version" 
        else if ((verOffset = nAgt.indexOf("Safari")) != -1) {
            browserName = "Safari";
            fullVersion = nAgt.substring(verOffset + 7);
            if ((verOffset = nAgt.indexOf("Version")) != -1)
                fullVersion = nAgt.substring(verOffset + 8);
        }
        // In Firefox, the true version is after "Firefox" 
        else if ((verOffset = nAgt.indexOf("Firefox")) != -1) {
            browserName = "Firefox";
            fullVersion = nAgt.substring(verOffset + 8);
        }
        // In most other browsers, "name/version" is at the end of userAgent 
        else if ((nameOffset = nAgt.lastIndexOf(' ') + 1) < (verOffset = nAgt.lastIndexOf('/'))) {
            browserName = nAgt.substring(nameOffset, verOffset);
            fullVersion = nAgt.substring(verOffset + 1);
            if (browserName.toLowerCase() == browserName.toUpperCase()) {
                browserName = navigator.appName;
            }
        }

        // trim the fullVersion string at semicolon/space if present
        if ((ix = fullVersion.indexOf(";")) != -1)
            fullVersion = fullVersion.substring(0, ix);
        if ((ix = fullVersion.indexOf(" ")) != -1)
            fullVersion = fullVersion.substring(0, ix);

        majorVersion = parseInt('' + fullVersion, 10);
        if (isNaN(majorVersion)) {
            fullVersion = '' + parseFloat(navigator.appVersion);
            majorVersion = parseInt(navigator.appVersion, 10);
        }

        var info = '{';
        info += '"screenWidth":"' + sw + '",';
        info += '"screenHeight":"' + sh + '",';
        info += '"browserName":"' + browserName + '",';
        info += '"fullVersion":"' + fullVersion + '",';
        info += '"majorVersion":"' + majorVersion + '",';
        info += '"platform":"' + navigator.platform + '"';
        info += '}';

        var cookie = $.cookie(cookieName);
        var date = new Date();

        if (cookie === undefined) {
            $.cookie(cookieName, info, { expires: date.setDate(date.setHours(date.getHours() + 1)) });
        }
        else {
            if (cookie != info)
                $.cookie(cookieName, info, { expires: date.setDate(date.setHours(date.getHours() + 1)) });
        }

    });
})(jQuery);;/*
*   wConfirmClick
*   Spinutech
*   Sept 2012, updated Feb 2015
*
*   02-26-2015  v1.1.0.0    Added off/on for single event binding; Plus, added namespace to click event
*   09-01-2012  v1.0.0.0    Initial version
*   
*   Simple jquery plugin that throws a custom confirmation message using jQuery dialog
*   when clicking on selected object. If confirmation is false, click is ignored.
*
*/
(function ($) {

    $.fn.wConfirmClick = function (opts) {
        var settings = $.extend({
            onConfirm: null,
            message: null,
            title: 'Warning'
        }, opts);

        var s4 = function () {
            return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
        }

        var guid = function () {
            var g = (s4() + s4() + "-" + s4() + "-4" + s4().substr(0, 3) + "-" + s4() + "-" + s4() + s4() + s4()).toLowerCase();
            return g;
        }

        this.each(function () {
            var $this = $(this);
            opts = opts === undefined ? {} : opts;

            $this.off('click.confirmClick').on('click.confirmClick', function (e) {
                var id = guid();

                var title = $this.data('title');
                var message = $this.data('message');

                opts.title = title !== undefined && title.length > 0 ? title : opts.title;
                opts.message = message !== undefined && message.length > 0 ? message : opts.message;

                $('body').find(':eq(0)').before('<div id="' + id + '">' + opts.message + '</div>');
                var $messageDiv = $('#' + id);

                if ($messageDiv.length > 0) {
                    $messageDiv.dialog({
                        title: opts.title == undefined ? 'Warning' : opts.title,
                        width: 400,
                        resizable: false,
                        modal: true,
                        buttons: {
                            'Proceed': function () {
                                $(this).dialog('close');
                                $messageDiv.remove();

                                if (opts.onConfirm == null) {
                                    if ($this.attr('href') != undefined)
                                        window.location = $this.attr('href');
                                    else if ($this.is("input[type='submit']"))
                                        $this.closest('form').submit();
                                }
                                else if(typeof opts.onConfirm === 'function') {
                                    var r = opts.onConfirm($this);
                                    if (r) {
                                        if ($this.attr('href') != undefined)
                                            window.location = $this.attr('href');
                                        else if ($this.is("input[type='submit']"))
                                            $this.closest('form').submit();
                                    }
                                }
                            },
                            Cancel: function () {
                                $(this).dialog('close');
                                $messageDiv.remove();
                            }
                        }
                    });

                    e.preventDefault();
                    return false;
                }
                else {
                    var c = confirm(message);
                    if (!c) {
                        e.preventDefault();
                        return false;
                    }
                }
            });
        });

        return this;
    };

})(jQuery);;var initConfirmMessage = function ($, message, customClass) {
    if (customClass == 'error') ConfirmMessage.Error(message);
    else ConfirmMessage.Confirm(message);
};

var ConfirmMessage = (function ($) {

    var _wrapperClass = 'form-message';

    var _template = function (message, customClass) {
        var html = '';
        html += '<div class="' + _wrapperClass + '">';
        html += '   <div class="' + _wrapperClass + '-wrapper">';
        html += '       <div class="' + _wrapperClass + '-content ' + (customClass ? customClass : '') + '">' + message + '</div>';
        html += '   </div>';
        html += '</div>';
        return html;
    }

    var _showMessage = function (html) {
        $('body').find('.' + _wrapperClass).remove();

        var $msg = $(html);
        $('body').prepend($msg);
        setTimeout(function () {
            $msg.fadeOut('slow', function () {
                $msg.remove();
            });
        }, 4000);
    }

    var classes = {
        confirm: 'confirm',
        error: 'error',
        warn: 'warn'
    };

    return {
        Confirm: function (message) {
            var templ = _template(message, classes.confirm);
            _showMessage(templ);
        },
        Error: function (message) {
            var templ = _template(message, classes.error);
            _showMessage(templ);
        },
        Warn: function (message) {
            var templ = _template(message, classes.warn);
            _showMessage(templ);
        }
    }

})(jQuery);;(function ($) {
    $(document).ready(function () {
        initFormMessage($);
    });
})(jQuery);

var initFormMessage = function ($) {
    var $wFormMessage = $('.form-message').first();
    if ($wFormMessage != undefined) {

        setTimeout(function () {
            $wFormMessage.fadeOut('slow', function () {
                $wFormMessage.remove();
            });
        }, 7000);
    }
};;(function ($) {

	//this script relies on responsive.js
	var _Responsive = Responsive ||
		// ensure no js errors if not included
		{ init: function () { alert('Method not implemented; please include responsive.js script in page head!'); } },


	//flags
	_menu_created,
	_menu_open,


	//method to create the custom sidebar menu for smaller window sizes
	_createMenu = function () {
		if ($("#nav").size() == 0) return;

		var navPrimary = $("#nav ul").html();
		var navSecondary = ($("#nav-secondary ul").size() > 0) ? $("#nav-secondary ul").html() : "";
		
		$("body").append("<div id='menu'><ul id='menu-primary'>" + navPrimary + "</ul></div>");
		if ($("#nav-secondary ul").size() > 0) $("#menu .current").append("<ul>" + navSecondary + "</ul>");
		$("#header-content").prepend("<a id='nav-toggle' href='#'><i class='fa fa-bars'></i> Menu</a>");
		
		$("#menu").height($(window).height());
		$("#nav").hide();

		$("#nav-toggle").click(function (event) {
			$("#menu").show().animate({ right: "0" }, 150);
			$("#wrapper").css({ position: "fixed", top: 0, width: $("#wrapper").width() }).animate({ right: "250px" }, 150);
			_menu_open = true;
			event.stopPropagation();
			return false;
		});

        $("html").on("click touchstart", function (e) {
            if (_menu_open && $("#menu").has(e.target).length === 0) {
                $("#menu").animate({ right: "-400px" }, 150, function () {
                    $(this).hide();
                });
                $("#wrapper").animate({ right: 0 }, 150, function () {
                    $(this).css({ position: "static", top: "auto", width: "auto" });
                });
                _menu_open = false;
                e.stopPropagation();
                return false;
            }
        });
	},

	//method to remove the custom sidebar menu
	_removeMenu = function () {
        $("#menu, #nav-toggle").remove();
        $("#wrapper").css({ position: "static", top: "auto", width: "auto" });
        $("#nav").show();
    };


	// initialize responsive layouts
	_Responsive.init({
		layouts: {
			MENU: { maxWidth: 600, stylesheet: false }
		},
		//listen for responsive layout change; will also be fired once on page load
		onLayoutChange: function (layout) {
			if (layout == _Responsive.LayoutType.MENU) {
				if (!_menu_created)
					_createMenu();
				_menu_created = true;
			}
			else {
				if (_menu_created)
					_removeMenu();
				_menu_created = false;
			}
		}
	});

})(jQuery);
;/*
*
*   wModalForm
*   Author: Spinutech
*   Feb 2013; Last updated January 2018
*
*   01-23-2018  v 1.6.2.1   Added customAjax option
*   05-18-2016  v 1.6.2.0   Added form() public method
*   04-21-2016  v 1.6.1.0   Do not show buttons if button text is set to empty ('').
*   03-10-2016  v 1.6.0.1   Bug fix when hiding dialog after onSave() and doRefresh = false.
*   02-25-2016  v 1.6.0.0   Updated form getter dialog to work with w.ajaxHelper.promise for better error showing.   
*   02-10-2016  v 1.5.0.0   Added "processing" message when clicking "submit" button
*   07-15-2015  v 1.4.4.0   Added enable()/disable() methods
*   07-14-2015  v 1.4.3.1   Added onGetForm() event handler; Added updateSourceParam(key, value), resetSourceParams(), updateTitle(title) methods
*   03-20-2015  v 1.4.3.0   Added public dialog() method that returns the dialog instance
*   02-11-2015  v 1.4.2.0   Show error dialog if form failed to load
*   02-09-2015  v 1.4.1.0   Show loading dialog when loading form
*   11-10-2014  v 1.4.0.0   Added enableEnter option
*   11-06-2014  v 1.3.1.0   Added buttons for options; Removed unused methods
*   09-11-2014  v 1.2.0.0   Added onSave() event handler
*   12-05-2013  v 1.1.2.0   Added onTrySave() event handler
*   11-06-2013  v 1.1.0.1
*
*   Description: Use this plugin to load a form into a modal dialog.
*   Saving of form is automated as long as action property of loaded form is provided.
*   Save and Cancel buttons are provided on dialog. No need to include them in the form.
*   The saving return must be a json object with the following params:
*   - Valid (bool)
*   - Errors (array of strings)
*   - Model (the .net model)
*
*   Plugin options:
*   buttons: {
*       cancel:     (string)    Name of close (cancel) button. Default 'Cancel'.
*       save:       (string)    Name of save button. Default 'Save'.
*   }
*   doRefresh:      (bool)      Refreshes the page when form submit is successful (when results.Valid is true). Default is true.
*   enableEnter:    (bool)      Enable enter button to submit form. First input field is focused. Default is false.
*   minWidth:       (int)       Minimum width of dialog. Default is 600.
*   source:         (string)    Source url for loading form. If null, defaults to anchortag's href attrib
*   sourceParms:    (2D array)  Optional parameters passed to 'source' url. Ex: [[ 'param1', 'x' ],[ 'param2', 99 ]]
*   target:         (string)    jQuery selector for dialog. Ex: '$(#div-selector)'. Default is null > will create one dynamically.
*   title:          (string)    Dialog title. Default ''. Will get data-title attribute if empty.
*   type:           (string)    jQuery.ajax submit type. Default is 'Post'
*   onForm          (func)      Triggered when ajax form is loaded
*   onGetForm       (func)      Triggered when just before ajax is made to get form
*   onSave:         (func)      Triggered when saving of model is successful
*   onTrySave:      (func)      Triggered just before saving ajax
*   customAjax      (func)      This ajax function will be triggered in place of default ajax
*
*   Plugin events:
*   wModalFormGet               Triggered when trying to load external form
*   wModalFormSuccess           Triggered when form is loaded
*   wModalFormError             Triggered when form failed to load
*   wModalFormTrySave           Triggered when trying to save the form
*   wModalFormSaved             Triggered when form has been successfully saved
*   wModalFormSaveError         Triggered when form submit had validation errors or when submit failed due to some 500 server error
*
*/

(function ($) {
    $.wModalForm = function (element, opts) {
        var defaults = $.extend(true, {
            buttons: {
                cancel: 'Cancel',
                save: 'Save'
            },
            doRefresh: true,
            enableEnter: false,
            minWidth: null,
            onForm: function (form, plugin) { },
            onGetForm: function(plugin) { },
            source: null,
            sourceParms: null,
            target: null,
            title: '',
            type: 'Post',
            customAjax: null,

            // event handlers
            onSave: function (obj, plugin) { },
            onTrySave: function (plugin) { }
        }, opts);

        var plugin = this;
        plugin.settings = {};

        var settings;
        var cancelLoad = false;
        var $cancel;
        var $element = $(element), element = element;
        var $errors;
        var $form;
        var $save;
        var $target;

        var isSaving;


        /***********************
        * Ajax Functions (used for customAjax in PaymentHelper)
        ***********************/
        var successFunction = function (results) {
            var valid = results.Valid;
            var errors = results.Errors;

            if (valid) {
                if (typeof settings.onSave === 'function')
                    settings.onSave(results.Model, plugin);

                if (settings.doRefresh) {
                    var hash = window.location.hash;
                    var url = window.location.href;
                    if (hash.length > 0 || url[url.length - 1] === '#')
                        url = url.substring(0, url.lastIndexOf('#'));
                    window.location = url;
                }
                else {
                    hideDialog();
                    $element.trigger('wModalFormSaved', results.Model);
                }
            }
            else {
                showErrors(errors);
                $element.trigger('wModalFormSaveError');
                hideProcessingMessage();
            }
        };

        var errorFunction = function (status) {
            var errors = ["Server error. Please try again or contact IT if error persists."];
            showErrors(errors);
            $element.trigger('wModalFormSaveError');
            hideProcessingMessage();
        };

        var completeFunction = function () {
            isSaving = false;
        };


        /***********************
        * Grand init
        ***********************/
        plugin.init = function () {
            plugin.settings = defaults;
            settings = plugin.settings;

            if (settings.target != null)
                $target = settings.target;

            if ($element.data('title') !== undefined)
                settings.title = $element.data('title');

            initClickEvent();
            isSaving = false;
        };

        /***********************
        * Initializers
        ***********************/
        var initClickEvent = function () {
            $element.off('click.wModalForm');
            $element.on('click.wModalForm', function (e) {
                getForm();

                e.preventDefault();
                return false;
            });
        }

        var getForm = function () {
            $element.trigger('wModalFormGet');
            plugin.settings.onGetForm(plugin);

            if (!cancelLoad) {
                var data = getSourceParmsData();
                initLoadDialog();

                var getPromise = spinutech.ajaxHelper.resolveAjax($.ajax({
                    data: data,
                    url: settings.source != null ? settings.source : $element.attr('href'),
                    type: settings.type
                }));

                getPromise.then(function (results) {
                    // success
                    var valid = results.Valid !== undefined ? results.Valid : true;
                    if (!cancelLoad) {
                        initDialog(results, valid);
                        initForm();

                        if (valid) {
                            plugin.settings.onForm($form, plugin);
                            $element.trigger('wModalFormSuccess');
                        }
                        else {
                            showErrors(results.Errors);
                        }
                    }
                    cancelLoad = false;
                }, function () {
                    // error
                    hideDialog();
                    $element.trigger('wModalFormError');
                }).then(function () {
                    // done
                });
            }
        }

        var initForm = function () {
            $form = $target.find('form').first();
            $form.find('input,textarea').each(function () {
                // disable focusing on the inputs by default
                if (!plugin.settings.enableEnter) {
                    $(this).blur();
                }
                else {
                    if ($(this).is('input')) {
                        $(this).on('keypress', function (e) {
                            var buttons = getButtons();
                            if (settings.buttons.save) {
                                var saveButton = buttons[settings.buttons.save];
                                if (e.keyCode === $.ui.keyCode.ENTER && typeof saveButton === 'function') {
                                    saveButton();
                                    e.preventDefault();
                                    return false;
                                }
                            }
                        });
                    }
                }
            });
        }

        var initDialog = function (results, valid) {
            $target.remove();
            $target = createWrapper();

            $target.empty();
            $target.append(results);

            var buttons = {};
            if (valid) {
                buttons = {};

                // init save button
                if (settings.buttons.save) {
                    buttons[settings.buttons.save] = function () {

                        // insert "processing..." message and hide buttons while saving
                        var $buttonset = $(this).closest('.ui-dialog').find('.ui-dialog-buttonset');
                        var $formProcessing = $(this).closest('.ui-dialog').find('.modal-form-processing');

                        if ($formProcessing.length === 0) {
                            $formProcessing = $('<div class="modal-form-processing" style="float: right;"><i class="fa fa-spinner fa-spin"></i> Processing. Please wait&hellip;<br /><span class="mute">Do not reload this page</span></div>');
                            $buttonset.after($formProcessing);
                        }

                        $buttonset.hide();
                        $formProcessing.show();

                        initSave();
                    }
                }

                // init cancel button
                if (settings.buttons.cancel) {
                    buttons[settings.buttons.cancel] = function () {
                        if (!isSaving) $target.dialog('close');
                        else initConfirmMessage($, 'Form is being saved. Please wait...', 'error');
                    }
                }
            }
            else {
                buttons = {
                    'Close': function () { $target.dialog('close'); }
                }
            }

            $target.dialog({
                buttons: buttons,
                close: function (evt, ui) { $target.remove(); },
                minWidth: valid ? (settings.minWidth != null ? settings.minWidth : 600) : 600,
                modal: true,
                title: settings.title
            });
        }

        var initLoadDialog = function () {
            if ($target === undefined)
                $target = createWrapper();

            $target.empty();
            $target.append('<i class="fa fa-spinner fa-spin fa-lg"></i> Loading. Please wait&hellip;');

            $target.dialog({
                buttons: { 
                    'Cancel': function () {
                        cancelLoad = true;
                        $target.dialog('close');
                    }
                },
                close: function (evt, ui) { $target.remove(); },
                minWidth: 200,
                modal: true,
                title: 'Loading'
            });

            $target.closest('.ui-dialog').find('.ui-dialog-titlebar').remove();
        }

        var initSave = function () {
            $element.trigger('wModalFormTrySave');
            settings.onTrySave(plugin);

            if (!isSaving) {
                isSaving = true;

                // remove previous error message if there is one
                $target.find('.flash').first().remove();

                // perform saving
                if (settings.customAjax != null) {
                    settings.customAjax;
                }
                else {
                    // collect form's data
                    var url = $form.attr('action');
                    var data = $form.serialize();

                    $.ajax({
                        url: url,
                        data: data,
                        type: 'Post',
                        success: successFunction,
                        error: errorFunction,
                        complete: completeFunction 
                    });
                }
            }
            else {
                initConfirmMessage($, 'Form is being saved. Please wait...', 'error');
            }
        }

        var hideDialog = function () {
            if ($target !== undefined) {
                $target.dialog('close');
                $target.remove();
            }
        };

        /***********************
        * Functional
        ***********************/
        var getButtons = function () {
            return $target.dialog('option', 'buttons');
        }

        var getSourceParmsData = function () {
            var data = '';
            if (settings.sourceParms != null) {
                var delim = '';
                try {
                    for (var i = 0; i < settings.sourceParms.length; i++) {
                        data += delim + settings.sourceParms[i][0] + '=' + settings.sourceParms[i][1];
                        delim = '&';
                    }
                }
                catch (err) {
                    data = '';
                    if (console)
                        console.log('w.modal-form @getSourceParmsData(): ' + err.message);
                }
            }

            return data;
        }

        var hideProcessingMessage = function () {
            // show buttonset and hide "processing..." message
            var $buttonset = $target.dialog().closest('.ui-dialog').find('.ui-dialog-buttonset');
            var $formProcessing = $target.dialog().closest('.ui-dialog').find('.modal-form-processing');

            $buttonset.show();
            $formProcessing.hide();
        }

        var showErrors = function (errors) {
            var errorHtml = '';
            errorHtml += '<div class="flash">';
            errorHtml += '    <div class="error">';
            errorHtml += '        <h2>The following errors occured:</h2>';
            errorHtml += '    </div>';
            errorHtml += '</div>';

            $target.prepend($(errorHtml));
            $errors = $target.find('.flash .error');

            var errorList = '<ul>';
            if (errors) {
                for (var i = 0; i < errors.length; i++)
                    errorList += '<li>' + errors[i] + '</li>';
            }
            else
                errorList += '<li>Server error</li>';
            errorList += '</ul>';

            $errors.append($(errorList));
        }

        var createWrapper = function () {
            var id = guid();
            $('body').find(':eq(0)').before('<div id="' + id + '" style="display:none;"></div>');
            return $('#' + id);
        }

        /***********************
        * Private methods
        ***********************/
        var s4 = function () {
            return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
        }

        var guid = function () {
            var g = (s4() + s4() + "-" + s4() + "-4" + s4().substr(0, 3) + "-" + s4() + "-" + s4() + s4() + s4()).toLowerCase();
            return g;
        }

        /***********************
        * Public methods
        ***********************/
        plugin.dialog = function () {
            return $target.dialog('instance');
        };

        plugin.disable = function () {
            cancelLoad = true;
        };

        plugin.enable = function () {
            cancelLoad = false;
        };

        plugin.close = function () {
            if ($target !== undefined && $target.length > 0)
                $target.dialog('close');
        };

        plugin.form = function () {
            return $form;
        };

        plugin.resetSourceParms = function () {
            settings.sourceParms = [];
        };

        plugin.updateSourceParam = function (key, value) {
            settings.sourceParms = settings.sourceParms || [];
            var index = -1;
            for (var i = 0; i < settings.sourceParms.length; i++) {
                if (settings.sourceParms[i][0] === key) {
                    index = i;
                    break;
                }
            }

            if (index === -1)
                settings.sourceParms.push([key, value]);
            else
                settings.sourceParms[index] = [key, value];
        };

        plugin.updateTitle = function (title) {
            settings.title = title;
        };

        plugin.ajax = function () {
            return {
                isAjax: true,
                successFunction: successFunction,
                errorFunction: errorFunction,
                completeFunction: completeFunction
            };
        }

        /***********************
        * Run plugin grand init
        ***********************/
        plugin.init();
    };

    $.fn.wModalForm = function (opts) {
        return this.each(function () {
            if ($(this).data('wModalForm') == undefined) {
                var plugin = new $.wModalForm(this, opts);
                $(this).data('wModalForm', plugin);
            }
        });
    };

})(jQuery);;