'+h.eq(i).text()+\"\";h.eq(i).parent().is(\"optgroup\")&&(void 0!==h.eq(i).parent().attr(\"class\")&&(f=\" \"+h.eq(i).parent().attr(\"class\")),a=\"'+h.eq(i).text()+\"\",h.eq(i).is(\":first-child\")&&\n(a=''+h.eq(i).parent().attr(\"label\")+\"\"+a));w+=a}}function p(){var r=new s,d=c(\"');a.css({margin:0,padding:0}).after(d).prependTo(d);\nvar r=c(\"div.jq-selectbox__select\",d),m=c(\"div.jq-selectbox__select-text\",d),l=h.filter(\":selected\");l.length?m.text(l.text()):m.text(h.first().text());b();var k=\"\";f.selectSearch&&(k=''+f.selectSearchNotFound+\"
\");var e=c('\");d.append(e);var n=c(\"ul\",e),g=c(\"li\",e),t=c(\"input\",e),x=c(\"div.jq-selectbox__not-found\",e).hide();g.lengthu&&(u=a.innerWidth(),A=a.width());a.css({display:\"block\"})});var k=d.clone().appendTo(\"body\").width(\"auto\"),v=k.width();k.remove();v==d.width()&&(m.width(A),u+=d.find(\"div.jq-selectbox__trigger\").width());u>d.width()&&e.width(u);\na.css({position:\"absolute\",left:0,top:0,width:\"100%\",height:\"100%\",opacity:0});var B=d.outerHeight(),z=t.outerHeight(),y=n.css(\"max-height\"),k=g.filter(\".selected\");1>k.length&&g.first().addClass(\"selected sel\");void 0===g.data(\"li-height\")&&g.data(\"li-height\",g.outerHeight());var C=e.css(\"top\");\"auto\"==e.css(\"left\")&&e.css({left:0});\"auto\"==e.css(\"top\")&&e.css({top:B});e.hide();k.length&&(h.first().text()!=l.text()&&d.addClass(\"changed\"),d.data(\"jqfs-class\",k.data(\"jqfs-class\")),d.addClass(k.data(\"jqfs-class\")));\nif(a.is(\":disabled\"))return d.addClass(\"disabled\"),!1;r.click(function(){a.focus();if(!navigator.userAgent.match(/(iPad|iPhone|iPod)/g)){if(f.selectSmartPositioning){var b=c(window),h=d.offset().top,m=b.height()-B-(h-b.scrollTop()),k=f.selectVisibleOptions,l=g.data(\"li-height\"),p=5*l,r=l*k;0k&&(p=r);0==k&&(r=\"auto\");m>p+z+20?(e.height(\"auto\").css({bottom:\"auto\",top:C}),k=function(){n.css(\"max-height\",Math.floor((m-20-z)/l)*l)},k(),n.css(\"max-height\",r),\"none\"!=y&&n.css(\"max-height\",y),mg.filter(\":visible\").length?x.show():x.hide()}));q(n);return!1}});g.hover(function(){c(this).siblings().removeClass(\"selected\")});var D=g.filter(\".selected\").text();g.filter(\".selected\").text();g.filter(\":not(.disabled):not(.optgroup)\").click(function(){var b=\nc(this),n=b.text();if(D!=n){var g=b.index();b.is(\".option\")&&(g-=b.prevAll(\".optgroup\").length);b.addClass(\"selected sel\").siblings().removeClass(\"selected sel\");h.prop(\"selected\",!1).eq(g).prop(\"selected\",!0);D=n;m.text(n);h.first().text()!=n?d.addClass(\"changed\"):d.removeClass(\"changed\");d.data(\"jqfs-class\")&&d.removeClass(d.data(\"jqfs-class\"));d.data(\"jqfs-class\",b.data(\"jqfs-class\"));d.addClass(b.data(\"jqfs-class\"));a.change()}t.length&&(t.val(\"\").keyup(),x.hide());e.hide();d.removeClass(\"opened\")});\ne.mouseout(function(){c(\"li.sel\",e).addClass(\"selected\")});a.change(function(){m.text(h.filter(\":selected\").text());g.removeClass(\"selected sel\").not(\".optgroup\").eq(a[0].selectedIndex).addClass(\"selected sel\")}).focus(function(){d.addClass(\"focused\")}).blur(function(){d.removeClass(\"focused\")}).bind(\"keydown keyup\",function(b){m.text(h.filter(\":selected\").text());g.removeClass(\"selected sel\").not(\".optgroup\").eq(a[0].selectedIndex).addClass(\"selected sel\");38!=b.which&&37!=b.which&&33!=b.which||\ne.scrollTop(e.scrollTop()+g.filter(\".selected\").position().top);40!=b.which&&39!=b.which&&34!=b.which||e.scrollTop(e.scrollTop()+g.filter(\".selected\").position().top-e.innerHeight()+liHeight);13==b.which&&e.hide()});c(document).on(\"click\",function(a){c(a.target).parents().hasClass(\"jq-selectbox\")||\"OPTION\"==a.target.nodeName||(t.length&&t.val(\"\").keyup(),e.hide().find(\"li.sel\").addClass(\"selected\"),d.removeClass(\"focused opened\"))})}function E(){var f=new s,d=c(\"');a.css({margin:0,padding:0}).after(d);b();d.append(\"\");var m=c(\"ul\",d).css({position:\"relative\",\"overflow-x\":\"hidden\",\"-webkit-overflow-scrolling\":\"touch\"}),l=c(\"li\",d).attr(\"unselectable\",\"on\").css({\"-webkit-user-select\":\"none\",\"-moz-user-select\":\"none\",\"-ms-user-select\":\"none\",\"-o-user-select\":\"none\",\"user-select\":\"none\",\"white-space\":\"nowrap\"}),f=a.attr(\"size\"),k=m.outerHeight(),e=l.outerHeight();void 0!==\nf&&0d.height()&&(m.css(\"overflowY\",\"scroll\"),q(m),l.filter(\".selected\").length&&m.scrollTop(m.scrollTop()+l.filter(\".selected\").position().top));a.prependTo(d).css({position:\"absolute\",left:0,top:0,width:\"100%\",height:\"100%\",opacity:0});a.is(\":disabled\")?(d.addClass(\"disabled\"),h.each(function(){c(this).is(\":selected\")&&l.eq(c(this).index()).addClass(\"selected\")})):(l.filter(\":not(.disabled):not(.optgroup)\").click(function(b){a.focus();d.removeClass(\"focused\");\nvar g=c(this);b.ctrlKey||b.metaKey||g.addClass(\"selected\");b.shiftKey||g.addClass(\"first\");b.ctrlKey||(b.metaKey||b.shiftKey)||g.siblings().removeClass(\"selected first\");if(b.ctrlKey||b.metaKey)g.is(\".selected\")?g.removeClass(\"selected first\"):g.addClass(\"selected first\"),g.siblings().removeClass(\"first\");if(b.shiftKey){var e=!1,f=!1;g.siblings().removeClass(\"selected\").siblings(\".first\").addClass(\"selected\");g.prevAll().each(function(){c(this).is(\".first\")&&(e=!0)});g.nextAll().each(function(){c(this).is(\".first\")&&\n(f=!0)});e&&g.prevAll().each(function(){if(c(this).is(\".selected\"))return!1;c(this).not(\".disabled, .optgroup\").addClass(\"selected\")});f&&g.nextAll().each(function(){if(c(this).is(\".selected\"))return!1;c(this).not(\".disabled, .optgroup\").addClass(\"selected\")});1==l.filter(\".selected\").length&&g.addClass(\"first\")}h.prop(\"selected\",!1);l.filter(\".selected\").each(function(){var a=c(this),b=a.index();a.is(\".option\")&&(b-=a.prevAll(\".optgroup\").length);h.eq(b).prop(\"selected\",!0)});a.change()}),h.each(function(a){c(this).data(\"optionIndex\",\na)}),a.change(function(){l.removeClass(\"selected\");var a=[];h.filter(\":selected\").each(function(){a.push(c(this).data(\"optionIndex\"))});l.not(\".optgroup\").filter(function(b){return-1d.height()&&a.keydown(function(a){38!=a.which&&37!=a.which&&33!=a.which||m.scrollTop(m.scrollTop()+l.filter(\".selected\").position().top-e);40!=a.which&&39!=a.which&&34!=a.which||m.scrollTop(m.scrollTop()+\nl.filter(\".selected:last\").position().top-m.innerHeight()+2*e)}))}var h=c(\"option\",a),w=\"\";a.is(\"[multiple]\")?E():p()};p();a.on(\"refresh\",function(){a.parent().before(a).remove();p()})}}):a.is(\":reset\")&&a.click(function(){setTimeout(function(){a.closest(f.wrapper).find(\"input, select\").trigger(\"refresh\")},1)})})}})(jQuery);","/*!\n * hoverIntent v1.9.0 // 2017.09.01 // jQuery v1.7.0+\n * http://briancherne.github.io/jquery-hoverIntent/\n *\n * You may use hoverIntent under the terms of the MIT license. Basically that\n * means you are free to use hoverIntent as long as this header is left intact.\n * Copyright 2007-2017 Brian Cherne\n */\n\n/* hoverIntent is similar to jQuery's built-in \"hover\" method except that\n * instead of firing the handlerIn function immediately, hoverIntent checks\n * to see if the user's mouse has slowed down (beneath the sensitivity\n * threshold) before firing the event. The handlerOut function is only\n * called after a matching handlerIn.\n *\n * // basic usage ... just like .hover()\n * .hoverIntent( handlerIn, handlerOut )\n * .hoverIntent( handlerInOut )\n *\n * // basic usage ... with event delegation!\n * .hoverIntent( handlerIn, handlerOut, selector )\n * .hoverIntent( handlerInOut, selector )\n *\n * // using a basic configuration object\n * .hoverIntent( config )\n *\n * @param handlerIn function OR configuration object\n * @param handlerOut function OR selector for delegation OR undefined\n * @param selector selector OR undefined\n * @author Brian Cherne \n */\n\n;(function(factory) {\n 'use strict';\n if (typeof define === 'function' && define.amd) {\n define(['jquery'], factory);\n } else if (jQuery && !jQuery.fn.hoverIntent) {\n factory(jQuery);\n }\n})(function($) {\n 'use strict';\n\n // default configuration values\n var _cfg = {\n interval: 100,\n sensitivity: 6,\n timeout: 0\n };\n\n // counter used to generate an ID for each instance\n var INSTANCE_COUNT = 0;\n\n // current X and Y position of mouse, updated during mousemove tracking (shared across instances)\n var cX, cY;\n\n // saves the current pointer position coordinates based on the given mousemove event\n var track = function(ev) {\n cX = ev.pageX;\n cY = ev.pageY;\n };\n\n // compares current and previous mouse positions\n var compare = function(ev,$el,s,cfg) {\n // compare mouse positions to see if pointer has slowed enough to trigger `over` function\n if ( Math.sqrt( (s.pX-cX)*(s.pX-cX) + (s.pY-cY)*(s.pY-cY) ) < cfg.sensitivity ) {\n $el.off(s.event,track);\n delete s.timeoutId;\n // set hoverIntent state as active for this element (permits `out` handler to trigger)\n s.isActive = true;\n // overwrite old mouseenter event coordinates with most recent pointer position\n ev.pageX = cX; ev.pageY = cY;\n // clear coordinate data from state object\n delete s.pX; delete s.pY;\n return cfg.over.apply($el[0],[ev]);\n } else {\n // set previous coordinates for next comparison\n s.pX = cX; s.pY = cY;\n // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)\n s.timeoutId = setTimeout( function(){compare(ev, $el, s, cfg);} , cfg.interval );\n }\n };\n\n // triggers given `out` function at configured `timeout` after a mouseleave and clears state\n var delay = function(ev,$el,s,out) {\n delete $el.data('hoverIntent')[s.id];\n return out.apply($el[0],[ev]);\n };\n\n $.fn.hoverIntent = function(handlerIn,handlerOut,selector) {\n // instance ID, used as a key to store and retrieve state information on an element\n var instanceId = INSTANCE_COUNT++;\n\n // extend the default configuration and parse parameters\n var cfg = $.extend({}, _cfg);\n if ( $.isPlainObject(handlerIn) ) {\n cfg = $.extend(cfg, handlerIn);\n if ( !$.isFunction(cfg.out) ) {\n cfg.out = cfg.over;\n }\n } else if ( $.isFunction(handlerOut) ) {\n cfg = $.extend(cfg, { over: handlerIn, out: handlerOut, selector: selector } );\n } else {\n cfg = $.extend(cfg, { over: handlerIn, out: handlerIn, selector: handlerOut } );\n }\n\n // A private function for handling mouse 'hovering'\n var handleHover = function(e) {\n // cloned event to pass to handlers (copy required for event object to be passed in IE)\n var ev = $.extend({},e);\n\n // the current target of the mouse event, wrapped in a jQuery object\n var $el = $(this);\n\n // read hoverIntent data from element (or initialize if not present)\n var hoverIntentData = $el.data('hoverIntent');\n if (!hoverIntentData) { $el.data('hoverIntent', (hoverIntentData = {})); }\n\n // read per-instance state from element (or initialize if not present)\n var state = hoverIntentData[instanceId];\n if (!state) { hoverIntentData[instanceId] = state = { id: instanceId }; }\n\n // state properties:\n // id = instance ID, used to clean up data\n // timeoutId = timeout ID, reused for tracking mouse position and delaying \"out\" handler\n // isActive = plugin state, true after `over` is called just until `out` is called\n // pX, pY = previously-measured pointer coordinates, updated at each polling interval\n // event = string representing the namespaced event used for mouse tracking\n\n // clear any existing timeout\n if (state.timeoutId) { state.timeoutId = clearTimeout(state.timeoutId); }\n\n // namespaced event used to register and unregister mousemove tracking\n var mousemove = state.event = 'mousemove.hoverIntent.hoverIntent'+instanceId;\n\n // handle the event, based on its type\n if (e.type === 'mouseenter') {\n // do nothing if already active\n if (state.isActive) { return; }\n // set \"previous\" X and Y position based on initial entry point\n state.pX = ev.pageX; state.pY = ev.pageY;\n // update \"current\" X and Y position based on mousemove\n $el.off(mousemove,track).on(mousemove,track);\n // start polling interval (self-calling timeout) to compare mouse coordinates over time\n state.timeoutId = setTimeout( function(){compare(ev,$el,state,cfg);} , cfg.interval );\n } else { // \"mouseleave\"\n // do nothing if not already active\n if (!state.isActive) { return; }\n // unbind expensive mousemove event\n $el.off(mousemove,track);\n // if hoverIntent state is true, then call the mouseOut function after the specified delay\n state.timeoutId = setTimeout( function(){delay(ev,$el,state,cfg.out);} , cfg.timeout );\n }\n };\n\n // listen for mouseenter and mouseleave\n return this.on({'mouseenter.hoverIntent':handleHover,'mouseleave.hoverIntent':handleHover}, cfg.selector);\n };\n});","/*\n * Lazy Load - jQuery plugin for lazy loading images\n *\n * Copyright (c) 2007-2013 Mika Tuupola\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/mit-license.php\n *\n * Project home:\n * http://www.appelsiini.net/projects/lazyload\n *\n * Version: 1.9.3\n *\n */\n\n(function($, window, document, undefined) {\n var $window = $(window);\n\n $.fn.lazyload = function(options) {\n var elements = this;\n var $container;\n var settings = {\n threshold : 0,\n failure_limit : 0,\n event : \"scroll\",\n effect : \"show\",\n container : window,\n data_attribute : \"original\",\n skip_invisible : true,\n appear : null,\n load : null,\n placeholder : \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC\"\n };\n\n function update() {\n var counter = 0;\n\n elements.each(function() {\n var $this = $(this);\n if (settings.skip_invisible && !$this.is(\":visible\")) {\n return;\n }\n if ($.abovethetop(this, settings) ||\n $.leftofbegin(this, settings)) {\n /* Nothing. */\n } else if (!$.belowthefold(this, settings) &&\n !$.rightoffold(this, settings)) {\n $this.trigger(\"appear\");\n /* if we found an image we'll load, reset the counter */\n counter = 0;\n } else {\n if (++counter > settings.failure_limit) {\n return false;\n }\n }\n });\n\n }\n\n if(options) {\n /* Maintain BC for a couple of versions. */\n if (undefined !== options.failurelimit) {\n options.failure_limit = options.failurelimit;\n delete options.failurelimit;\n }\n if (undefined !== options.effectspeed) {\n options.effect_speed = options.effectspeed;\n delete options.effectspeed;\n }\n\n $.extend(settings, options);\n }\n\n /* Cache container as jQuery as object. */\n $container = (settings.container === undefined ||\n settings.container === window) ? $window : $(settings.container);\n\n /* Fire one scroll event per scroll. Not one scroll event per image. */\n if (0 === settings.event.indexOf(\"scroll\")) {\n $container.bind(settings.event, function() {\n return update();\n });\n }\n\n this.each(function() {\n var self = this;\n var $self = $(self);\n\n self.loaded = false;\n\n /* If no src attribute given use data:uri. */\n if ($self.attr(\"src\") === undefined || $self.attr(\"src\") === false) {\n if ($self.is(\"img\")) {\n $self.attr(\"src\", settings.placeholder);\n }\n }\n\n /* When appear is triggered load original image. */\n $self.one(\"appear\", function() {\n if (!this.loaded) {\n if (settings.appear) {\n var elements_left = elements.length;\n settings.appear.call(self, elements_left, settings);\n }\n $(\"
\")\n .bind(\"load\", function() {\n\n var original = $self.attr(\"data-\" + settings.data_attribute);\n $self.hide();\n if ($self.is(\"img\")) {\n $self.attr(\"src\", original);\n } else {\n $self.css(\"background-image\", \"url('\" + original + \"')\");\n }\n $self[settings.effect](settings.effect_speed);\n\n self.loaded = true;\n\n /* Remove image from array so it is not looped next time. */\n var temp = $.grep(elements, function(element) {\n return !element.loaded;\n });\n elements = $(temp);\n\n if (settings.load) {\n var elements_left = elements.length;\n settings.load.call(self, elements_left, settings);\n }\n })\n .attr(\"src\", $self.attr(\"data-\" + settings.data_attribute));\n }\n });\n\n /* When wanted event is triggered load original image */\n /* by triggering appear. */\n if (0 !== settings.event.indexOf(\"scroll\")) {\n $self.bind(settings.event, function() {\n if (!self.loaded) {\n $self.trigger(\"appear\");\n }\n });\n }\n });\n\n /* Check if something appears when window is resized. */\n $window.bind(\"resize\", function() {\n update();\n });\n\n /* With IOS5 force loading images when navigating with back button. */\n /* Non optimal workaround. */\n if ((/(?:iphone|ipod|ipad).*os 5/gi).test(navigator.appVersion)) {\n $window.bind(\"pageshow\", function(event) {\n if (event.originalEvent && event.originalEvent.persisted) {\n elements.each(function() {\n $(this).trigger(\"appear\");\n });\n }\n });\n }\n\n /* Force initial check if images should appear. */\n $(document).ready(function() {\n update();\n });\n\n return this;\n };\n\n /* Convenience methods in jQuery namespace. */\n /* Use as $.belowthefold(element, {threshold : 100, container : window}) */\n\n $.belowthefold = function(element, settings) {\n var fold;\n\n if (settings.container === undefined || settings.container === window) {\n fold = (window.innerHeight ? window.innerHeight : $window.height()) + $window.scrollTop();\n } else {\n fold = $(settings.container).offset().top + $(settings.container).height();\n }\n\n return fold <= $(element).offset().top - settings.threshold;\n };\n\n $.rightoffold = function(element, settings) {\n var fold;\n\n if (settings.container === undefined || settings.container === window) {\n fold = $window.width() + $window.scrollLeft();\n } else {\n fold = $(settings.container).offset().left + $(settings.container).width();\n }\n\n return fold <= $(element).offset().left - settings.threshold;\n };\n\n $.abovethetop = function(element, settings) {\n var fold;\n\n if (settings.container === undefined || settings.container === window) {\n fold = $window.scrollTop();\n } else {\n fold = $(settings.container).offset().top;\n }\n\n return fold >= $(element).offset().top + settings.threshold + $(element).height();\n };\n\n $.leftofbegin = function(element, settings) {\n var fold;\n\n if (settings.container === undefined || settings.container === window) {\n fold = $window.scrollLeft();\n } else {\n fold = $(settings.container).offset().left;\n }\n\n return fold >= $(element).offset().left + settings.threshold + $(element).width();\n };\n\n $.inviewport = function(element, settings) {\n return !$.rightoffold(element, settings) && !$.leftofbegin(element, settings) &&\n !$.belowthefold(element, settings) && !$.abovethetop(element, settings);\n };\n\n /* Custom selectors for your convenience. */\n /* Use as $(\"img:below-the-fold\").something() or */\n /* $(\"img\").filter(\":below-the-fold\").something() which is faster */\n\n $.extend($.expr[\":\"], {\n \"below-the-fold\" : function(a) { return $.belowthefold(a, {threshold : 0}); },\n \"above-the-top\" : function(a) { return !$.belowthefold(a, {threshold : 0}); },\n \"right-of-screen\": function(a) { return $.rightoffold(a, {threshold : 0}); },\n \"left-of-screen\" : function(a) { return !$.rightoffold(a, {threshold : 0}); },\n \"in-viewport\" : function(a) { return $.inviewport(a, {threshold : 0}); },\n /* Maintain BC for couple of versions. */\n \"above-the-fold\" : function(a) { return !$.belowthefold(a, {threshold : 0}); },\n \"right-of-fold\" : function(a) { return $.rightoffold(a, {threshold : 0}); },\n \"left-of-fold\" : function(a) { return !$.rightoffold(a, {threshold : 0}); }\n });\n\n})(jQuery, window, document);\n","/*\n jQuery Masked Input Plugin\n Copyright (c) 2007 - 2015 Josh Bush (digitalbush.com)\n Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)\n Version: 1.4.1\n*/\n!function(factory) {\n \"function\" == typeof define && define.amd ? define([ \"jquery\" ], factory) : factory(\"object\" == typeof exports ? require(\"jquery\") : jQuery);\n}(function($) {\n var caretTimeoutId, ua = navigator.userAgent, iPhone = /iphone/i.test(ua), chrome = /chrome/i.test(ua), android = /android/i.test(ua);\n $.mask = {\n definitions: {\n \"9\": \"[0-9]\",\n a: \"[A-Za-z]\",\n \"*\": \"[A-Za-z0-9]\"\n },\n autoclear: !0,\n dataName: \"rawMaskFn\",\n placeholder: \"_\"\n }, $.fn.extend({\n caret: function(begin, end) {\n var range;\n if (0 !== this.length && !this.is(\":hidden\")) return \"number\" == typeof begin ? (end = \"number\" == typeof end ? end : begin, \n this.each(function() {\n this.setSelectionRange ? this.setSelectionRange(begin, end) : this.createTextRange && (range = this.createTextRange(), \n range.collapse(!0), range.moveEnd(\"character\", end), range.moveStart(\"character\", begin), \n range.select());\n })) : (this[0].setSelectionRange ? (begin = this[0].selectionStart, end = this[0].selectionEnd) : document.selection && document.selection.createRange && (range = document.selection.createRange(), \n begin = 0 - range.duplicate().moveStart(\"character\", -1e5), end = begin + range.text.length), \n {\n begin: begin,\n end: end\n });\n },\n unmask: function() {\n return this.trigger(\"unmask\");\n },\n mask: function(mask, settings) {\n var input, defs, tests, partialPosition, firstNonMaskPos, lastRequiredNonMaskPos, len, oldVal;\n if (!mask && this.length > 0) {\n input = $(this[0]);\n var fn = input.data($.mask.dataName);\n return fn ? fn() : void 0;\n }\n return settings = $.extend({\n autoclear: $.mask.autoclear,\n placeholder: $.mask.placeholder,\n completed: null\n }, settings), defs = $.mask.definitions, tests = [], partialPosition = len = mask.length, \n firstNonMaskPos = null, $.each(mask.split(\"\"), function(i, c) {\n \"?\" == c ? (len--, partialPosition = i) : defs[c] ? (tests.push(new RegExp(defs[c])), \n null === firstNonMaskPos && (firstNonMaskPos = tests.length - 1), partialPosition > i && (lastRequiredNonMaskPos = tests.length - 1)) : tests.push(null);\n }), this.trigger(\"unmask\").each(function() {\n function tryFireCompleted() {\n if (settings.completed) {\n for (var i = firstNonMaskPos; lastRequiredNonMaskPos >= i; i++) if (tests[i] && buffer[i] === getPlaceholder(i)) return;\n settings.completed.call(input);\n }\n }\n function getPlaceholder(i) {\n return settings.placeholder.charAt(i < settings.placeholder.length ? i : 0);\n }\n function seekNext(pos) {\n for (;++pos < len && !tests[pos]; ) ;\n return pos;\n }\n function seekPrev(pos) {\n for (;--pos >= 0 && !tests[pos]; ) ;\n return pos;\n }\n function shiftL(begin, end) {\n var i, j;\n if (!(0 > begin)) {\n for (i = begin, j = seekNext(end); len > i; i++) if (tests[i]) {\n if (!(len > j && tests[i].test(buffer[j]))) break;\n buffer[i] = buffer[j], buffer[j] = getPlaceholder(j), j = seekNext(j);\n }\n writeBuffer(), input.caret(Math.max(firstNonMaskPos, begin));\n }\n }\n function shiftR(pos) {\n var i, c, j, t;\n for (i = pos, c = getPlaceholder(pos); len > i; i++) if (tests[i]) {\n if (j = seekNext(i), t = buffer[i], buffer[i] = c, !(len > j && tests[j].test(t))) break;\n c = t;\n }\n }\n function androidInputEvent() {\n var curVal = input.val(), pos = input.caret();\n if (oldVal && oldVal.length && oldVal.length > curVal.length) {\n for (checkVal(!0); pos.begin > 0 && !tests[pos.begin - 1]; ) pos.begin--;\n if (0 === pos.begin) for (;pos.begin < firstNonMaskPos && !tests[pos.begin]; ) pos.begin++;\n input.caret(pos.begin, pos.begin);\n } else {\n for (checkVal(!0); pos.begin < len && !tests[pos.begin]; ) pos.begin++;\n input.caret(pos.begin, pos.begin);\n }\n tryFireCompleted();\n }\n function blurEvent() {\n checkVal(), input.val() != focusText && input.change();\n }\n function keydownEvent(e) {\n if (!input.prop(\"readonly\")) {\n var pos, begin, end, k = e.which || e.keyCode;\n oldVal = input.val(), 8 === k || 46 === k || iPhone && 127 === k ? (pos = input.caret(), \n begin = pos.begin, end = pos.end, end - begin === 0 && (begin = 46 !== k ? seekPrev(begin) : end = seekNext(begin - 1), \n end = 46 === k ? seekNext(end) : end), clearBuffer(begin, end), shiftL(begin, end - 1), \n e.preventDefault()) : 13 === k ? blurEvent.call(this, e) : 27 === k && (input.val(focusText), \n input.caret(0, checkVal()), e.preventDefault());\n }\n }\n function keypressEvent(e) {\n if (!input.prop(\"readonly\")) {\n var p, c, next, k = e.which || e.keyCode, pos = input.caret();\n if (!(e.ctrlKey || e.altKey || e.metaKey || 32 > k) && k && 13 !== k) {\n if (pos.end - pos.begin !== 0 && (clearBuffer(pos.begin, pos.end), shiftL(pos.begin, pos.end - 1)), \n p = seekNext(pos.begin - 1), len > p && (c = String.fromCharCode(k), tests[p].test(c))) {\n if (shiftR(p), buffer[p] = c, writeBuffer(), next = seekNext(p), android) {\n var proxy = function() {\n $.proxy($.fn.caret, input, next)();\n };\n setTimeout(proxy, 0);\n } else input.caret(next);\n pos.begin <= lastRequiredNonMaskPos && tryFireCompleted();\n }\n e.preventDefault();\n }\n }\n }\n function clearBuffer(start, end) {\n var i;\n for (i = start; end > i && len > i; i++) tests[i] && (buffer[i] = getPlaceholder(i));\n }\n function writeBuffer() {\n input.val(buffer.join(\"\"));\n }\n function checkVal(allow) {\n var i, c, pos, test = input.val(), lastMatch = -1;\n for (i = 0, pos = 0; len > i; i++) if (tests[i]) {\n for (buffer[i] = getPlaceholder(i); pos++ < test.length; ) if (c = test.charAt(pos - 1), \n tests[i].test(c)) {\n buffer[i] = c, lastMatch = i;\n break;\n }\n if (pos > test.length) {\n clearBuffer(i + 1, len);\n break;\n }\n } else buffer[i] === test.charAt(pos) && pos++, partialPosition > i && (lastMatch = i);\n return allow ? writeBuffer() : partialPosition > lastMatch + 1 ? settings.autoclear || buffer.join(\"\") === defaultBuffer ? (input.val() && input.val(\"\"), \n clearBuffer(0, len)) : writeBuffer() : (writeBuffer(), input.val(input.val().substring(0, lastMatch + 1))), \n partialPosition ? i : firstNonMaskPos;\n }\n var input = $(this), buffer = $.map(mask.split(\"\"), function(c, i) {\n return \"?\" != c ? defs[c] ? getPlaceholder(i) : c : void 0;\n }), defaultBuffer = buffer.join(\"\"), focusText = input.val();\n input.data($.mask.dataName, function() {\n return $.map(buffer, function(c, i) {\n return tests[i] && c != getPlaceholder(i) ? c : null;\n }).join(\"\");\n }), input.one(\"unmask\", function() {\n input.off(\".mask\").removeData($.mask.dataName);\n }).on(\"focus.mask\", function() {\n if (!input.prop(\"readonly\")) {\n clearTimeout(caretTimeoutId);\n var pos;\n focusText = input.val(), pos = checkVal(), caretTimeoutId = setTimeout(function() {\n input.get(0) === document.activeElement && (writeBuffer(), pos == mask.replace(\"?\", \"\").length ? input.caret(0, pos) : input.caret(pos));\n }, 10);\n }\n }).on(\"blur.mask\", blurEvent).on(\"keydown.mask\", keydownEvent).on(\"keypress.mask\", keypressEvent).on(\"input.mask paste.mask\", function() {\n input.prop(\"readonly\") || setTimeout(function() {\n var pos = checkVal(!0);\n input.caret(pos), tryFireCompleted();\n }, 0);\n }), chrome && android && input.off(\"input.mask\").on(\"input.mask\", androidInputEvent), \n checkVal();\n });\n }\n });\n});","/*\n * jQuery Mobile 1.4.0pre\n * Git HEAD hash: 856505571fd484976814d85280f26d139b752915 <> Date: Tue Jun 4 2013 20:00:33 UTC\n * http://jquerymobile.com\n *\n * Copyright 2010, 2013 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license.\n * http://jquery.org/license\n *\n */\n\n\n(function ( root, doc, factory ) {\n if ( typeof define === \"function\" && define.amd ) {\n // AMD. Register as an anonymous module.\n define( [ \"jquery\" ], function ( $ ) {\n factory( $, root, doc );\n return $.mobile;\n });\n } else {\n // Browser globals\n factory( root.jQuery, root, doc );\n }\n}( this, document, function ( jQuery, window, document, undefined ) {\n// This plugin is an experiment for abstracting away the touch and mouse\n// events so that developers don't have to worry about which method of input\n// the device their document is loaded on supports.\n//\n// The idea here is to allow the developer to register listeners for the\n// basic mouse events, such as mousedown, mousemove, mouseup, and click,\n// and the plugin will take care of registering the correct listeners\n// behind the scenes to invoke the listener at the fastest possible time\n// for that device, while still retaining the order of event firing in\n// the traditional mouse environment, should multiple handlers be registered\n// on the same element for different events.\n//\n// The current version exposes the following virtual events to jQuery bind methods:\n// \"vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel\"\n\n (function( $, window, document, undefined ) {\n\n var dataPropertyName = \"virtualMouseBindings\",\n touchTargetPropertyName = \"virtualTouchID\",\n virtualEventNames = \"vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel\".split( \" \" ),\n touchEventProps = \"clientX clientY pageX pageY screenX screenY\".split( \" \" ),\n mouseHookProps = $.event.mouseHooks ? $.event.mouseHooks.props : [],\n mouseEventProps = $.event.props.concat( mouseHookProps ),\n activeDocHandlers = {},\n resetTimerID = 0,\n startX = 0,\n startY = 0,\n didScroll = false,\n clickBlockList = [],\n blockMouseTriggers = false,\n blockTouchTriggers = false,\n eventCaptureSupported = \"addEventListener\" in document,\n $document = $( document ),\n nextTouchID = 1,\n lastTouchID = 0, threshold,\n i;\n\n $.vmouse = {\n moveDistanceThreshold: 10,\n clickDistanceThreshold: 10,\n resetTimerDuration: 1500\n };\n\n function getNativeEvent( event ) {\n\n while ( event && typeof event.originalEvent !== \"undefined\" ) {\n event = event.originalEvent;\n }\n return event;\n }\n\n function createVirtualEvent( event, eventType ) {\n\n var t = event.type,\n oe, props, ne, prop, ct, touch, i, j, len;\n\n event = $.Event( event );\n event.type = eventType;\n\n oe = event.originalEvent;\n props = $.event.props;\n\n // addresses separation of $.event.props in to $.event.mouseHook.props and Issue 3280\n // https://github.com/jquery/jquery-mobile/issues/3280\n if ( t.search( /^(mouse|click)/ ) > -1 ) {\n props = mouseEventProps;\n }\n\n // copy original event properties over to the new event\n // this would happen if we could call $.event.fix instead of $.Event\n // but we don't have a way to force an event to be fixed multiple times\n if ( oe ) {\n for ( i = props.length, prop; i; ) {\n prop = props[ --i ];\n event[ prop ] = oe[ prop ];\n }\n }\n\n // make sure that if the mouse and click virtual events are generated\n // without a .which one is defined\n if ( t.search(/mouse(down|up)|click/) > -1 && !event.which ) {\n event.which = 1;\n }\n\n if ( t.search(/^touch/) !== -1 ) {\n ne = getNativeEvent( oe );\n t = ne.touches;\n ct = ne.changedTouches;\n touch = ( t && t.length ) ? t[0] : ( ( ct && ct.length ) ? ct[ 0 ] : undefined );\n\n if ( touch ) {\n for ( j = 0, len = touchEventProps.length; j < len; j++) {\n prop = touchEventProps[ j ];\n event[ prop ] = touch[ prop ];\n }\n }\n }\n\n return event;\n }\n\n function getVirtualBindingFlags( element ) {\n\n var flags = {},\n b, k;\n\n while ( element ) {\n\n b = $.data( element, dataPropertyName );\n\n for ( k in b ) {\n if ( b[ k ] ) {\n flags[ k ] = flags.hasVirtualBinding = true;\n }\n }\n element = element.parentNode;\n }\n return flags;\n }\n\n function getClosestElementWithVirtualBinding( element, eventType ) {\n var b;\n while ( element ) {\n\n b = $.data( element, dataPropertyName );\n\n if ( b && ( !eventType || b[ eventType ] ) ) {\n return element;\n }\n element = element.parentNode;\n }\n return null;\n }\n\n function enableTouchBindings() {\n blockTouchTriggers = false;\n }\n\n function disableTouchBindings() {\n blockTouchTriggers = true;\n }\n\n function enableMouseBindings() {\n lastTouchID = 0;\n clickBlockList.length = 0;\n blockMouseTriggers = false;\n\n // When mouse bindings are enabled, our\n // touch bindings are disabled.\n disableTouchBindings();\n }\n\n function disableMouseBindings() {\n // When mouse bindings are disabled, our\n // touch bindings are enabled.\n enableTouchBindings();\n }\n\n function startResetTimer() {\n clearResetTimer();\n resetTimerID = setTimeout( function() {\n resetTimerID = 0;\n enableMouseBindings();\n }, $.vmouse.resetTimerDuration );\n }\n\n function clearResetTimer() {\n if ( resetTimerID ) {\n clearTimeout( resetTimerID );\n resetTimerID = 0;\n }\n }\n\n function triggerVirtualEvent( eventType, event, flags ) {\n var ve;\n\n if ( ( flags && flags[ eventType ] ) ||\n ( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) {\n\n ve = createVirtualEvent( event, eventType );\n\n $( event.target).trigger( ve );\n }\n\n return ve;\n }\n\n function mouseEventCallback( event ) {\n var touchID = $.data( event.target, touchTargetPropertyName ),\n ve;\n\n if ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ) {\n ve = triggerVirtualEvent( \"v\" + event.type, event );\n if ( ve ) {\n if ( ve.isDefaultPrevented() ) {\n event.preventDefault();\n }\n if ( ve.isPropagationStopped() ) {\n event.stopPropagation();\n }\n if ( ve.isImmediatePropagationStopped() ) {\n event.stopImmediatePropagation();\n }\n }\n }\n }\n\n function handleTouchStart( event ) {\n\n var touches = getNativeEvent( event ).touches,\n target, flags, t;\n\n if ( touches && touches.length === 1 ) {\n\n target = event.target;\n flags = getVirtualBindingFlags( target );\n\n if ( flags.hasVirtualBinding ) {\n\n lastTouchID = nextTouchID++;\n $.data( target, touchTargetPropertyName, lastTouchID );\n\n clearResetTimer();\n\n disableMouseBindings();\n didScroll = false;\n\n t = getNativeEvent( event ).touches[ 0 ];\n startX = t.pageX;\n startY = t.pageY;\n\n triggerVirtualEvent( \"vmouseover\", event, flags );\n triggerVirtualEvent( \"vmousedown\", event, flags );\n }\n }\n }\n\n function handleScroll( event ) {\n if ( blockTouchTriggers ) {\n return;\n }\n\n if ( !didScroll ) {\n triggerVirtualEvent( \"vmousecancel\", event, getVirtualBindingFlags( event.target ) );\n }\n\n didScroll = true;\n startResetTimer();\n }\n\n function handleTouchMove( event ) {\n if ( blockTouchTriggers ) {\n return;\n }\n\n var t = getNativeEvent( event ).touches[ 0 ],\n didCancel = didScroll,\n moveThreshold = $.vmouse.moveDistanceThreshold,\n flags = getVirtualBindingFlags( event.target );\n\n didScroll = didScroll ||\n ( Math.abs( t.pageX - startX ) > moveThreshold ||\n Math.abs( t.pageY - startY ) > moveThreshold );\n\n\n if ( didScroll && !didCancel ) {\n triggerVirtualEvent( \"vmousecancel\", event, flags );\n }\n\n triggerVirtualEvent( \"vmousemove\", event, flags );\n startResetTimer();\n }\n\n function handleTouchEnd( event ) {\n if ( blockTouchTriggers ) {\n return;\n }\n\n disableTouchBindings();\n\n var flags = getVirtualBindingFlags( event.target ),\n ve, t;\n triggerVirtualEvent( \"vmouseup\", event, flags );\n\n if ( !didScroll ) {\n ve = triggerVirtualEvent( \"vclick\", event, flags );\n if ( ve && ve.isDefaultPrevented() ) {\n // The target of the mouse events that follow the touchend\n // event don't necessarily match the target used during the\n // touch. This means we need to rely on coordinates for blocking\n // any click that is generated.\n t = getNativeEvent( event ).changedTouches[ 0 ];\n clickBlockList.push({\n touchID: lastTouchID,\n x: t.clientX,\n y: t.clientY\n });\n\n // Prevent any mouse events that follow from triggering\n // virtual event notifications.\n blockMouseTriggers = true;\n }\n }\n triggerVirtualEvent( \"vmouseout\", event, flags);\n didScroll = false;\n\n startResetTimer();\n }\n\n function hasVirtualBindings( ele ) {\n var bindings = $.data( ele, dataPropertyName ),\n k;\n\n if ( bindings ) {\n for ( k in bindings ) {\n if ( bindings[ k ] ) {\n return true;\n }\n }\n }\n return false;\n }\n\n function dummyMouseHandler() {}\n\n function getSpecialEventObject( eventType ) {\n var realType = eventType.substr( 1 );\n\n return {\n setup: function(/* data, namespace */) {\n // If this is the first virtual mouse binding for this element,\n // add a bindings object to its data.\n\n if ( !hasVirtualBindings( this ) ) {\n $.data( this, dataPropertyName, {} );\n }\n\n // If setup is called, we know it is the first binding for this\n // eventType, so initialize the count for the eventType to zero.\n var bindings = $.data( this, dataPropertyName );\n bindings[ eventType ] = true;\n\n // If this is the first virtual mouse event for this type,\n // register a global handler on the document.\n\n activeDocHandlers[ eventType ] = ( activeDocHandlers[ eventType ] || 0 ) + 1;\n\n if ( activeDocHandlers[ eventType ] === 1 ) {\n $document.bind( realType, mouseEventCallback );\n }\n\n // Some browsers, like Opera Mini, won't dispatch mouse/click events\n // for elements unless they actually have handlers registered on them.\n // To get around this, we register dummy handlers on the elements.\n\n $( this ).bind( realType, dummyMouseHandler );\n\n // For now, if event capture is not supported, we rely on mouse handlers.\n if ( eventCaptureSupported ) {\n // If this is the first virtual mouse binding for the document,\n // register our touchstart handler on the document.\n\n activeDocHandlers[ \"touchstart\" ] = ( activeDocHandlers[ \"touchstart\" ] || 0) + 1;\n\n if ( activeDocHandlers[ \"touchstart\" ] === 1 ) {\n $document.bind( \"touchstart\", handleTouchStart )\n .bind( \"touchend\", handleTouchEnd )\n\n // On touch platforms, touching the screen and then dragging your finger\n // causes the window content to scroll after some distance threshold is\n // exceeded. On these platforms, a scroll prevents a click event from being\n // dispatched, and on some platforms, even the touchend is suppressed. To\n // mimic the suppression of the click event, we need to watch for a scroll\n // event. Unfortunately, some platforms like iOS don't dispatch scroll\n // events until *AFTER* the user lifts their finger (touchend). This means\n // we need to watch both scroll and touchmove events to figure out whether\n // or not a scroll happenens before the touchend event is fired.\n\n .bind( \"touchmove\", handleTouchMove )\n .bind( \"scroll\", handleScroll );\n }\n }\n },\n\n teardown: function(/* data, namespace */) {\n // If this is the last virtual binding for this eventType,\n // remove its global handler from the document.\n\n --activeDocHandlers[ eventType ];\n\n if ( !activeDocHandlers[ eventType ] ) {\n $document.unbind( realType, mouseEventCallback );\n }\n\n if ( eventCaptureSupported ) {\n // If this is the last virtual mouse binding in existence,\n // remove our document touchstart listener.\n\n --activeDocHandlers[ \"touchstart\" ];\n\n if ( !activeDocHandlers[ \"touchstart\" ] ) {\n $document.unbind( \"touchstart\", handleTouchStart )\n .unbind( \"touchmove\", handleTouchMove )\n .unbind( \"touchend\", handleTouchEnd )\n .unbind( \"scroll\", handleScroll );\n }\n }\n\n var $this = $( this ),\n bindings = $.data( this, dataPropertyName );\n\n // teardown may be called when an element was\n // removed from the DOM. If this is the case,\n // jQuery core may have already stripped the element\n // of any data bindings so we need to check it before\n // using it.\n if ( bindings ) {\n bindings[ eventType ] = false;\n }\n\n // Unregister the dummy event handler.\n\n $this.unbind( realType, dummyMouseHandler );\n\n // If this is the last virtual mouse binding on the\n // element, remove the binding data from the element.\n\n if ( !hasVirtualBindings( this ) ) {\n $this.removeData( dataPropertyName );\n }\n }\n };\n }\n\n// Expose our custom events to the jQuery bind/unbind mechanism.\n\n for ( i = 0; i < virtualEventNames.length; i++ ) {\n $.event.special[ virtualEventNames[ i ] ] = getSpecialEventObject( virtualEventNames[ i ] );\n }\n\n// Add a capture click handler to block clicks.\n// Note that we require event capture support for this so if the device\n// doesn't support it, we punt for now and rely solely on mouse events.\n if ( eventCaptureSupported ) {\n document.addEventListener( \"click\", function( e ) {\n var cnt = clickBlockList.length,\n target = e.target,\n x, y, ele, i, o, touchID;\n\n if ( cnt ) {\n x = e.clientX;\n y = e.clientY;\n threshold = $.vmouse.clickDistanceThreshold;\n\n // The idea here is to run through the clickBlockList to see if\n // the current click event is in the proximity of one of our\n // vclick events that had preventDefault() called on it. If we find\n // one, then we block the click.\n //\n // Why do we have to rely on proximity?\n //\n // Because the target of the touch event that triggered the vclick\n // can be different from the target of the click event synthesized\n // by the browser. The target of a mouse/click event that is syntehsized\n // from a touch event seems to be implementation specific. For example,\n // some browsers will fire mouse/click events for a link that is near\n // a touch event, even though the target of the touchstart/touchend event\n // says the user touched outside the link. Also, it seems that with most\n // browsers, the target of the mouse/click event is not calculated until the\n // time it is dispatched, so if you replace an element that you touched\n // with another element, the target of the mouse/click will be the new\n // element underneath that point.\n //\n // Aside from proximity, we also check to see if the target and any\n // of its ancestors were the ones that blocked a click. This is necessary\n // because of the strange mouse/click target calculation done in the\n // Android 2.1 browser, where if you click on an element, and there is a\n // mouse/click handler on one of its ancestors, the target will be the\n // innermost child of the touched element, even if that child is no where\n // near the point of touch.\n\n ele = target;\n\n while ( ele ) {\n for ( i = 0; i < cnt; i++ ) {\n o = clickBlockList[ i ];\n touchID = 0;\n\n if ( ( ele === target && Math.abs( o.x - x ) < threshold && Math.abs( o.y - y ) < threshold ) ||\n $.data( ele, touchTargetPropertyName ) === o.touchID ) {\n // XXX: We may want to consider removing matches from the block list\n // instead of waiting for the reset timer to fire.\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n }\n ele = ele.parentNode;\n }\n }\n }, true);\n }\n })( jQuery, window, document );\n\n (function( $ ) {\n $.mobile = {};\n }( jQuery ));\n (function( $, undefined ) {\n var support = {\n touch: \"ontouchend\" in document\n };\n\n $.mobile.support = $.mobile.support || {};\n $.extend( $.support, support );\n $.extend( $.mobile.support, support );\n }( jQuery ));\n\n\n (function( $, window, undefined ) {\n var $document = $( document ),\n supportTouch = $.mobile.support.touch,\n scrollEvent = \"touchmove scroll\",\n touchStartEvent = supportTouch ? \"touchstart\" : \"mousedown\",\n touchStopEvent = supportTouch ? \"touchend\" : \"mouseup\",\n touchMoveEvent = supportTouch ? \"touchmove\" : \"mousemove\";\n\n // setup new event shortcuts\n $.each( ( \"touchstart touchmove touchend \" +\n \"tap taphold \" +\n \"swipe swipeleft swiperight \" +\n \"scrollstart scrollstop\" ).split( \" \" ), function( i, name ) {\n\n $.fn[ name ] = function( fn ) {\n return fn ? this.bind( name, fn ) : this.trigger( name );\n };\n\n // jQuery < 1.8\n if ( $.attrFn ) {\n $.attrFn[ name ] = true;\n }\n });\n\n function triggerCustomEvent( obj, eventType, event ) {\n var originalType = event.type;\n event.type = eventType;\n $.event.dispatch.call( obj, event );\n event.type = originalType;\n }\n\n // also handles scrollstop\n $.event.special.scrollstart = {\n\n enabled: true,\n setup: function() {\n\n var thisObject = this,\n $this = $( thisObject ),\n scrolling,\n timer;\n\n function trigger( event, state ) {\n scrolling = state;\n triggerCustomEvent( thisObject, scrolling ? \"scrollstart\" : \"scrollstop\", event );\n }\n\n // iPhone triggers scroll after a small delay; use touchmove instead\n $this.bind( scrollEvent, function( event ) {\n\n if ( !$.event.special.scrollstart.enabled ) {\n return;\n }\n\n if ( !scrolling ) {\n trigger( event, true );\n }\n\n clearTimeout( timer );\n timer = setTimeout( function() {\n trigger( event, false );\n }, 50 );\n });\n },\n teardown: function() {\n $( this ).unbind( scrollEvent );\n }\n };\n\n // also handles taphold\n $.event.special.tap = {\n tapholdThreshold: 750,\n emitTapOnTaphold: true,\n setup: function() {\n var thisObject = this,\n $this = $( thisObject ),\n isTaphold = false;\n\n $this.bind( \"vmousedown\", function( event ) {\n isTaphold = false;\n if ( event.which && event.which !== 1 ) {\n return false;\n }\n\n var origTarget = event.target,\n timer;\n\n function clearTapTimer() {\n clearTimeout( timer );\n }\n\n function clearTapHandlers() {\n clearTapTimer();\n\n $this.unbind( \"vclick\", clickHandler )\n .unbind( \"vmouseup\", clearTapTimer );\n $document.unbind( \"vmousecancel\", clearTapHandlers );\n }\n\n function clickHandler( event ) {\n clearTapHandlers();\n\n // ONLY trigger a 'tap' event if the start target is\n // the same as the stop target.\n if ( !isTaphold && origTarget === event.target ) {\n triggerCustomEvent( thisObject, \"tap\", event );\n } else if ( isTaphold ) {\n event.stopPropagation();\n }\n }\n\n $this.bind( \"vmouseup\", clearTapTimer )\n .bind( \"vclick\", clickHandler );\n $document.bind( \"vmousecancel\", clearTapHandlers );\n\n timer = setTimeout( function() {\n if( $.event.special.tap.emitTapOnTaphold ) {\n isTaphold = true;\n }\n triggerCustomEvent( thisObject, \"taphold\", $.Event( \"taphold\", { target: origTarget } ) );\n }, $.event.special.tap.tapholdThreshold );\n });\n },\n teardown: function() {\n $( this ).unbind( \"vmousedown\" ).unbind( \"vclick\" ).unbind( \"vmouseup\" );\n $document.unbind( \"vmousecancel\" );\n }\n };\n\n // also handles swipeleft, swiperight\n $.event.special.swipe = {\n scrollSupressionThreshold: 30, // More than this horizontal displacement, and we will suppress scrolling.\n\n durationThreshold: 1000, // More time than this, and it isn't a swipe.\n\n horizontalDistanceThreshold: 30, // Swipe horizontal displacement must be more than this.\n\n verticalDistanceThreshold: 75, // Swipe vertical displacement must be less than this.\n\n start: function( event ) {\n var data = event.originalEvent.touches ?\n event.originalEvent.touches[ 0 ] : event;\n return {\n time: ( new Date() ).getTime(),\n coords: [ data.pageX, data.pageY ],\n origin: $( event.target )\n };\n },\n\n stop: function( event ) {\n var data = event.originalEvent.touches ?\n event.originalEvent.touches[ 0 ] : event;\n return {\n time: ( new Date() ).getTime(),\n coords: [ data.pageX, data.pageY ]\n };\n },\n\n handleSwipe: function( start, stop, thisObject, origTarget ) {\n if ( stop.time - start.time < $.event.special.swipe.durationThreshold &&\n Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold &&\n Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) {\n var direction = start.coords[0] > stop.coords[ 0 ] ? \"swipeleft\" : \"swiperight\";\n\n triggerCustomEvent( thisObject, \"swipe\", $.Event( \"swipe\", { target: origTarget }) );\n triggerCustomEvent( thisObject, direction,$.Event( direction, { target: origTarget } ) );\n }\n },\n\n setup: function() {\n var thisObject = this,\n $this = $( thisObject );\n\n $this.bind( touchStartEvent, function( event ) {\n var stop,\n start = $.event.special.swipe.start( event ),\n origTarget = event.target;\n\n function moveHandler( event ) {\n if ( !start ) {\n return;\n }\n\n stop = $.event.special.swipe.stop( event );\n\n // prevent scrolling\n if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) {\n event.preventDefault();\n }\n }\n\n $this.bind( touchMoveEvent, moveHandler )\n .one( touchStopEvent, function() {\n $this.unbind( touchMoveEvent, moveHandler );\n\n if ( start && stop ) {\n $.event.special.swipe.handleSwipe( start, stop, thisObject, origTarget );\n }\n start = stop = undefined;\n });\n });\n },\n\n teardown: function() {\n $( this ).unbind( touchStartEvent ).unbind( touchMoveEvent ).unbind( touchStopEvent );\n }\n };\n $.each({\n scrollstop: \"scrollstart\",\n taphold: \"tap\",\n swipeleft: \"swipe\",\n swiperight: \"swipe\"\n }, function( event, sourceEvent ) {\n\n $.event.special[ event ] = {\n setup: function() {\n $( this ).bind( sourceEvent, $.noop );\n },\n teardown: function() {\n $( this ).unbind( sourceEvent );\n }\n };\n });\n\n })( jQuery, this );\n\n}));\n","/*!\n * jQuery.scrollTo\n * Copyright (c) 2007 Ariel Flesler - aflesler ○ gmail • com | https://github.com/flesler\n * Licensed under MIT\n * https://github.com/flesler/jquery.scrollTo\n * @projectDescription Lightweight, cross-browser and highly customizable animated scrolling with jQuery\n * @author Ariel Flesler\n * @version 2.1.2\n */\n;(function(factory) {\n 'use strict';\n if (typeof define === 'function' && define.amd) {\n // AMD\n define(['jquery'], factory);\n } else if (typeof module !== 'undefined' && module.exports) {\n // CommonJS\n module.exports = factory(require('jquery'));\n } else {\n // Global\n factory(jQuery);\n }\n})(function($) {\n 'use strict';\n\n var $scrollTo = $.scrollTo = function(target, duration, settings) {\n return $(window).scrollTo(target, duration, settings);\n };\n\n $scrollTo.defaults = {\n axis:'xy',\n duration: 0,\n limit:true\n };\n\n function isWin(elem) {\n return !elem.nodeName ||\n $.inArray(elem.nodeName.toLowerCase(), ['iframe','#document','html','body']) !== -1;\n }\n\n $.fn.scrollTo = function(target, duration, settings) {\n if (typeof duration === 'object') {\n settings = duration;\n duration = 0;\n }\n if (typeof settings === 'function') {\n settings = { onAfter:settings };\n }\n if (target === 'max') {\n target = 9e9;\n }\n\n settings = $.extend({}, $scrollTo.defaults, settings);\n // Speed is still recognized for backwards compatibility\n duration = duration || settings.duration;\n // Make sure the settings are given right\n var queue = settings.queue && settings.axis.length > 1;\n if (queue) {\n // Let's keep the overall duration\n duration /= 2;\n }\n settings.offset = both(settings.offset);\n settings.over = both(settings.over);\n\n return this.each(function() {\n // Null target yields nothing, just like jQuery does\n if (target === null) return;\n\n var win = isWin(this),\n elem = win ? this.contentWindow || window : this,\n $elem = $(elem),\n targ = target,\n attr = {},\n toff;\n\n switch (typeof targ) {\n // A number will pass the regex\n case 'number':\n case 'string':\n if (/^([+-]=?)?\\d+(\\.\\d+)?(px|%)?$/.test(targ)) {\n targ = both(targ);\n // We are done\n break;\n }\n // Relative/Absolute selector\n targ = win ? $(targ) : $(targ, elem);\n\t\t\t\t/* falls through */\n case 'object':\n if (targ.length === 0) return;\n // DOMElement / jQuery\n if (targ.is || targ.style) {\n // Get the real position of the target\n toff = (targ = $(targ)).offset();\n }\n }\n\n var offset = $.isFunction(settings.offset) && settings.offset(elem, targ) || settings.offset;\n\n $.each(settings.axis.split(''), function(i, axis) {\n var Pos\t= axis === 'x' ? 'Left' : 'Top',\n pos = Pos.toLowerCase(),\n key = 'scroll' + Pos,\n prev = $elem[key](),\n max = $scrollTo.max(elem, axis);\n\n if (toff) {// jQuery / DOMElement\n attr[key] = toff[pos] + (win ? 0 : prev - $elem.offset()[pos]);\n\n // If it's a dom element, reduce the margin\n if (settings.margin) {\n attr[key] -= parseInt(targ.css('margin'+Pos), 10) || 0;\n attr[key] -= parseInt(targ.css('border'+Pos+'Width'), 10) || 0;\n }\n\n attr[key] += offset[pos] || 0;\n\n if (settings.over[pos]) {\n // Scroll to a fraction of its width/height\n attr[key] += targ[axis === 'x'?'width':'height']() * settings.over[pos];\n }\n } else {\n var val = targ[pos];\n // Handle percentage values\n attr[key] = val.slice && val.slice(-1) === '%' ?\n parseFloat(val) / 100 * max\n : val;\n }\n\n // Number or 'number'\n if (settings.limit && /^\\d+$/.test(attr[key])) {\n // Check the limits\n attr[key] = attr[key] <= 0 ? 0 : Math.min(attr[key], max);\n }\n\n // Don't waste time animating, if there's no need.\n if (!i && settings.axis.length > 1) {\n if (prev === attr[key]) {\n // No animation needed\n attr = {};\n } else if (queue) {\n // Intermediate animation\n animate(settings.onAfterFirst);\n // Don't animate this axis again in the next iteration.\n attr = {};\n }\n }\n });\n\n animate(settings.onAfter);\n\n function animate(callback) {\n var opts = $.extend({}, settings, {\n // The queue setting conflicts with animate()\n // Force it to always be true\n queue: true,\n duration: duration,\n complete: callback && function() {\n callback.call(elem, targ, settings);\n }\n });\n $elem.animate(attr, opts);\n }\n });\n };\n\n // Max scrolling position, works on quirks mode\n // It only fails (not too badly) on IE, quirks mode.\n $scrollTo.max = function(elem, axis) {\n var Dim = axis === 'x' ? 'Width' : 'Height',\n scroll = 'scroll'+Dim;\n\n if (!isWin(elem))\n return elem[scroll] - $(elem)[Dim.toLowerCase()]();\n\n var size = 'client' + Dim,\n doc = elem.ownerDocument || elem.document,\n html = doc.documentElement,\n body = doc.body;\n\n return Math.max(html[scroll], body[scroll]) - Math.min(html[size], body[size]);\n };\n\n function both(val) {\n return $.isFunction(val) || $.isPlainObject(val) ? val : { top:val, left:val };\n }\n\n // Add special hooks so that window scroll properties can be animated\n $.Tween.propHooks.scrollLeft =\n $.Tween.propHooks.scrollTop = {\n get: function(t) {\n return $(t.elem)[t.prop]();\n },\n set: function(t) {\n var curr = this.get(t);\n // If interrupt is true and user scrolled, stop animating\n if (t.options.interrupt && t._last && t._last !== curr) {\n return $(t.elem).stop();\n }\n var next = Math.round(t.now);\n // Don't waste CPU\n // Browsers don't render floating point scroll\n if (curr !== next) {\n $(t.elem)[t.prop](next);\n t._last = this.get(t);\n }\n }\n };\n\n // AMD requirement\n return $scrollTo;\n});","/*! Copyright (c) 2011 by Jonas Mosbech - https://github.com/jmosbech/StickyTableHeaders\n MIT license info: https://github.com/jmosbech/StickyTableHeaders/blob/master/license.txt */\n\n;(function ($, window, undefined) {\n 'use strict';\n\n var name = 'stickyTableHeaders',\n id = 0,\n defaults = {\n fixedOffset: 0,\n leftOffset: 0,\n scrollableArea: window\n };\n\n function Plugin (el, options) {\n // To avoid scope issues, use 'base' instead of 'this'\n // to reference this class from internal events and functions.\n var base = this;\n\n // Access to jQuery and DOM versions of element\n base.$el = $(el);\n base.el = el;\n base.id = id++;\n base.$window = $(window);\n base.$document = $(document);\n\n // Listen for destroyed, call teardown\n base.$el.bind('destroyed',\n $.proxy(base.teardown, base));\n\n // Cache DOM refs for performance reasons\n base.$clonedHeader = null;\n base.$originalHeader = null;\n\n // Keep track of state\n base.isSticky = false;\n base.hasBeenSticky = false;\n base.leftOffset = null;\n base.topOffset = null;\n\n base.init = function () {\n base.$el.each(function () {\n var $this = $(this);\n\n // remove padding on to fix issue #7\n $this.css('padding', 0);\n\n base.$originalHeader = $('thead:first', this);\n base.$clonedHeader = base.$originalHeader.clone();\n $this.trigger('clonedHeader.' + name, [base.$clonedHeader]);\n\n base.$clonedHeader.addClass('tableFloatingHeader');\n base.$clonedHeader.css('display', 'none');\n\n base.$originalHeader.addClass('tableFloatingHeaderOriginal');\n\n base.$originalHeader.after(base.$clonedHeader);\n\n base.$printStyle = $('');\n $('head').append(base.$printStyle);\n });\n\n base.setOptions(options);\n base.updateWidth();\n base.toggleHeaders();\n base.bind();\n };\n\n base.destroy = function (){\n base.$el.unbind('destroyed', base.teardown);\n base.teardown();\n };\n\n base.teardown = function(){\n if (base.isSticky) {\n base.$originalHeader.css('position', 'static');\n }\n $.removeData(base.el, 'plugin_' + name);\n base.unbind();\n\n base.$clonedHeader.remove();\n base.$originalHeader.removeClass('tableFloatingHeaderOriginal');\n base.$originalHeader.css('visibility', 'visible');\n base.$printStyle.remove();\n\n base.el = null;\n base.$el = null;\n };\n\n base.bind = function(){\n base.$scrollableArea.on('scroll.' + name, base.toggleHeaders);\n if (!base.isWindowScrolling) {\n base.$window.on('scroll.' + name + base.id, base.setPositionValues);\n base.$window.on('resize.' + name + base.id, base.toggleHeaders);\n }\n base.$scrollableArea.on('resize.' + name, base.toggleHeaders);\n base.$scrollableArea.on('resize.' + name, base.updateWidth);\n };\n\n base.unbind = function(){\n // unbind window events by specifying handle so we don't remove too much\n base.$scrollableArea.off('.' + name, base.toggleHeaders);\n if (!base.isWindowScrolling) {\n base.$window.off('.' + name + base.id, base.setPositionValues);\n base.$window.off('.' + name + base.id, base.toggleHeaders);\n }\n base.$scrollableArea.off('.' + name, base.updateWidth);\n base.$el.off('.' + name);\n base.$el.find('*').off('.' + name);\n };\n\n base.toggleHeaders = function () {\n if (base.$el) {\n base.$el.each(function () {\n var $this = $(this),\n newLeft,\n newTopOffset = base.isWindowScrolling ? (\n isNaN(base.options.fixedOffset) ?\n base.options.fixedOffset.outerHeight() :\n base.options.fixedOffset\n ) :\n base.$scrollableArea.offset().top + (!isNaN(base.options.fixedOffset) ? base.options.fixedOffset : 0),\n offset = $this.offset(),\n\n scrollTop = base.$scrollableArea.scrollTop() + newTopOffset,\n scrollLeft = base.$scrollableArea.scrollLeft(),\n\n scrolledPastTop = base.isWindowScrolling ?\n scrollTop > offset.top :\n newTopOffset > offset.top,\n notScrolledPastBottom = (base.isWindowScrolling ? scrollTop : 0) <\n (offset.top + $this.height() - base.$clonedHeader.height() - (base.isWindowScrolling ? 0 : newTopOffset));\n\n if (scrolledPastTop && notScrolledPastBottom) {\n newLeft = offset.left - scrollLeft + base.options.leftOffset;\n base.$originalHeader.css({\n 'position': 'fixed',\n 'margin-top': 0,\n 'left': newLeft,\n 'z-index': 1 // #18: opacity bug\n });\n base.leftOffset = newLeft;\n base.topOffset = newTopOffset;\n base.$clonedHeader.css('display', '');\n if (!base.isSticky) {\n base.isSticky = true;\n // make sure the width is correct: the user might have resized the browser while in static mode\n base.updateWidth();\n base.$el.addClass('stickyTableFloating');\n }\n base.setPositionValues();\n } else if (base.isSticky) {\n base.$originalHeader.css('position', 'static');\n base.$clonedHeader.css('display', 'none');\n base.isSticky = false;\n base.$el.removeClass('stickyTableFloating');\n base.resetWidth($('td,th', base.$clonedHeader), $('td,th', base.$originalHeader));\n }\n });\n }\n };\n\n base.setPositionValues = function () {\n var winScrollTop = base.$window.scrollTop(),\n winScrollLeft = base.$window.scrollLeft();\n if (!base.isSticky ||\n winScrollTop < 0 || winScrollTop + base.$window.height() > base.$document.height() ||\n winScrollLeft < 0 || winScrollLeft + base.$window.width() > base.$document.width()) {\n return;\n }\n base.$originalHeader.css({\n 'top': base.topOffset - (base.isWindowScrolling ? 0 : winScrollTop),\n 'left': base.leftOffset - (base.isWindowScrolling ? 0 : winScrollLeft)\n });\n };\n\n base.updateWidth = function () {\n if (!base.isSticky) {\n return;\n }\n // Copy cell widths from clone\n if (!base.$originalHeaderCells) {\n base.$originalHeaderCells = $('th,td', base.$originalHeader);\n }\n if (!base.$clonedHeaderCells) {\n base.$clonedHeaderCells = $('th,td', base.$clonedHeader);\n }\n var cellWidths = base.getWidth(base.$clonedHeaderCells);\n base.setWidth(cellWidths, base.$clonedHeaderCells, base.$originalHeaderCells);\n\n // Copy row width from whole table\n base.$originalHeader.css('width', base.$clonedHeader.width());\n };\n\n base.getWidth = function ($clonedHeaders) {\n var widths = [];\n $clonedHeaders.each(function (index) {\n var width, $this = $(this);\n\n if ($this.css('box-sizing') === 'border-box') {\n width = $this.outerWidth(); // #39: border-box bug\n } else {\n var $origTh = $('th', base.$originalHeader);\n if ($origTh.css('border-collapse') === 'collapse') {\n if (window.getComputedStyle) {\n width = parseFloat(window.getComputedStyle(this, null).width);\n } else {\n // ie8 only\n var leftPadding = parseFloat($this.css('padding-left'));\n var rightPadding = parseFloat($this.css('padding-right'));\n // Needs more investigation - this is assuming constant border around this cell and it's neighbours.\n var border = parseFloat($this.css('border-width'));\n width = $this.outerWidth() - leftPadding - rightPadding - border;\n }\n } else {\n width = $this.width();\n }\n }\n\n widths[index] = width;\n });\n return widths;\n };\n\n base.setWidth = function (widths, $clonedHeaders, $origHeaders) {\n $clonedHeaders.each(function (index) {\n var width = widths[index];\n $origHeaders.eq(index).css({\n 'min-width': width,\n 'max-width': width\n });\n });\n };\n\n base.resetWidth = function ($clonedHeaders, $origHeaders) {\n $clonedHeaders.each(function (index) {\n var $this = $(this);\n $origHeaders.eq(index).css({\n 'min-width': $this.css('min-width'),\n 'max-width': $this.css('max-width')\n });\n });\n };\n\n base.setOptions = function (options) {\n base.options = $.extend({}, defaults, options);\n base.$scrollableArea = $(base.options.scrollableArea);\n base.isWindowScrolling = base.$scrollableArea[0] === window;\n };\n\n base.updateOptions = function (options) {\n base.setOptions(options);\n // scrollableArea might have changed\n base.unbind();\n base.bind();\n base.updateWidth();\n base.toggleHeaders();\n };\n\n // Run initializer\n base.init();\n }\n\n // A plugin wrapper around the constructor,\n // preventing against multiple instantiations\n $.fn[name] = function ( options ) {\n return this.each(function () {\n var instance = $.data(this, 'plugin_' + name);\n if (instance) {\n if (typeof options === 'string') {\n instance[options].apply(instance);\n } else {\n instance.updateOptions(options);\n }\n } else if(options !== 'destroy') {\n $.data(this, 'plugin_' + name, new Plugin( this, options ));\n }\n });\n };\n\n})(jQuery, window);","// Underscore.js 1.5.2\n// http://underscorejs.org\n// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n// Underscore may be freely distributed under the MIT license.\n\n(function() {\n\n // Baseline setup\n // --------------\n\n // Establish the root object, `window` in the browser, or `exports` on the server.\n var root = this;\n\n // Save the previous value of the `_` variable.\n var previousUnderscore = root._;\n\n // Establish the object that gets returned to break out of a loop iteration.\n var breaker = {};\n\n // Save bytes in the minified (but not gzipped) version:\n var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;\n\n // Create quick reference variables for speed access to core prototypes.\n var\n push = ArrayProto.push,\n slice = ArrayProto.slice,\n concat = ArrayProto.concat,\n toString = ObjProto.toString,\n hasOwnProperty = ObjProto.hasOwnProperty;\n\n // All **ECMAScript 5** native function implementations that we hope to use\n // are declared here.\n var\n nativeForEach = ArrayProto.forEach,\n nativeMap = ArrayProto.map,\n nativeReduce = ArrayProto.reduce,\n nativeReduceRight = ArrayProto.reduceRight,\n nativeFilter = ArrayProto.filter,\n nativeEvery = ArrayProto.every,\n nativeSome = ArrayProto.some,\n nativeIndexOf = ArrayProto.indexOf,\n nativeLastIndexOf = ArrayProto.lastIndexOf,\n nativeIsArray = Array.isArray,\n nativeKeys = Object.keys,\n nativeBind = FuncProto.bind;\n\n // Create a safe reference to the Underscore object for use below.\n var _ = function(obj) {\n if (obj instanceof _) return obj;\n if (!(this instanceof _)) return new _(obj);\n this._wrapped = obj;\n };\n\n // Export the Underscore object for **Node.js**, with\n // backwards-compatibility for the old `require()` API. If we're in\n // the browser, add `_` as a global object via a string identifier,\n // for Closure Compiler \"advanced\" mode.\n if (typeof exports !== 'undefined') {\n if (typeof module !== 'undefined' && module.exports) {\n exports = module.exports = _;\n }\n exports._ = _;\n } else {\n root._ = _;\n }\n\n // Current version.\n _.VERSION = '1.5.2';\n\n // Collection Functions\n // --------------------\n\n // The cornerstone, an `each` implementation, aka `forEach`.\n // Handles objects with the built-in `forEach`, arrays, and raw objects.\n // Delegates to **ECMAScript 5**'s native `forEach` if available.\n var each = _.each = _.forEach = function(obj, iterator, context) {\n if (obj == null) return;\n if (nativeForEach && obj.forEach === nativeForEach) {\n obj.forEach(iterator, context);\n } else if (obj.length === +obj.length) {\n for (var i = 0, length = obj.length; i < length; i++) {\n if (iterator.call(context, obj[i], i, obj) === breaker) return;\n }\n } else {\n var keys = _.keys(obj);\n for (var i = 0, length = keys.length; i < length; i++) {\n if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;\n }\n }\n };\n\n // Return the results of applying the iterator to each element.\n // Delegates to **ECMAScript 5**'s native `map` if available.\n _.map = _.collect = function(obj, iterator, context) {\n var results = [];\n if (obj == null) return results;\n if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);\n each(obj, function(value, index, list) {\n results.push(iterator.call(context, value, index, list));\n });\n return results;\n };\n\n var reduceError = 'Reduce of empty array with no initial value';\n\n // **Reduce** builds up a single result from a list of values, aka `inject`,\n // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.\n _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {\n var initial = arguments.length > 2;\n if (obj == null) obj = [];\n if (nativeReduce && obj.reduce === nativeReduce) {\n if (context) iterator = _.bind(iterator, context);\n return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);\n }\n each(obj, function(value, index, list) {\n if (!initial) {\n memo = value;\n initial = true;\n } else {\n memo = iterator.call(context, memo, value, index, list);\n }\n });\n if (!initial) throw new TypeError(reduceError);\n return memo;\n };\n\n // The right-associative version of reduce, also known as `foldr`.\n // Delegates to **ECMAScript 5**'s native `reduceRight` if available.\n _.reduceRight = _.foldr = function(obj, iterator, memo, context) {\n var initial = arguments.length > 2;\n if (obj == null) obj = [];\n if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {\n if (context) iterator = _.bind(iterator, context);\n return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);\n }\n var length = obj.length;\n if (length !== +length) {\n var keys = _.keys(obj);\n length = keys.length;\n }\n each(obj, function(value, index, list) {\n index = keys ? keys[--length] : --length;\n if (!initial) {\n memo = obj[index];\n initial = true;\n } else {\n memo = iterator.call(context, memo, obj[index], index, list);\n }\n });\n if (!initial) throw new TypeError(reduceError);\n return memo;\n };\n\n // Return the first value which passes a truth test. Aliased as `detect`.\n _.find = _.detect = function(obj, iterator, context) {\n var result;\n any(obj, function(value, index, list) {\n if (iterator.call(context, value, index, list)) {\n result = value;\n return true;\n }\n });\n return result;\n };\n\n // Return all the elements that pass a truth test.\n // Delegates to **ECMAScript 5**'s native `filter` if available.\n // Aliased as `select`.\n _.filter = _.select = function(obj, iterator, context) {\n var results = [];\n if (obj == null) return results;\n if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);\n each(obj, function(value, index, list) {\n if (iterator.call(context, value, index, list)) results.push(value);\n });\n return results;\n };\n\n // Return all the elements for which a truth test fails.\n _.reject = function(obj, iterator, context) {\n return _.filter(obj, function(value, index, list) {\n return !iterator.call(context, value, index, list);\n }, context);\n };\n\n // Determine whether all of the elements match a truth test.\n // Delegates to **ECMAScript 5**'s native `every` if available.\n // Aliased as `all`.\n _.every = _.all = function(obj, iterator, context) {\n iterator || (iterator = _.identity);\n var result = true;\n if (obj == null) return result;\n if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);\n each(obj, function(value, index, list) {\n if (!(result = result && iterator.call(context, value, index, list))) return breaker;\n });\n return !!result;\n };\n\n // Determine if at least one element in the object matches a truth test.\n // Delegates to **ECMAScript 5**'s native `some` if available.\n // Aliased as `any`.\n var any = _.some = _.any = function(obj, iterator, context) {\n iterator || (iterator = _.identity);\n var result = false;\n if (obj == null) return result;\n if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);\n each(obj, function(value, index, list) {\n if (result || (result = iterator.call(context, value, index, list))) return breaker;\n });\n return !!result;\n };\n\n // Determine if the array or object contains a given value (using `===`).\n // Aliased as `include`.\n _.contains = _.include = function(obj, target) {\n if (obj == null) return false;\n if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;\n return any(obj, function(value) {\n return value === target;\n });\n };\n\n // Invoke a method (with arguments) on every item in a collection.\n _.invoke = function(obj, method) {\n var args = slice.call(arguments, 2);\n var isFunc = _.isFunction(method);\n return _.map(obj, function(value) {\n return (isFunc ? method : value[method]).apply(value, args);\n });\n };\n\n // Convenience version of a common use case of `map`: fetching a property.\n _.pluck = function(obj, key) {\n return _.map(obj, function(value){ return value[key]; });\n };\n\n // Convenience version of a common use case of `filter`: selecting only objects\n // containing specific `key:value` pairs.\n _.where = function(obj, attrs, first) {\n if (_.isEmpty(attrs)) return first ? void 0 : [];\n return _[first ? 'find' : 'filter'](obj, function(value) {\n for (var key in attrs) {\n if (attrs[key] !== value[key]) return false;\n }\n return true;\n });\n };\n\n // Convenience version of a common use case of `find`: getting the first object\n // containing specific `key:value` pairs.\n _.findWhere = function(obj, attrs) {\n return _.where(obj, attrs, true);\n };\n\n // Return the maximum element or (element-based computation).\n // Can't optimize arrays of integers longer than 65,535 elements.\n // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797)\n _.max = function(obj, iterator, context) {\n if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {\n return Math.max.apply(Math, obj);\n }\n if (!iterator && _.isEmpty(obj)) return -Infinity;\n var result = {computed : -Infinity, value: -Infinity};\n each(obj, function(value, index, list) {\n var computed = iterator ? iterator.call(context, value, index, list) : value;\n computed > result.computed && (result = {value : value, computed : computed});\n });\n return result.value;\n };\n\n // Return the minimum element (or element-based computation).\n _.min = function(obj, iterator, context) {\n if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {\n return Math.min.apply(Math, obj);\n }\n if (!iterator && _.isEmpty(obj)) return Infinity;\n var result = {computed : Infinity, value: Infinity};\n each(obj, function(value, index, list) {\n var computed = iterator ? iterator.call(context, value, index, list) : value;\n computed < result.computed && (result = {value : value, computed : computed});\n });\n return result.value;\n };\n\n // Shuffle an array, using the modern version of the\n // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).\n _.shuffle = function(obj) {\n var rand;\n var index = 0;\n var shuffled = [];\n each(obj, function(value) {\n rand = _.random(index++);\n shuffled[index - 1] = shuffled[rand];\n shuffled[rand] = value;\n });\n return shuffled;\n };\n\n // Sample **n** random values from an array.\n // If **n** is not specified, returns a single random element from the array.\n // The internal `guard` argument allows it to work with `map`.\n _.sample = function(obj, n, guard) {\n if (arguments.length < 2 || guard) {\n return obj[_.random(obj.length - 1)];\n }\n return _.shuffle(obj).slice(0, Math.max(0, n));\n };\n\n // An internal function to generate lookup iterators.\n var lookupIterator = function(value) {\n return _.isFunction(value) ? value : function(obj){ return obj[value]; };\n };\n\n // Sort the object's values by a criterion produced by an iterator.\n _.sortBy = function(obj, value, context) {\n var iterator = lookupIterator(value);\n return _.pluck(_.map(obj, function(value, index, list) {\n return {\n value: value,\n index: index,\n criteria: iterator.call(context, value, index, list)\n };\n }).sort(function(left, right) {\n var a = left.criteria;\n var b = right.criteria;\n if (a !== b) {\n if (a > b || a === void 0) return 1;\n if (a < b || b === void 0) return -1;\n }\n return left.index - right.index;\n }), 'value');\n };\n\n // An internal function used for aggregate \"group by\" operations.\n var group = function(behavior) {\n return function(obj, value, context) {\n var result = {};\n var iterator = value == null ? _.identity : lookupIterator(value);\n each(obj, function(value, index) {\n var key = iterator.call(context, value, index, obj);\n behavior(result, key, value);\n });\n return result;\n };\n };\n\n // Groups the object's values by a criterion. Pass either a string attribute\n // to group by, or a function that returns the criterion.\n _.groupBy = group(function(result, key, value) {\n (_.has(result, key) ? result[key] : (result[key] = [])).push(value);\n });\n\n // Indexes the object's values by a criterion, similar to `groupBy`, but for\n // when you know that your index values will be unique.\n _.indexBy = group(function(result, key, value) {\n result[key] = value;\n });\n\n // Counts instances of an object that group by a certain criterion. Pass\n // either a string attribute to count by, or a function that returns the\n // criterion.\n _.countBy = group(function(result, key) {\n _.has(result, key) ? result[key]++ : result[key] = 1;\n });\n\n // Use a comparator function to figure out the smallest index at which\n // an object should be inserted so as to maintain order. Uses binary search.\n _.sortedIndex = function(array, obj, iterator, context) {\n iterator = iterator == null ? _.identity : lookupIterator(iterator);\n var value = iterator.call(context, obj);\n var low = 0, high = array.length;\n while (low < high) {\n var mid = (low + high) >>> 1;\n iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;\n }\n return low;\n };\n\n // Safely create a real, live array from anything iterable.\n _.toArray = function(obj) {\n if (!obj) return [];\n if (_.isArray(obj)) return slice.call(obj);\n if (obj.length === +obj.length) return _.map(obj, _.identity);\n return _.values(obj);\n };\n\n // Return the number of elements in an object.\n _.size = function(obj) {\n if (obj == null) return 0;\n return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;\n };\n\n // Array Functions\n // ---------------\n\n // Get the first element of an array. Passing **n** will return the first N\n // values in the array. Aliased as `head` and `take`. The **guard** check\n // allows it to work with `_.map`.\n _.first = _.head = _.take = function(array, n, guard) {\n if (array == null) return void 0;\n return (n == null) || guard ? array[0] : slice.call(array, 0, n);\n };\n\n // Returns everything but the last entry of the array. Especially useful on\n // the arguments object. Passing **n** will return all the values in\n // the array, excluding the last N. The **guard** check allows it to work with\n // `_.map`.\n _.initial = function(array, n, guard) {\n return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));\n };\n\n // Get the last element of an array. Passing **n** will return the last N\n // values in the array. The **guard** check allows it to work with `_.map`.\n _.last = function(array, n, guard) {\n if (array == null) return void 0;\n if ((n == null) || guard) {\n return array[array.length - 1];\n } else {\n return slice.call(array, Math.max(array.length - n, 0));\n }\n };\n\n // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.\n // Especially useful on the arguments object. Passing an **n** will return\n // the rest N values in the array. The **guard**\n // check allows it to work with `_.map`.\n _.rest = _.tail = _.drop = function(array, n, guard) {\n return slice.call(array, (n == null) || guard ? 1 : n);\n };\n\n // Trim out all falsy values from an array.\n _.compact = function(array) {\n return _.filter(array, _.identity);\n };\n\n // Internal implementation of a recursive `flatten` function.\n var flatten = function(input, shallow, output) {\n if (shallow && _.every(input, _.isArray)) {\n return concat.apply(output, input);\n }\n each(input, function(value) {\n if (_.isArray(value) || _.isArguments(value)) {\n shallow ? push.apply(output, value) : flatten(value, shallow, output);\n } else {\n output.push(value);\n }\n });\n return output;\n };\n\n // Flatten out an array, either recursively (by default), or just one level.\n _.flatten = function(array, shallow) {\n return flatten(array, shallow, []);\n };\n\n // Return a version of the array that does not contain the specified value(s).\n _.without = function(array) {\n return _.difference(array, slice.call(arguments, 1));\n };\n\n // Produce a duplicate-free version of the array. If the array has already\n // been sorted, you have the option of using a faster algorithm.\n // Aliased as `unique`.\n _.uniq = _.unique = function(array, isSorted, iterator, context) {\n if (_.isFunction(isSorted)) {\n context = iterator;\n iterator = isSorted;\n isSorted = false;\n }\n var initial = iterator ? _.map(array, iterator, context) : array;\n var results = [];\n var seen = [];\n each(initial, function(value, index) {\n if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {\n seen.push(value);\n results.push(array[index]);\n }\n });\n return results;\n };\n\n // Produce an array that contains the union: each distinct element from all of\n // the passed-in arrays.\n _.union = function() {\n return _.uniq(_.flatten(arguments, true));\n };\n\n // Produce an array that contains every item shared between all the\n // passed-in arrays.\n _.intersection = function(array) {\n var rest = slice.call(arguments, 1);\n return _.filter(_.uniq(array), function(item) {\n return _.every(rest, function(other) {\n return _.indexOf(other, item) >= 0;\n });\n });\n };\n\n // Take the difference between one array and a number of other arrays.\n // Only the elements present in just the first array will remain.\n _.difference = function(array) {\n var rest = concat.apply(ArrayProto, slice.call(arguments, 1));\n return _.filter(array, function(value){ return !_.contains(rest, value); });\n };\n\n // Zip together multiple lists into a single array -- elements that share\n // an index go together.\n _.zip = function() {\n var length = _.max(_.pluck(arguments, \"length\").concat(0));\n var results = new Array(length);\n for (var i = 0; i < length; i++) {\n results[i] = _.pluck(arguments, '' + i);\n }\n return results;\n };\n\n // Converts lists into objects. Pass either a single array of `[key, value]`\n // pairs, or two parallel arrays of the same length -- one of keys, and one of\n // the corresponding values.\n _.object = function(list, values) {\n if (list == null) return {};\n var result = {};\n for (var i = 0, length = list.length; i < length; i++) {\n if (values) {\n result[list[i]] = values[i];\n } else {\n result[list[i][0]] = list[i][1];\n }\n }\n return result;\n };\n\n // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),\n // we need this function. Return the position of the first occurrence of an\n // item in an array, or -1 if the item is not included in the array.\n // Delegates to **ECMAScript 5**'s native `indexOf` if available.\n // If the array is large and already in sort order, pass `true`\n // for **isSorted** to use binary search.\n _.indexOf = function(array, item, isSorted) {\n if (array == null) return -1;\n var i = 0, length = array.length;\n if (isSorted) {\n if (typeof isSorted == 'number') {\n i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted);\n } else {\n i = _.sortedIndex(array, item);\n return array[i] === item ? i : -1;\n }\n }\n if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);\n for (; i < length; i++) if (array[i] === item) return i;\n return -1;\n };\n\n // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.\n _.lastIndexOf = function(array, item, from) {\n if (array == null) return -1;\n var hasIndex = from != null;\n if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {\n return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);\n }\n var i = (hasIndex ? from : array.length);\n while (i--) if (array[i] === item) return i;\n return -1;\n };\n\n // Generate an integer Array containing an arithmetic progression. A port of\n // the native Python `range()` function. See\n // [the Python documentation](http://docs.python.org/library/functions.html#range).\n _.range = function(start, stop, step) {\n if (arguments.length <= 1) {\n stop = start || 0;\n start = 0;\n }\n step = arguments[2] || 1;\n\n var length = Math.max(Math.ceil((stop - start) / step), 0);\n var idx = 0;\n var range = new Array(length);\n\n while(idx < length) {\n range[idx++] = start;\n start += step;\n }\n\n return range;\n };\n\n // Function (ahem) Functions\n // ------------------\n\n // Reusable constructor function for prototype setting.\n var ctor = function(){};\n\n // Create a function bound to a given object (assigning `this`, and arguments,\n // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if\n // available.\n _.bind = function(func, context) {\n var args, bound;\n if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));\n if (!_.isFunction(func)) throw new TypeError;\n args = slice.call(arguments, 2);\n return bound = function() {\n if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));\n ctor.prototype = func.prototype;\n var self = new ctor;\n ctor.prototype = null;\n var result = func.apply(self, args.concat(slice.call(arguments)));\n if (Object(result) === result) return result;\n return self;\n };\n };\n\n // Partially apply a function by creating a version that has had some of its\n // arguments pre-filled, without changing its dynamic `this` context.\n _.partial = function(func) {\n var args = slice.call(arguments, 1);\n return function() {\n return func.apply(this, args.concat(slice.call(arguments)));\n };\n };\n\n // Bind all of an object's methods to that object. Useful for ensuring that\n // all callbacks defined on an object belong to it.\n _.bindAll = function(obj) {\n var funcs = slice.call(arguments, 1);\n if (funcs.length === 0) throw new Error(\"bindAll must be passed function names\");\n each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });\n return obj;\n };\n\n // Memoize an expensive function by storing its results.\n _.memoize = function(func, hasher) {\n var memo = {};\n hasher || (hasher = _.identity);\n return function() {\n var key = hasher.apply(this, arguments);\n return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));\n };\n };\n\n // Delays a function for the given number of milliseconds, and then calls\n // it with the arguments supplied.\n _.delay = function(func, wait) {\n var args = slice.call(arguments, 2);\n return setTimeout(function(){ return func.apply(null, args); }, wait);\n };\n\n // Defers a function, scheduling it to run after the current call stack has\n // cleared.\n _.defer = function(func) {\n return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));\n };\n\n // Returns a function, that, when invoked, will only be triggered at most once\n // during a given window of time. Normally, the throttled function will run\n // as much as it can, without ever going more than once per `wait` duration;\n // but if you'd like to disable the execution on the leading edge, pass\n // `{leading: false}`. To disable execution on the trailing edge, ditto.\n _.throttle = function(func, wait, options) {\n var context, args, result;\n var timeout = null;\n var previous = 0;\n options || (options = {});\n var later = function() {\n previous = options.leading === false ? 0 : new Date;\n timeout = null;\n result = func.apply(context, args);\n };\n return function() {\n var now = new Date;\n if (!previous && options.leading === false) previous = now;\n var remaining = wait - (now - previous);\n context = this;\n args = arguments;\n if (remaining <= 0) {\n clearTimeout(timeout);\n timeout = null;\n previous = now;\n result = func.apply(context, args);\n } else if (!timeout && options.trailing !== false) {\n timeout = setTimeout(later, remaining);\n }\n return result;\n };\n };\n\n // Returns a function, that, as long as it continues to be invoked, will not\n // be triggered. The function will be called after it stops being called for\n // N milliseconds. If `immediate` is passed, trigger the function on the\n // leading edge, instead of the trailing.\n _.debounce = function(func, wait, immediate) {\n var timeout, args, context, timestamp, result;\n return function() {\n context = this;\n args = arguments;\n timestamp = new Date();\n var later = function() {\n var last = (new Date()) - timestamp;\n if (last < wait) {\n timeout = setTimeout(later, wait - last);\n } else {\n timeout = null;\n if (!immediate) result = func.apply(context, args);\n }\n };\n var callNow = immediate && !timeout;\n if (!timeout) {\n timeout = setTimeout(later, wait);\n }\n if (callNow) result = func.apply(context, args);\n return result;\n };\n };\n\n // Returns a function that will be executed at most one time, no matter how\n // often you call it. Useful for lazy initialization.\n _.once = function(func) {\n var ran = false, memo;\n return function() {\n if (ran) return memo;\n ran = true;\n memo = func.apply(this, arguments);\n func = null;\n return memo;\n };\n };\n\n // Returns the first function passed as an argument to the second,\n // allowing you to adjust arguments, run code before and after, and\n // conditionally execute the original function.\n _.wrap = function(func, wrapper) {\n return function() {\n var args = [func];\n push.apply(args, arguments);\n return wrapper.apply(this, args);\n };\n };\n\n // Returns a function that is the composition of a list of functions, each\n // consuming the return value of the function that follows.\n _.compose = function() {\n var funcs = arguments;\n return function() {\n var args = arguments;\n for (var i = funcs.length - 1; i >= 0; i--) {\n args = [funcs[i].apply(this, args)];\n }\n return args[0];\n };\n };\n\n // Returns a function that will only be executed after being called N times.\n _.after = function(times, func) {\n return function() {\n if (--times < 1) {\n return func.apply(this, arguments);\n }\n };\n };\n\n // Object Functions\n // ----------------\n\n // Retrieve the names of an object's properties.\n // Delegates to **ECMAScript 5**'s native `Object.keys`\n _.keys = nativeKeys || function(obj) {\n if (obj !== Object(obj)) throw new TypeError('Invalid object');\n var keys = [];\n for (var key in obj) if (_.has(obj, key)) keys.push(key);\n return keys;\n };\n\n // Retrieve the values of an object's properties.\n _.values = function(obj) {\n var keys = _.keys(obj);\n var length = keys.length;\n var values = new Array(length);\n for (var i = 0; i < length; i++) {\n values[i] = obj[keys[i]];\n }\n return values;\n };\n\n // Convert an object into a list of `[key, value]` pairs.\n _.pairs = function(obj) {\n var keys = _.keys(obj);\n var length = keys.length;\n var pairs = new Array(length);\n for (var i = 0; i < length; i++) {\n pairs[i] = [keys[i], obj[keys[i]]];\n }\n return pairs;\n };\n\n // Invert the keys and values of an object. The values must be serializable.\n _.invert = function(obj) {\n var result = {};\n var keys = _.keys(obj);\n for (var i = 0, length = keys.length; i < length; i++) {\n result[obj[keys[i]]] = keys[i];\n }\n return result;\n };\n\n // Return a sorted list of the function names available on the object.\n // Aliased as `methods`\n _.functions = _.methods = function(obj) {\n var names = [];\n for (var key in obj) {\n if (_.isFunction(obj[key])) names.push(key);\n }\n return names.sort();\n };\n\n // Extend a given object with all the properties in passed-in object(s).\n _.extend = function(obj) {\n each(slice.call(arguments, 1), function(source) {\n if (source) {\n for (var prop in source) {\n obj[prop] = source[prop];\n }\n }\n });\n return obj;\n };\n\n // Return a copy of the object only containing the whitelisted properties.\n _.pick = function(obj) {\n var copy = {};\n var keys = concat.apply(ArrayProto, slice.call(arguments, 1));\n each(keys, function(key) {\n if (key in obj) copy[key] = obj[key];\n });\n return copy;\n };\n\n // Return a copy of the object without the blacklisted properties.\n _.omit = function(obj) {\n var copy = {};\n var keys = concat.apply(ArrayProto, slice.call(arguments, 1));\n for (var key in obj) {\n if (!_.contains(keys, key)) copy[key] = obj[key];\n }\n return copy;\n };\n\n // Fill in a given object with default properties.\n _.defaults = function(obj) {\n each(slice.call(arguments, 1), function(source) {\n if (source) {\n for (var prop in source) {\n if (obj[prop] === void 0) obj[prop] = source[prop];\n }\n }\n });\n return obj;\n };\n\n // Create a (shallow-cloned) duplicate of an object.\n _.clone = function(obj) {\n if (!_.isObject(obj)) return obj;\n return _.isArray(obj) ? obj.slice() : _.extend({}, obj);\n };\n\n // Invokes interceptor with the obj, and then returns obj.\n // The primary purpose of this method is to \"tap into\" a method chain, in\n // order to perform operations on intermediate results within the chain.\n _.tap = function(obj, interceptor) {\n interceptor(obj);\n return obj;\n };\n\n // Internal recursive comparison function for `isEqual`.\n var eq = function(a, b, aStack, bStack) {\n // Identical objects are equal. `0 === -0`, but they aren't identical.\n // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).\n if (a === b) return a !== 0 || 1 / a == 1 / b;\n // A strict comparison is necessary because `null == undefined`.\n if (a == null || b == null) return a === b;\n // Unwrap any wrapped objects.\n if (a instanceof _) a = a._wrapped;\n if (b instanceof _) b = b._wrapped;\n // Compare `[[Class]]` names.\n var className = toString.call(a);\n if (className != toString.call(b)) return false;\n switch (className) {\n // Strings, numbers, dates, and booleans are compared by value.\n case '[object String]':\n // Primitives and their corresponding object wrappers are equivalent; thus, `\"5\"` is\n // equivalent to `new String(\"5\")`.\n return a == String(b);\n case '[object Number]':\n // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for\n // other numeric values.\n return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);\n case '[object Date]':\n case '[object Boolean]':\n // Coerce dates and booleans to numeric primitive values. Dates are compared by their\n // millisecond representations. Note that invalid dates with millisecond representations\n // of `NaN` are not equivalent.\n return +a == +b;\n // RegExps are compared by their source patterns and flags.\n case '[object RegExp]':\n return a.source == b.source &&\n a.global == b.global &&\n a.multiline == b.multiline &&\n a.ignoreCase == b.ignoreCase;\n }\n if (typeof a != 'object' || typeof b != 'object') return false;\n // Assume equality for cyclic structures. The algorithm for detecting cyclic\n // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.\n var length = aStack.length;\n while (length--) {\n // Linear search. Performance is inversely proportional to the number of\n // unique nested structures.\n if (aStack[length] == a) return bStack[length] == b;\n }\n // Objects with different constructors are not equivalent, but `Object`s\n // from different frames are.\n var aCtor = a.constructor, bCtor = b.constructor;\n if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&\n _.isFunction(bCtor) && (bCtor instanceof bCtor))) {\n return false;\n }\n // Add the first object to the stack of traversed objects.\n aStack.push(a);\n bStack.push(b);\n var size = 0, result = true;\n // Recursively compare objects and arrays.\n if (className == '[object Array]') {\n // Compare array lengths to determine if a deep comparison is necessary.\n size = a.length;\n result = size == b.length;\n if (result) {\n // Deep compare the contents, ignoring non-numeric properties.\n while (size--) {\n if (!(result = eq(a[size], b[size], aStack, bStack))) break;\n }\n }\n } else {\n // Deep compare objects.\n for (var key in a) {\n if (_.has(a, key)) {\n // Count the expected number of properties.\n size++;\n // Deep compare each member.\n if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;\n }\n }\n // Ensure that both objects contain the same number of properties.\n if (result) {\n for (key in b) {\n if (_.has(b, key) && !(size--)) break;\n }\n result = !size;\n }\n }\n // Remove the first object from the stack of traversed objects.\n aStack.pop();\n bStack.pop();\n return result;\n };\n\n // Perform a deep comparison to check if two objects are equal.\n _.isEqual = function(a, b) {\n return eq(a, b, [], []);\n };\n\n // Is a given array, string, or object empty?\n // An \"empty\" object has no enumerable own-properties.\n _.isEmpty = function(obj) {\n if (obj == null) return true;\n if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;\n for (var key in obj) if (_.has(obj, key)) return false;\n return true;\n };\n\n // Is a given value a DOM element?\n _.isElement = function(obj) {\n return !!(obj && obj.nodeType === 1);\n };\n\n // Is a given value an array?\n // Delegates to ECMA5's native Array.isArray\n _.isArray = nativeIsArray || function(obj) {\n return toString.call(obj) == '[object Array]';\n };\n\n // Is a given variable an object?\n _.isObject = function(obj) {\n return obj === Object(obj);\n };\n\n // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.\n each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {\n _['is' + name] = function(obj) {\n return toString.call(obj) == '[object ' + name + ']';\n };\n });\n\n // Define a fallback version of the method in browsers (ahem, IE), where\n // there isn't any inspectable \"Arguments\" type.\n if (!_.isArguments(arguments)) {\n _.isArguments = function(obj) {\n return !!(obj && _.has(obj, 'callee'));\n };\n }\n\n // Optimize `isFunction` if appropriate.\n if (typeof (/./) !== 'function') {\n _.isFunction = function(obj) {\n return typeof obj === 'function';\n };\n }\n\n // Is a given object a finite number?\n _.isFinite = function(obj) {\n return isFinite(obj) && !isNaN(parseFloat(obj));\n };\n\n // Is the given value `NaN`? (NaN is the only number which does not equal itself).\n _.isNaN = function(obj) {\n return _.isNumber(obj) && obj != +obj;\n };\n\n // Is a given value a boolean?\n _.isBoolean = function(obj) {\n return obj === true || obj === false || toString.call(obj) == '[object Boolean]';\n };\n\n // Is a given value equal to null?\n _.isNull = function(obj) {\n return obj === null;\n };\n\n // Is a given variable undefined?\n _.isUndefined = function(obj) {\n return obj === void 0;\n };\n\n // Shortcut function for checking if an object has a given property directly\n // on itself (in other words, not on a prototype).\n _.has = function(obj, key) {\n return hasOwnProperty.call(obj, key);\n };\n\n // Utility Functions\n // -----------------\n\n // Run Underscore.js in *noConflict* mode, returning the `_` variable to its\n // previous owner. Returns a reference to the Underscore object.\n _.noConflict = function() {\n root._ = previousUnderscore;\n return this;\n };\n\n // Keep the identity function around for default iterators.\n _.identity = function(value) {\n return value;\n };\n\n // Run a function **n** times.\n _.times = function(n, iterator, context) {\n var accum = Array(Math.max(0, n));\n for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);\n return accum;\n };\n\n // Return a random integer between min and max (inclusive).\n _.random = function(min, max) {\n if (max == null) {\n max = min;\n min = 0;\n }\n return min + Math.floor(Math.random() * (max - min + 1));\n };\n\n // List of HTML entities for escaping.\n var entityMap = {\n escape: {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": '''\n }\n };\n entityMap.unescape = _.invert(entityMap.escape);\n\n // Regexes containing the keys and values listed immediately above.\n var entityRegexes = {\n escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),\n unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')\n };\n\n // Functions for escaping and unescaping strings to/from HTML interpolation.\n _.each(['escape', 'unescape'], function(method) {\n _[method] = function(string) {\n if (string == null) return '';\n return ('' + string).replace(entityRegexes[method], function(match) {\n return entityMap[method][match];\n });\n };\n });\n\n // If the value of the named `property` is a function then invoke it with the\n // `object` as context; otherwise, return it.\n _.result = function(object, property) {\n if (object == null) return void 0;\n var value = object[property];\n return _.isFunction(value) ? value.call(object) : value;\n };\n\n // Add your own custom functions to the Underscore object.\n _.mixin = function(obj) {\n each(_.functions(obj), function(name) {\n var func = _[name] = obj[name];\n _.prototype[name] = function() {\n var args = [this._wrapped];\n push.apply(args, arguments);\n return result.call(this, func.apply(_, args));\n };\n });\n };\n\n // Generate a unique integer id (unique within the entire client session).\n // Useful for temporary DOM ids.\n var idCounter = 0;\n _.uniqueId = function(prefix) {\n var id = ++idCounter + '';\n return prefix ? prefix + id : id;\n };\n\n // By default, Underscore uses ERB-style template delimiters, change the\n // following template settings to use alternative delimiters.\n _.templateSettings = {\n evaluate : /<%([\\s\\S]+?)%>/g,\n interpolate : /<%=([\\s\\S]+?)%>/g,\n escape : /<%-([\\s\\S]+?)%>/g\n };\n\n // When customizing `templateSettings`, if you don't want to define an\n // interpolation, evaluation or escaping regex, we need one that is\n // guaranteed not to match.\n var noMatch = /(.)^/;\n\n // Certain characters need to be escaped so that they can be put into a\n // string literal.\n var escapes = {\n \"'\": \"'\",\n '\\\\': '\\\\',\n '\\r': 'r',\n '\\n': 'n',\n '\\t': 't',\n '\\u2028': 'u2028',\n '\\u2029': 'u2029'\n };\n\n var escaper = /\\\\|'|\\r|\\n|\\t|\\u2028|\\u2029/g;\n\n // JavaScript micro-templating, similar to John Resig's implementation.\n // Underscore templating handles arbitrary delimiters, preserves whitespace,\n // and correctly escapes quotes within interpolated code.\n _.template = function(text, data, settings) {\n var render;\n settings = _.defaults({}, settings, _.templateSettings);\n\n // Combine delimiters into one regular expression via alternation.\n var matcher = new RegExp([\n (settings.escape || noMatch).source,\n (settings.interpolate || noMatch).source,\n (settings.evaluate || noMatch).source\n ].join('|') + '|$', 'g');\n\n // Compile the template source, escaping string literals appropriately.\n var index = 0;\n var source = \"__p+='\";\n text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {\n source += text.slice(index, offset)\n .replace(escaper, function(match) { return '\\\\' + escapes[match]; });\n\n if (escape) {\n source += \"'+\\n((__t=(\" + escape + \"))==null?'':_.escape(__t))+\\n'\";\n }\n if (interpolate) {\n source += \"'+\\n((__t=(\" + interpolate + \"))==null?'':__t)+\\n'\";\n }\n if (evaluate) {\n source += \"';\\n\" + evaluate + \"\\n__p+='\";\n }\n index = offset + match.length;\n return match;\n });\n source += \"';\\n\";\n\n // If a variable is not specified, place data values in local scope.\n if (!settings.variable) source = 'with(obj||{}){\\n' + source + '}\\n';\n\n source = \"var __t,__p='',__j=Array.prototype.join,\" +\n \"print=function(){__p+=__j.call(arguments,'');};\\n\" +\n source + \"return __p;\\n\";\n\n try {\n render = new Function(settings.variable || 'obj', '_', source);\n } catch (e) {\n e.source = source;\n throw e;\n }\n\n if (data) return render(data, _);\n var template = function(data) {\n return render.call(this, data, _);\n };\n\n // Provide the compiled function source as a convenience for precompilation.\n template.source = 'function(' + (settings.variable || 'obj') + '){\\n' + source + '}';\n\n return template;\n };\n\n // Add a \"chain\" function, which will delegate to the wrapper.\n _.chain = function(obj) {\n return _(obj).chain();\n };\n\n // OOP\n // ---------------\n // If Underscore is called as a function, it returns a wrapped object that\n // can be used OO-style. This wrapper holds altered versions of all the\n // underscore functions. Wrapped objects may be chained.\n\n // Helper function to continue chaining intermediate results.\n var result = function(obj) {\n return this._chain ? _(obj).chain() : obj;\n };\n\n // Add all of the Underscore functions to the wrapper object.\n _.mixin(_);\n\n // Add all mutator Array functions to the wrapper.\n each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {\n var method = ArrayProto[name];\n _.prototype[name] = function() {\n var obj = this._wrapped;\n method.apply(obj, arguments);\n if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];\n return result.call(this, obj);\n };\n });\n\n // Add all accessor Array functions to the wrapper.\n each(['concat', 'join', 'slice'], function(name) {\n var method = ArrayProto[name];\n _.prototype[name] = function() {\n return result.call(this, method.apply(this._wrapped, arguments));\n };\n });\n\n _.extend(_.prototype, {\n\n // Start chaining a wrapped Underscore object.\n chain: function() {\n this._chain = true;\n return this;\n },\n\n // Extracts the result from a wrapped and chained object.\n value: function() {\n return this._wrapped;\n }\n\n });\n\n}).call(this);","/**\n * Created by dagan on 07/04/2014.\n */\n'use strict';\nwindow.XdUtils = window.XdUtils || (function () {\n\n function extend(object, defaultObject) {\n var result = defaultObject || {};\n var key;\n for (key in object) {\n if (object.hasOwnProperty(key)) {\n result[key] = object[key];\n }\n }\n return result;\n }\n\n //public interface\n return {\n extend : extend\n };\n})();\n/* global console, XdUtils */\nwindow.xdLocalStorage = window.xdLocalStorage || (function () {\n var MESSAGE_NAMESPACE = 'cross-domain-local-message';\n var options = {\n iframeId: 'cross-domain-iframe',\n iframeUrl: undefined,\n initCallback: function () {}\n };\n var requestId = -1;\n var iframe;\n var requests = {};\n var wasInit = false;\n var iframeReady = true;\n\n function applyCallback(data) {\n if (requests[data.id]) {\n requests[data.id](data);\n delete requests[data.id];\n }\n }\n\n function receiveMessage(event) {\n var data;\n try {\n data = JSON.parse(event.data);\n } catch (err) {\n //not our message, can ignore\n }\n if (data && data.namespace === MESSAGE_NAMESPACE) {\n if (data.id === 'iframe-ready') {\n iframeReady = true;\n options.initCallback();\n } else {\n applyCallback(data);\n }\n }\n }\n\n function buildMessage(action, key, value, callback) {\n requestId++;\n requests[requestId] = callback;\n var data = {\n namespace: MESSAGE_NAMESPACE,\n id: requestId,\n action: action,\n key: key,\n value: value\n };\n iframe.contentWindow.postMessage(JSON.stringify(data), '*');\n }\n\n function init(customOptions) {\n options = XdUtils.extend(customOptions, options);\n var temp = document.createElement('div');\n\n if (window.addEventListener) {\n window.addEventListener('message', receiveMessage, false);\n } else {\n window.attachEvent('onmessage', receiveMessage);\n }\n\n temp.innerHTML = '';\n document.body.appendChild(temp);\n iframe = document.getElementById(options.iframeId);\n }\n\n function isApiReady() {\n if (!wasInit) {\n console.log('You must call xdLocalStorage.init() before using it.');\n return false;\n }\n if (!iframeReady) {\n console.log('You must wait for iframe ready message before using the api.');\n return false;\n }\n return true;\n }\n\n function isDomReady() {\n return true; //(document.readyState === 'complete');\n }\n\n return {\n //callback is optional for cases you use the api before window load.\n init: function (customOptions) {\n if (!customOptions.iframeUrl) {\n throw 'You must specify iframeUrl';\n }\n if (wasInit) {\n console.log('xdLocalStorage was already initialized!');\n return;\n }\n wasInit = true;\n if (isDomReady()) {\n init(customOptions);\n } else {\n if (document.addEventListener) {\n // All browsers expect IE < 9\n document.addEventListener('readystatechange', function () {\n if (isDomReady()) {\n init(customOptions);\n }\n });\n } else {\n // IE < 9\n document.attachEvent('readystatechange', function () {\n if (isDomReady()) {\n init(customOptions);\n }\n });\n }\n }\n },\n setItem: function (key, value, callback) {\n if (!isApiReady()) {\n return;\n }\n buildMessage('set', key, value, callback);\n },\n\n getItem: function (key, callback) {\n if (!isApiReady()) {\n return;\n }\n buildMessage('get', key, null, callback);\n },\n removeItem: function (key, callback) {\n if (!isApiReady()) {\n return;\n }\n buildMessage('remove', key, null, callback);\n },\n key: function (index, callback) {\n if (!isApiReady()) {\n return;\n }\n buildMessage('key', index, null, callback);\n },\n getSize: function(callback) {\n if(!isApiReady()) {\n return;\n }\n buildMessage('size', null, null, callback);\n },\n getLength: function(callback) {\n if(!isApiReady()) {\n return;\n }\n buildMessage('length', null, null, callback);\n },\n clear: function (callback) {\n if (!isApiReady()) {\n return;\n }\n buildMessage('clear', null, null, callback);\n },\n wasInit: function () {\n return wasInit;\n }\n };\n})();\n","(function(){\n var $CSN = window.ConsultSystemsNod = {\n siteHash: '',\n siteId: 0,\n urlCheckInterval: false,\n windowTitle: 'Онлайн-консультант'\n };\n\n var $CS = window.ConsultSystems = {\n min: [240,350], //[440,350],\n max: [1400,1400],\n offset: {x:0,y:0},\n savedOffset: {},\n savedSize: [],\n fixedSupport: true,\n scrolltop: 0,\n window: {},\n opener: false,\n iframeSrc: \"\"+document.location.protocol+\"//consultsystems.ru/siteim/\",\n fixedClass: \"fixed\",\n isFixed: true,\n touchSupport: false,\n imagesUrl: \"\"+document.location.protocol+\"//consultsystems.ru/script/im/images/\",\n buttonImagesUrl: ''+document.location.protocol+'//consultsystems.ru/script/im/button/',\n avatar: ''+document.location.protocol+'//consultsystems.ru/script/im/button/avatar-2.png',\n style: {},\n domReady: false,\n buttonsCount: 0,\n minOpacity: 0,\n buttons: {},\n openPosition: [300,200],\n stylesheet: '',\n titleHeight: 35,\n callbackVisit: \"consultsystemsVisit\",\n urlVisit: \"\"+document.location.protocol+\"//consultsystems.ru/script/im/visit.php?callback=?\",\n callbackCheck: \"consultsystemsCheck\",\n urlCheck: \"\"+document.location.protocol+\"//consultsystems.ru/script/im/update.php?callback=?\",\n callbackClose: \"consultsystemsClose\",\n urlClose: \"\"+document.location.protocol+\"//consultsystems.ru/script/im/close.php?callback=?\",\n callbackParams: \"consultsystemsParams\",\n urlParams: \"\"+document.location.protocol+\"//consultsystems.ru/script/im/setparams.php?callback=?\",\n checkMaxId: '0',\n haveSession: false,\n needReload: false,\n tarifId: 4,\n userStatus: \"offline\",\n userReq: true,\n isIE8: (navigator.appVersion.indexOf(\"MSIE 8.\") != -1),\n isIE7: (navigator.appVersion.indexOf(\"MSIE 7.\") != -1),\n isIE6: false /*@cc_on || @_jscript_version < 5.7 @*/,\n isSafari: Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0\n };\n\n\n $CS.style = {\n windowTitle: \"Онлайн-консультант\",\n textColor: \"#ffffff\",\n textShadow: \"1px 1px 1px rgba(0,0,0,.5)\",\n fontSize: \"14px\",\n borderRadius: 0,\n bgColorType: \"non-gradient\",\n bgColor: \"#66cc00\",\n bgGradient: [\"#9de21d\", \"#5e9427\"],\n borderColor: [\"#619829\"],\n borderWidth: 0,\n inBorderColor: [\"#BEEC69\",\"#ADD76C\",\"#9BC070\",\"#ADD76C\"],\n inBorderWidth: 0\n }\n\n $CS.windowShow = function () {\n document.getElementById('bubble_but').click();\n }\n\n $CS.widget = function () {\n\n var cook = getCookie(\"consultsystemswindow\");\n if (cook) {\n\n var csw = $CS.csw = cook.split(\"|\");\n\n if (csw[0] && csw[0]==\"open\" && $CS.haveSession) {\n $CS.preopen = true;\n }\n\n if (csw[1] && csw[2]) {\n $CS.savedOffset = {\n x: Number(csw[1]),\n y: Number(csw[2])\n }\n }\n\n if (csw[2] && csw[3]) {\n $CS.savedSize = [Number(csw[3]), Number(csw[4])];\n }\n\n }\n\n\n\n\n\n\n if ($CS.style.repaint) {\n $(\"#consultsystems_title span\").text($CSN.windowTitle)\n }\n\n var brdrad = $CS.style.borderRadius+'px '+$CS.style.borderRadius+'px 0 0';\n\n $CS.defaultStyle = '.consultsystems{-khtml-opacity:0;-moz-opacity:0;opacity:0;position:absolute;margin:0;padding:0;z-index:1000000;}#consultsystems_widget,#consultsystems_widget *{z-index:1000000;border:none;background:none;margin:0;padding:0;}.consultsystems_pre{transition:top .3s ease, left .3s ease, opacity .3s ease, width .3s ease, height .3s ease;-moz-transition:top .3s ease, left .3s ease, opacity .3s ease, width .3s ease, height .3s ease;-webkit-transition:top .3s ease, left .3s ease, opacity .3s ease, width .3s ease, height .3s ease;border:none;margin:0;padding:0;}.consultsystems_hidden{-khtml-opacity:'+$CS.minOpacity+';-moz-opacity:'+$CS.minOpacity+';opacity:'+$CS.minOpacity+';height:0;width:0;border:none;margin:0;padding:0;}.consultsystems_visible{-khtml-opacity:1;-moz-opacity:1;opacity:1;border:none;margin:0;padding:0;}#consultsystems_widget .consultsystems a{border:none;text-decoration:none;margin:0;padding:0;}#consultsystems_widget .consultsystems_widget{position:absolute;width:100%;height:100%;left:0;right:0;top:0;bottom:0;}#consultsystems_widget .consultsystems_title{cursor:default;left:0;top:0;right:0;position:static;width:auto;text-align:left;}#consultsystems_widget .consultsystems_title span{text-align:left;cursor:default;font-size:14px!important;font-family:Arial!important;font: bold 14px/'+$CS.titleHeight+'px Arial !important;font-weight:bold!important;display:block!important;line-height:'+$CS.titleHeight+'px;color:#fff!important;text-shadow:1px 1px 1px rgba(0,0,0,.5)!important;-moz-text-shadow:1px 1px 1px rgba(0,0,0,.5)!important;-webkit-text-shadow:1px 1px 1px rgba(0,0,0,.5)!important;margin:0; display:block; height: '+$CS.titleHeight+'px; padding-left:15px}#consultsystems_widget .consultsystems_title strong{text-align:left;display:block;overflow:hidden;}#consultsystems_widget .consultsystems_title b{display:none;/*right:0;width:6px;height:'+$CS.titleHeight+'px;overflow:hidden;position:absolute;float:right;*/}#consultsystems_widget .consultsystems_iframe_div{border-left:solid 1px #DFDFDF;border-right:solid 1px #DFDFDF;background:#fff;min-height:100px;position:absolute;left:0;right:0;top:'+$CS.titleHeight+'px;bottom:10px;}#consultsystems_widget .consultsystems_bottom{height:12px;display:block;overflow:hidden;width:100%;right:0;left:0;position:absolute;bottom:0;}#consultsystems_widget .consultsystems_bottom strong{display:block;height:12px;overflow:hidden;background:url('+$CS.imagesUrl+'bottom.png) repeat-x 0 0;left:0;right:12px;margin-right:12px;position:relative;}#consultsystems_widget .consultsystems_bottom b{display:block;height:12px;width:12px;overflow:hidden;background:url('+$CS.imagesUrl+'bottom-r.png) repeat-x 0 0;right:0;float:right;position:absolute;}.consultsystems_fixed .consultsystems_shadows{display:block!important;}.consultsystems_shadow_lefttop{position:absolute;overflow:hidden;left:-3px;top:0;width:3px;height:20px;background:url('+$CS.imagesUrl+'shadow-corners.png) no-repeat 0 0;}#consultsystems_widget .consultsystems_shadow_righttop{position:absolute;overflow:hidden;right:-7px;top:10px;width:7px;height:10px;background:url('+$CS.imagesUrl+'shadow-corners.png) no-repeat -27px 0;}#consultsystems_widget .consultsystems_shadow_right{position:absolute;overflow:hidden;right:-7px;width:7px;top:20px;bottom:11px;background:url('+$CS.imagesUrl+'shadow-both.png) repeat-y -3px 0;}#consultsystems_widget .consultsystems_shadow_rightbottom{position:absolute;overflow:hidden;right:-7px;bottom:-7px;width:18px;height:18px;background:url('+$CS.imagesUrl+'shadow-corners.png) no-repeat -16px -20px;}#consultsystems_widget .consultsystems_shadow_bottom{position:absolute;overflow:hidden;left:13px;right:11px;bottom:-7px;height:7px;background:url('+$CS.imagesUrl+'shadow-bottom.png) repeat-x 0 0;}#consultsystems_widget .consultsystems_shadow_leftbottom{position:absolute;overflow:hidden;left:-3px;bottom:-7px;width:16px;height:18px;background:url('+$CS.imagesUrl+'shadow-corners.png) no-repeat 0 -20px;}#consultsystems_widget .consultsystems_shadow_left{position:absolute;overflow:hidden;left:-3px;width:3px;top:20px;bottom:11px;background:url('+$CS.imagesUrl+'shadow-both.png) repeat-y 0 0;}#consultsystems_widget .consultsystems_resizer{position:absolute;overflow:hidden;right:0;bottom:0;width:18px;height:18px;cursor:se-resize;}';\n $CS.defaultStyle += '#consultsystems_widget .consultsystems_close{cursor:pointer;position:absolute;width:13px;height:'+$CS.titleHeight+'px;right:0;top:0;}#consultsystems_widget .consultsystems_close i{position:absolute;background:url('+$CS.imagesUrl+'close.png) no-repeat 0 0;overflow:hidden;width:13px;height:13px;right:27px;top:12px;}#consultsystems_widget .consultsystems_close:hover i{background-position:-16px 0;}#consultsystems_widget .consultsystems_close:active i{background-position:-32px 0;}';\n\n $CS.defaultStyle += '#consultsystems_widget .consultsystems_end{cursor:pointer;position:absolute;width:13px;height:'+$CS.titleHeight+'px;right:0;top:0;}#consultsystems_widget .consultsystems_end i{position:absolute;background:url('+$CS.imagesUrl+'end.png) no-repeat 0 0;overflow:hidden;width:13px;height:13px;right:10px;top:12px;}#consultsystems_widget .consultsystems_end:hover i{background-position:-16px 0;}#consultsystems_widget .consultsystems_end:active i{background-position:-32px 0;}';\n\n $CS.defaultStyle += '#consultsystems_widget .consultsystems_iframe_over,.consultsystems_iframe_loading{position:absolute;left:0;top:0;right:0;bottom:0;width:100%;height:100%;background:#fff;}#consultsystems_widget .consultsystems_iframe_over{display:none;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;}#consultsystems_widget .consultsystems_iframe_loading{background:url('+$CS.imagesUrl+'preloader.gif) no-repeat center center;}#consultsystems_widget .consultsystems_iframe_over_show{display:block;}.consultsystems_fixed{position:fixed;}#consultsystems_widget .consultsystems_shadows,.consultsystems_closed,#consultsystems_widget .consultsystems_iframe_loaded{display:none;}';\n $CS.defaultStyle += '#consultsystems_widget .consultsystems_title, #consultsystems_widget .consultsystems_title strong, #consultsystems_widget .consultsystems_title span {border-radius: '+brdrad+'; -moz-border-radius: '+brdrad+'; -webkit-border-radius: '+brdrad+'}';\n $CS.defaultStyle +='.consultsystems_button_wrap{position:absolute;cursor:default;display:block;-khtml-opacity:1;z-index:100000;-moz-opacity:1;opacity:1;transition:opacity .5s ease;-moz-transition:opacity .5s ease;-webkit-transition:opacity .5s ease;}.consultsystems_button_wrap,.consultsystems_button_wrap *{border:none;user-select:none;-moz-user-select:none;-webkit-user-select:none;margin:0;padding:0;}.consultsystems_button_wrap .consultsystems_button{z-index:1000000;display:block;text-decoration:none;position:relative;}.consultsystems_button_hide{display:none;}.consultsystems_button_outscreen{left:-1000px!important;top:-10000px!important;right:auto!important;bottom:auto!important;}.consultsystems_button_left-top{top:0;left:0;}.consultsystems_button_center-top{top:0;left:50%;}.consultsystems_button_right-top{top:0;right:0;}.consultsystems_button_right-center{top:50%;right:0;}.consultsystems_button_left-bottom{bottom:0;left:0;}.consultsystems_button_center-bottom{bottom:0;left:50%;}.consultsystems_button_right-bottom{bottom:0;right:0;}.consultsystems_button_left-center{top:50%;left:0;}.consultsystems_button_wrap .consultsystems_button_pos{display:block;position:relative;}.consultsystems_button_wrap .consultsystems_button_border{display:block;border:solid 1px #619829;text-decoration:none;vertical-align:bottom;overflow:hidden;outline:none;margin:0;}.consultsystems_button_wrap .consultsystems_button_in{cursor:pointer;display:block;text-decoration:none;position:relative;overflow:hidden;}.consultsystems_button_text{display:inline-block;font:bold 14px/32px Arial!important;font-family:Arial!important;font-weight:bold;border:none;white-space:nowrap;margin:0;}.consultsystems_button_left-top .consultsystems_button_text,.consultsystems_button_center-top .consultsystems_button_text,.consultsystems_button_right-top .consultsystems_button_text,.consultsystems_button_left-bottom .consultsystems_button_text,.consultsystems_button_center-bottom .consultsystems_button_text,.consultsystems_button_right-bottom .consultsystems_button_text{padding:0 10px 0 35px;}.consultsystems_button_right-center .consultsystems_button_text,.consultsystems_button_left-center .consultsystems_button_text{width:33px;text-align:center;padding:35px 0 25px;}.consultsystems_button_icon{display:block;overflow:hidden;position:absolute;left:7px;top:50%;background:url('+$CS.buttonImagesUrl+'icon-1.png) no-repeat center center;width:24px;height:24px;margin-top:-12px;}.consultsystems_button_right-center .consultsystems_button_icon,.consultsystems_button_left-center .consultsystems_button_icon{left:50%;margin-left:-12px;bottom:7px;top:auto;}.consultsystems_button_status{display:none;background:url('+$CS.buttonImagesUrl+'online.png) no-repeat 0 0;width:70px;height:21px;overflow:hidden;position:absolute;right:7px;top:50%;border:none;margin:-10px 0 0;padding:0;}.consultsystems_button_right-center .consultsystems_button_status,.consultsystems_button_left-center .consultsystems_button_status{background:url('+$CS.buttonImagesUrl+'online.png) no-repeat 0 -30px;width:21px;height:70px;left:50%;top:7px;bottom:auto;margin:0 0 0 -10px;}.consultsystems_button_wrap .consultsystems_bubble_trans {transition:opacity .5s ease;-moz-transition:opacity .5s ease;-webkit-transition:opacity .5s ease;} .consultsystems_button_wrap .consultsystems_bubble{text-align:left;border:solid 1px #D3CEC9;background:#F9F5F1;width:240px;border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px;position:absolute;display:block;box-shadow:1px 2px 3px rgba(0,0,0,0.1);-moz-shadow:1px 2px 3px rgba(0,0,0,0.1);-webkit-shadow:1px 2px 3px rgba(0,0,0,0.1);-khtml-opacity:1;-moz-opacity:1;opacity:1;}.consultsystems_button_wrap .consultsystems_bubble_in{text-align:left;font:normal 12px/15px Arial, Tahoma!important;color:#333333;display:block;position:relative;}.consultsystems_button_wrap .consultsystems_bubble_info{display:block;padding:10px;}.consultsystems_button_wrap .consultsystems_bubble_arrow{position:absolute;}.consultsystems_button_left-top .consultsystems_bubble_arrow,.consultsystems_button_center-top .consultsystems_bubble_arrow{display:inline-block;width:15px;height:23px;top:-23px;left:20px;background:url('+$CS.buttonImagesUrl+'bubble-top-1.png) no-repeat 0 0;}.consultsystems_button_right-top .consultsystems_bubble_arrow{display:block;width:15px;height:23px;top:-23px;right:20px;background:url('+$CS.buttonImagesUrl+'bubble-top-2.png) no-repeat 0 0;}.consultsystems_button_right-center .consultsystems_bubble_arrow{display:block;width:21px;height:16px;top:10px;right:-21px;background:url('+$CS.buttonImagesUrl+'bubble-right.png) no-repeat 0 0;}.consultsystems_button_left-center .consultsystems_bubble_arrow{display:inline-block;width:21px;height:16px;top:10px;left:-21px;background:url('+$CS.buttonImagesUrl+'bubble-left.png) no-repeat 0 0;}.consultsystems_button_left-bottom .consultsystems_bubble_arrow,.consultsystems_button_center-bottom .consultsystems_bubble_arrow{display:inline-block;width:18px;height:19px;bottom:-19px;left:20px;background:url('+$CS.buttonImagesUrl+'bubble-bottom-1.png) no-repeat 0 0;}.consultsystems_button_right-bottom .consultsystems_bubble_arrow{display:inline-block;width:18px;height:19px;bottom:-19px;right:20px;background:url('+$CS.buttonImagesUrl+'bubble-bottom-2.png) no-repeat 0 0;}.consultsystems_button_right-top .consultsystems_bubble{top:100%;right:0;margin:10px 0 0;}.consultsystems_button_right-center .consultsystems_bubble{top:10px;left:-250px;}.consultsystems_button_left-center .consultsystems_bubble{top:10px;left:100%;margin:0 0 0 10px;}.consultsystems_button_right-bottom .consultsystems_bubble{top:-100%;right:10px;margin:-10px 0 0;}.consultsystems_button_wrap .consultsystems_bubble_info_img{float:left;display:block;padding:0 10px 0 0;position:absolute;left:10px;top:10px}.consultsystems_button_wrap .consultsystems_bubble_info_text{text-align:left;display:block;margin-left:55px;text-decoration:none;}.consultsystems_button_wrap .consultsystems_bubble_button{cursor:pointer;display:inline-block;margin-top:6px;border-radius:4px;-moz-border-radius:4px;-webkit-border-radius:4px;font-size:11px;text-decoration:none;padding:3px 8px;margin-left:55px}.consultsystems_button_wrap .consultsystems_bubble_close{background:url('+$CS.buttonImagesUrl+'close.png) no-repeat 0 0;position:absolute;display:inline-block;right:10px;top:10px;width:10px;height:10px;overflow:hidden;cursor:pointer;}.consultsystems_button_wrap .consultsystems_bubble_close:hover{background-position:0 -20px;}.consultsystems_button_hidden,.consultsystems_button_wrap .consultsystems_bubble_hidden{filter:alpha(opacity=0);-khtml-opacity:0;-moz-opacity:0;opacity:0;}.consultsystems_online .consultsystems_button_status,.consultsystems_offline .consultsystems_button_status{display:block;}.consultsystems_button_wrap .consultsystems_bubble_closed,.consultsystems_button_closed{display:none;}.consultsystems_button_left-top .consultsystems_bubble,.consultsystems_button_center-top .consultsystems_bubble{top:100%;left:0;margin:10px 0 0 5px;}.consultsystems_button_left-bottom .consultsystems_bubble,.consultsystems_button_center-bottom .consultsystems_bubble{top:-100%;left:0;margin:-10px 0 0 5px;}.consultsystems_button_preopen {top:-10000px; left:-10000px}';\n\n if ($CS.style) {\n var addstyle = '';\n if ($CS.style.textColor) { addstyle+='#consultsystems_widget .consultsystems_title span {color:'+$CS.style.textColor+' !important}'; }\n if ($CS.style.textShadow) { addstyle+='#consultsystems_widget .consultsystems_title span { text-shadow: '+$CS.style.textShadow+' !important ; -moz-text-shadow: 1px 1px 1px '+$CS.style.textShadow+' !important ; -webkit-text-shadow: 1px 1px 1px '+$CS.style.textShadow+' !important ; }'; }\n\n addstyle+='#consultsystems_widget .consultsystems_title span {background: '+$CS.style.bgColor+';}';\n if ($CS.style.bgColorType==\"gradient\") {\n addstyle+='#consultsystems_widget .consultsystems_title span {background: '+$CS.style.bgColor+'; '+gradientGenerator($CS.style.bgGradient[0],$CS.style.bgGradient[1], 'y')+'}';\n }\n\n var winOuter = borderGenerator($CS.style.borderColor, $CS.style.borderWidth);\n var winInner = borderGenerator($CS.style.inBorderColor, $CS.style.inBorderWidth);\n\n var brdrlength = winOuter.obj.top.width+winOuter.obj.bottom.width+winInner.obj.top.width+winInner.obj.bottom.width;\n\n\n $CS.newTitleHeight = $CS.titleHeight-brdrlength;\n addstyle+='#consultsystems_widget .consultsystems_title span {font-size: '+$CS.style.fontSize+' !important; color: '+$CS.style.textColor+' !important; line-height:'+($CS.newTitleHeight-1)+'px !important; height: '+$CS.newTitleHeight+'px !important;}';\n addstyle+='#consultsystems_widget .consultsystems_title {'+winOuter.raw+'}';\n addstyle+='#consultsystems_widget .consultsystems_title strong {'+winInner.raw+'}';\n $CS.defaultStyle+=addstyle;\n }\n\n if ('ontouchstart' in document.documentElement) { $CS.touchSupport = true }\n\n }\n\n if (!window.CSEditorMode) {\n $CS.widget();\n }\n\n\n $CS.stateReplacementsSource = [\"color\",\"textShadow\",\"fontSize\",\"bgColor\",\"bgGradient\",\"bgColorType\",\"bgGradientType\",\"borderColor\",\"borderWidth\",\"inBorderWidth\",\"inBorderColor\"];\n $CS.stateReplacements = [\"Color\",\"TextShadow\",\"FontSize\",\"BgColor\",\"BgGradient\",\"BgColorType\",\"BgGradientType\",\"BorderColor\",\"BorderWidth\",\"InBorderWidth\",\"InBorderColor\"];\n\n\n\n $CS.button = function (_options) {\n\n\n var defaults = {\n\n bubbleBorder: '#D3CEC9',\n bubbleText: 'Здравствуйте! Могу ли Вам помочь?',\n bubbleImage: $CS.avatar,\n bubbleButtonText: 'начать диалог',\n bubbleButtonTextColor: '#593D00',\n bubbleButtonBorder: '#E8E6E3',\n bubbleButtonBg: 'white',\n bubbleButtonHoverTextColor: '#593D00',\n bubbleButtonHoverBorder: '#cccccc',\n bubbleButtonHoverBg: '#eee',\n bubbleButtonActiveTextColor: '#593D00',\n bubbleButtonActiveBorder: '#E8E6E3',\n bubbleButtonActiveBg: '#ccc',\n autoOpenMargin: {\n x: 50,\n y: 30\n },\n autoOpenPosition: true\n }\n\n\n var options = extend (defaults, _options);\n\n\n $CS.toggleHide = options.toggleHide;\n\n\n $CS.stateReplacementsSource = [\"color\",\"textShadow\",\"fontSize\",\"bgColor\",\"bgGradient\",\"bgColorType\",\"bgGradientType\",\"borderColor\",\"borderWidth\",\"inBorderWidth\",\"inBorderColor\"];\n $CS.stateReplacements = [\"Color\",\"TextShadow\",\"FontSize\",\"BgColor\",\"BgGradient\",\"BgColorType\",\"BgGradientType\",\"BorderColor\",\"BorderWidth\",\"InBorderWidth\",\"InBorderColor\"];\n\n for (var i in $CS.stateReplacements) {\n if (!options[\"hover\"+$CS.stateReplacements[i]] && typeof options[\"hover\"+$CS.stateReplacements[i]]!='boolean') {\n options[\"hover\"+$CS.stateReplacements[i]] = options[$CS.stateReplacementsSource[i]];\n }\n if (!options[\"active\"+$CS.stateReplacements[i]] && typeof options[\"active\"+$CS.stateReplacements[i]]!='boolean') {\n options[\"active\"+$CS.stateReplacements[i]] = options[\"hover\"+$CS.stateReplacements[i]];\n }\n }\n\n\n\n var brd = options.borderRadius;\n\n var positions = {\n\n \"left-top\": {\n br:[0,0,brd,brd],\n arrowImg: $CS.buttonImagesUrl+'bubble-top-1.png',\n arrowWhiteImg: $CS.buttonImagesUrl+'bubble-top-1-white.png',\n op: function (s,o,ww) {\n return {\n x: o.offsetLeft+options.autoOpenMargin.x,\n y: o.offsetHeight+o.offsetTop+options.autoOpenMargin.y\n }\n }\n },\n\n \"center-top\": {\n br:[0,0,brd,brd],\n arrowImg: $CS.buttonImagesUrl+'bubble-top-1.png',\n arrowWhiteImg: $CS.buttonImagesUrl+'bubble-top-1-white.png',\n op: function (s,o,ww) {\n return {\n x: o.offsetLeft+o.offsetWidth/2-s[0]/2,\n y: o.offsetHeight+o.offsetTop+options.autoOpenMargin.y\n }\n }\n },\n\n \"right-top\": {\n br:[0,0,brd,brd],\n arrowImg: $CS.buttonImagesUrl+'bubble-top-2.png',\n arrowWhiteImg: $CS.buttonImagesUrl+'bubble-top-2-white.png',\n op: function (s,o,ww) {\n return {\n x: ww.innerWidth-options.autoOpenMargin.x-s[0],\n y: o.offsetHeight+o.offsetTop+options.autoOpenMargin.y\n }\n }\n },\n\n \"right-center\": {\n br:[brd,0,0,brd],\n vertical: true,\n arrowImg: $CS.buttonImagesUrl+'bubble-right.png',\n arrowWhiteImg: $CS.buttonImagesUrl+'bubble-right-white.png',\n op: function (s,o,ww) {\n return {\n x: ww.innerWidth-o.offsetWidth-options.autoOpenMargin.x-s[0],\n y: o.offsetTop+o.offsetHeight/2-s[1]/2\n }\n }\n },\n\n \"left-center\": {\n br:[0,brd,brd,0],\n vertical: true,\n arrowImg: $CS.buttonImagesUrl+'bubble-left.png',\n arrowWhiteImg: $CS.buttonImagesUrl+'bubble-left-white.png',\n op: function (s,o,ww) {\n return {\n x: o.offsetWidth+options.autoOpenMargin.x,\n y: o.offsetTop+o.offsetHeight/2-s[1]/2\n }\n }\n },\n\n \"right-bottom\": {\n br:[brd,brd,0,0],\n bottom: true,\n arrowImg: $CS.buttonImagesUrl+'bubble-bottom-1.png',\n arrowWhiteImg: $CS.buttonImagesUrl+'bubble-bottom-1-white.png',\n op: function (s,o,ww) {\n return {\n x: ww.innerWidth-options.autoOpenMargin.x-s[0],\n y: ww.innerHeight-options.autoOpenMargin.y-s[1]-o.offsetHeight\n }\n }\n },\n\n \"center-bottom\": {\n br:[brd,brd,0,0],\n bottom: true,\n arrowImg: $CS.buttonImagesUrl+'bubble-bottom-1.png',\n arrowWhiteImg: $CS.buttonImagesUrl+'bubble-bottom-1-white.png',\n op: function (s,o,ww) {\n return {\n x: o.offsetLeft+o.offsetWidth/2-s[0]/2,\n y: ww.innerHeight-options.autoOpenMargin.y-s[1]-o.offsetHeight\n }\n }\n\n },\n\n \"left-bottom\": {\n br:[brd,brd,0,0],\n bottom: true,\n arrowImg: $CS.buttonImagesUrl+'bubble-bottom-1.png',\n arrowWhiteImg: $CS.buttonImagesUrl+'bubble-bottom-1-white.png',\n\n op: function (s,o,ww) {\n return {\n x: o.offsetLeft+options.autoOpenMargin.x,\n y: ww.innerHeight-options.autoOpenMargin.y-s[1]-o.offsetHeight\n }\n }\n }\n\n }\n\n\n if (positions[options.position]) {\n\n var poptions = positions[options.position];\n var title = options.title;\n options.pos = poptions;\n\n if (poptions.vertical) {\n title = options.titleFlatten;\n }\n\n\n var statusClass = options.status==\"online\" ? 'consultsystems_online' : 'consultsystems_offline';\n\n var cbh = 'consultsystems_bubble_hidden';\n if (window.CSEditorMode && typeof options.showBubble==\"number\" && options.bubbleAutoHide!==0) {\n cbh = ''\n }\n\n var bubbleHtml = ''+\n ''+\n ''+\n ''+\n ''+\n '
'+\n ''+options.bubbleText+'
'+\n ''+\n ''+\n '';\n\n\n var html = ''+\n ''+\n ''+\n ''+\n ''+\n ''+title+''+\n ''+\n ''+\n ''+\n bubbleHtml+\n ''+\n '';\n\n\n var main = document.createElement('span');\n main.id=\"consultsystems_button_\"+$CS.buttonsCount;\n\n\n addClass(main, \"consultsystems_button_wrap consultsystems_button_\"+options.position);\n\n main.innerHTML = html;\n\n addEvent (window, \"scroll\", function(e){\n if (!$CS.fixedSupport){\n $CS.scrollTopButtons = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;\n main.style.marginTop = $CS.scrollTopButtons+\"px\";\n }\n });\n\n var bubbleButton = document.createElement('a');\n bubbleButton.id = 'bubble_but';\n addClass(bubbleButton, \"consultsystems_bubble_button\");\n bubbleButton.innerHTML = ''+options.bubbleButtonText+'';\n\n\n if (window.CSEditorMode) {\n var itm = 0;\n $el(\"export-preview\").appendChild(main);\n } else {\n var itm = 200;\n document.body.appendChild(main);\n }\n\n\n\n var $button = $CS.buttons[$CS.buttonsCount] = {\n wrap: main,\n spanpos: main.childNodes[0],\n options: options\n }\n\n $button.pos = $button.spanpos.childNodes[0];\n $button.button = $button.pos.childNodes[0];\n $button.bubble = $button.pos.childNodes[1];\n $button.bubbleClose = $button.bubble.childNodes[0].childNodes[0];\n $button.bubbleButton = $button.bubble.childNodes[0].childNodes[2].appendChild(bubbleButton);\n\n if ($CS.fixedSupport && !window.CSEditorMode) {\n $button.wrap.style.position = \"fixed\";\n $button.wrap.style.webkitTransform = \"translateZ(0)\";\n\n\n }\n\n if (!window.CSEditorMode) {\n addClass($button.pos,\"consultsystems_button_outscreen\");\n addClass($button.bubble,\"consultsystems_bubble_trans\");\n }\n\n\n\n setTimeout(function(){\n $button.size = sizes ($button.button);\n autoOffset ($button);\n\n\n removeClass($button.pos, \"consultsystems_button_outscreen\");\n if (!window.CSEditorMode) {\n var bubbleclose = getCookie(\"bubbleclose\");\n closeBubble ();\n if (!bubbleclose && (options.showBubble || typeof options.showBubble == \"number\") && options.status==\"online\") {\n setTimeout(openBubble, options.showBubble+1);\n setTimeout(showBubble, options.showBubble+25);\n if (options.bubbleAutoHide) {\n setTimeout(hideBubble, options.showBubble+options.bubbleAutoHide+5)\n }\n }\n } else {\n //closeBubble();\n if ((options.showBubble || typeof options.showBubble == \"number\") && options.bubbleAutoHide!==0) {\n openBubble();\n showBubble();\n }\n }\n },itm);\n\n\n\n var x = $CS.openPosition[0],\n y = $CS.openPosition[1];\n\n browserWindow();\n\n\n addEvent($button.button, \"mousedown\", function(e){\n addClass($button.button,\"consultsystems_button_border_active\")\n });\n\n addEvent(document, \"mouseup\", function(e) {\n removeClass($button.button,\"consultsystems_button_border_active\")\n });\n\n\n\n if (!window.CSEditorMode) {\n addEvent($button.button, \"click\", function(e){\n if (options.autoOpenPosition){\n var s = [ $CS.savedSize[0] || $CS.min[0], $CS.savedSize[1] || $CS.min[1] ];\n var op = poptions.op(s, $button.wrap, $CS.window);\n x = op.x, y = op.y;\n }\n\n $CS.lastOpener = $button.wrap;\n\n if(!$CS.isSafari){\n $CS.show (x, y, $button.wrap);\n }else{\n newWin = window.open(\"https://consultsystems.ru/labs/safarifix.php\",\"safarifix\",\"width=5,height=5,resizable=no,scrollbars=no,status=no\" );\n setTimeout(function() {\n $CS.show (x, y, $button.wrap);\n }, 1000)\n\n }\n\n\n hideBubble();\n\n\n });\n\n\n addEvent($button.bubbleButton, \"click\", function(e){\n if (options.autoOpenPosition){\n var s = [ $CS.savedSize[0] || $CS.min[0], $CS.savedSize[1] || $CS.min[1] ];\n var op = poptions.op(s, $button.wrap, $CS.window);\n x = op.x, y = op.y;\n }\n\n $CS.lastOpener = $button.wrap;\n\n if(!$CS.isSafari){\n $CS.show (x, y, $button.wrap);\n }else{\n newWin = window.open(\"https://consultsystems.ru/labs/safarifix.php\",\"safarifix\",\"width=5,height=5,resizable=no,scrollbars=no,status=no\" );\n setTimeout(function() {\n $CS.show (x, y, $button.wrap);\n }, 1000)\n\n }\n\n\n hideBubble();\n });\n\n addEvent($button.bubbleClose, \"click\", function(e){\n\n var d = new Date();\n var n = new Date(d.getTime()+1000*3600);\n\n setCookie(\"bubbleclose\",\"1\", {\n expires: n, path: \"/\"\n })\n\n hideBubble()\n });\n\n }\n\n\n\n var hideBubble = function () {\n addClass ($button.bubble, \"consultsystems_bubble_hidden\");\n setTimeout(closeBubble,500);\n }\n\n var showBubble = function () {\n removeClass ($button.bubble, \"consultsystems_bubble_hidden\")\n }\n var closeBubble = function () { addClass ($button.bubble, \"consultsystems_bubble_closed\") }\n var openBubble = function () {\n removeClass ($button.bubble, \"consultsystems_bubble_closed\");\n\n }\n\n\n\n /* styles */\n\n var addstyle = '';\n addstyle+='#'+main.id+' .consultsystems_button_in {background: '+options.bgColor+'}';\n\n if (window.CSEditorMode) {\n addstyle+='.consultsystems_button_right-bottom .consultsystems_bubble {top:auto;bottom:45px}';\n }\n\n if (options.bgColorType=='gradient' && !$CS.isIE6) {\n if (poptions.vertical) { var bgGradGen = gradientGenerator(options.bgGradient[0],options.bgGradient[1], 'x') }\n else { var bgGradGen = gradientGenerator(options.bgGradient[0],options.bgGradient[1], 'y') }\n addstyle+='#'+main.id+' .consultsystems_button_in {background: '+options.bgColor+';'+bgGradGen+'}';\n\n }\n\n\n\n var genBordersOut = borderGenerator(options.borderColor, options.borderWidth);\n var genBordersIn = borderGenerator(options.inBorderColor, options.inBorderWidth);\n\n addstyle+='#'+main.id+' .consultsystems_button_border {'+genBordersOut.raw+'}';\n addstyle+='#'+main.id+' .consultsystems_button_in {'+genBordersIn.raw+'}';\n\n\n var winOuter = borderGenerator(options.borderColor, options.borderWidth);\n var winInner = borderGenerator(options.inBorderColor, options.inBorderWidth);\n\n\n var brdrlength = winOuter.obj.top.width+winOuter.obj.bottom.width+winInner.obj.top.width+winInner.obj.bottom.width;\n $CS.newTitleHeight = $CS.titleHeight-brdrlength;\n\n\n addstyle+='#'+main.id+' .consultsystems_button_text {height: '+($CS.newTitleHeight)+'px !important; line-height: '+($CS.newTitleHeight-2)+'px !important;}'\n\n if (poptions.vertical) {\n addstyle+='#'+main.id+' .consultsystems_button_text {height: auto !important; width: '+$CS.newTitleHeight+'px}';\n }\n\n\n /* on Hover */\n addstyle+='#'+main.id+' .consultsystems_button_border:hover .consultsystems_button_text {color: '+options.hoverColor+'; text-shadow: '+options.hoverTextShadow+'; -moz-text-shadow: '+options.hoverTextShadow+'; -text-shadow: '+options.hoverTextShadow+' }';\n addstyle+='#'+main.id+' .consultsystems_button_border:hover .consultsystems_button_in {background: none; background: '+options.hoverBgColor+'}';\n if (options.hoverBgColorType==\"gradient\" && !$CS.isIE6) {\n if (poptions.vertical) { var hoverBgGradGen = gradientGenerator(options.hoverBgGradient[0],options.hoverBgGradient[1], 'x') }\n else { var hoverBgGradGen = gradientGenerator(options.hoverBgGradient[0],options.hoverBgGradient[1], 'y') }\n addstyle+='#'+main.id+' .consultsystems_button_border:hover .consultsystems_button_in {'+hoverBgGradGen+'}';\n }\n addstyle+='#'+main.id+' .consultsystems_button_border:hover {'+borderGenerator(options.hoverBorderColor, options.hoverBorderWidth).raw+'}';\n addstyle+='#'+main.id+' .consultsystems_button_border:hover .consultsystems_button_in {'+borderGenerator(options.hoverInBorderColor, options.hoverInBorderWidth).raw+'}';\n\n\n /* on Active */\n addstyle+='#'+main.id+' .consultsystems_button_border:active .consultsystems_button_text, #'+main.id+' .consultsystems_button_border_active .consultsystems_button_text, .consultsystems_button_border_active:hover .consultsystems_button_text {color: '+options.activeColor+' !important; text-shadow: '+options.activeTextShadow+'; -moz-text-shadow: '+options.activeTextShadow+'; -text-shadow: '+options.activeTextShadow+' }';\n addstyle+='#'+main.id+' .consultsystems_button_border:active .consultsystems_button_in, #'+main.id+' .consultsystems_button_border_active .consultsystems_button_in, .consultsystems_button_border_active:hover .consultsystems_button_in {background: none; background: '+options.activeBgColor+'}';\n\n\n if (options.activeBgColorType==\"gradient\" && !$CS.isIE6) {\n if (poptions.vertical) { var activeBgGradGen = gradientGenerator(options.activeBgGradient[0],options.activeBgGradient[1], 'x') }\n else { var activeBgGradGen = gradientGenerator(options.activeBgGradient[0],options.activeBgGradient[1], 'y') }\n addstyle+='#'+main.id+' .consultsystems_button_border:active .consultsystems_button_in, #'+main.id+' .consultsystems_button_border_active .consultsystems_button_in {background: none; '+activeBgGradGen+'}';\n }\n addstyle+='#'+main.id+' .consultsystems_button_border:active, #'+main.id+' .consultsystems_button_border_active {'+borderGenerator(options.activeBorderColor, options.activeBorderWidth).raw+'}';\n addstyle+='#'+main.id+' .consultsystems_button_border:active .consultsystems_button_in, #'+main.id+' .consultsystems_button_border_active .consultsystems_button_in {'+borderGenerator(options.activeInBorderColor, options.activeInBorderWidth).raw+'}';\n\n if (!options.icon) {\n options.iconImage = 'none';\n options.iconSize = [0,0];\n if (poptions.vertical) {\n addstyle+='#'+main.id+' .consultsystems_button_text {padding-bottom:5px}';\n } else {\n addstyle+='#'+main.id+' .consultsystems_button_text {padding-left:12px}';\n }\n }\n\n addstyle+='#'+main.id+' .consultsystems_button_icon {background: '+options.iconImage+'; width: '+options.iconSize[0]+'px; height: '+options.iconSize[1]+'px; }';\n\n var brdrad = poptions.br[0]+'px '+poptions.br[1]+'px '+poptions.br[2]+'px '+poptions.br[3]+'px';\n addstyle+='#'+main.id+' .consultsystems_button_border {border-radius: '+brdrad+';-moz-border-radius:'+brdrad+';-webkit-border-radius:'+brdrad+';}';\n addstyle+='#'+main.id+' .consultsystems_button_in {border-radius: '+brdrad+';-moz-border-radius:'+brdrad+';-webkit-border-radius:'+brdrad+';}';\n\n\n\n var statusTextPadding = 'padding-right: 85px';\n if (poptions.vertical) {\n statusTextPadding = 'padding-top: 85px'\n }\n\n if (options.status==\"online\") {\n var statusBg = options.statusOnlineImgX;\n if (poptions.vertical) { statusBg = options.statusOnlineImgY }\n } else {\n var statusBg = options.statusOfflineImgX;\n if (poptions.vertical) { statusBg = options.statusOfflineImgY }\n }\n\n var statusDsp = '';\n\n if ((options.statusShow==\"onlyIfOnline\" && options.status!='online') || options.statusShow=='hide') {\n statusBg = 'none';\n statusDsp = 'display: none';\n statusTextPadding = 'padding-right: 12px';\n if (poptions.vertical) {\n statusTextPadding = 'padding-top: 12px'\n }\n }\n\n\n addstyle+='#'+main.id+' .consultsystems_button_text {font-size: '+options.fontSize+' !important; color: '+options.textColor+' !important; text-shadow: '+options.textShadow+'; -moz-text-shadow: '+options.textShadow+'; -text-shadow: '+options.textShadow+'; '+statusTextPadding+' }';\n addstyle+='#'+main.id+' .consultsystems_button_status {background:'+statusBg+'; '+statusDsp+';}';\n addstyle+='#'+main.id+' .consultsystems_bubble {background:'+options.bubbleBg+'; border: solid 1px '+options.bubbleBorder+'}';\n\n\n var arrowImg = poptions.arrowImg;\n\n if (options.bubbleBg && (options.bubbleBg==\"white\" || options.bubbleBg.toLowerCase==\"#fff\" || options.bubbleBg.toLowerCase==\"#ffffff\")) {\n arrowImg = poptions.arrowWhiteImg;\n }\n\n addstyle+='#'+main.id+' .consultsystems_bubble_arrow {background-image:url('+arrowImg+')}';\n addstyle+='#'+main.id+' .consultsystems_bubble_button {background: '+options.bubbleButtonBg+'; color: '+options.bubbleButtonTextColor+'; border: solid 1px '+options.bubbleButtonBorder+'}';\n addstyle+='#'+main.id+' .consultsystems_bubble_button:hover {background: '+options.bubbleButtonHoverBg+'; color: '+options.bubbleButtonHoverTextColor+'; border: solid 1px '+options.bubbleButtonHoverBorder+'}';\n addstyle+='#'+main.id+' .consultsystems_bubble_button:active {background: '+options.bubbleButtonActiveBg+'; color: '+options.bubbleButtonActiveTextColor+'; border: solid 1px '+options.bubbleButtonActiveBorder+'}';\n\n $CS.defaultStyle+=addstyle;\n\n $CS.buttonsCount++;\n\n\n\n function autoOffset ($btn) {\n\n //if (!$CS.isIE7) {\n if ($btn.options.position==\"center-top\") {\n $btn.wrap.style.marginLeft = -($btn.size[0]/2)+\"px\"\n }\n\n if ($btn.options.position==\"center-bottom\") {\n $btn.wrap.style.marginLeft = -($btn.size[0]/2)+\"px\"\n }\n\n if ($btn.options.position==\"left-center\") {\n $btn.wrap.style.marginTop= -($btn.size[1]/2)+\"px\"\n }\n\n if ($btn.options.position==\"right-center\") {\n $btn.wrap.style.marginTop= -($btn.size[1]/2)+\"px\"\n }\n //}\n\n\n\n\n\n\n\n\n\n if ($btn.options.marginTop) {\n if (typeof $btn.options.marginTop == \"number\" && $btn.options.marginTop!==0) { $btn.options.marginTop+=\"px\" }\n $btn.spanpos.style.marginTop = $btn.options.marginTop;\n }\n\n if ($btn.options.marginRight) {\n if (typeof $btn.options.marginRight == \"number\" && $btn.options.marginRight!==0) { $btn.options.marginRight+=\"px\" }\n $btn.spanpos.style.marginRight = $btn.options.marginRight;\n }\n\n if ($btn.options.marginBottom) {\n if (typeof $btn.options.marginBottom == \"number\" && $btn.options.marginBottom!==0) { $btn.options.marginBottom+=\"px\" }\n $btn.spanpos.style.marginBottom = $btn.options.offsetBottom;\n }\n\n if ($btn.options.marginLeft) {\n if (typeof $btn.options.marginLeft == \"number\" && $btn.options.marginLeft!==0) { $btn.options.marginLeft+=\"px\" }\n $btn.spanpos.style.marginLeft = $btn.options.marginLeft;\n }\n\n\n if (!window.CSEditorMode) {\n if (poptions.bottom) {\n var bubbleHeight = $btn.bubble.offsetHeight;\n $btn.bubble.style.top = -bubbleHeight+\"px\"\n }\n }\n\n\n }\n\n function sizes (span) {\n return [span.offsetWidth, span.offsetHeight];\n }\n\n\n\n }\n\n return $button;\n }\n\n\n\n\n\n\n\n bindReady(function(){\n return false;\n $CS.fixedSupport = browserPositionFixed();\n\n if (!window.CSEditorMode) {\n\n\n\n\n var $button = $CS.button({ position: \"right-bottom\",\n marginTop: 0,\n marginRight: 0,\n marginBottom: 0,\n marginLeft: 0,\n toggleHide: true,\n textColor: \"#ffffff\",\n textShadow: \"1px 1px 1px rgba(0,0,0,.5)\",\n bgColor: \"#66cc00\",\n bgGradient: [\"#9de21d\", \"#5e9427\"],\n bgColorType: \"non-gradient\",\n bgGradientType: \"x\",\n borderColor: [\"#619829\"],\n borderWidth: 0,\n inBorderColor: [\"#BEEC69\",\"#ADD76C\",\"#9BC070\",\"#ADD76C\"],\n inBorderWidth: 0,\n hoverColor: \"#fff\",\n hoverTextShadow: \"1px 1px 1px rgba(0,0,0,.5)\",\n hoverBgColor: \"#5e9427\",\n hoverBgGradient: [\"#A8E640\", \"#79B938\"],\n hoverBorderColor: [\"#74B731\"],\n hoverBgColorType: \"gradient\",\n hoverInBorderColor: [\"#BEEC69\",\"#ADD76C\",\"#9BC070\",\"#ADD76C\"],\n activeColor: \"#fff\",\n activeTextShadow: \"1px 1px 1px rgba(0,0,0,.5)\",\n activeBgColor: \"#5e9427\",\n activeBgGradient: [\"#84C332\", \"#99D736\"],\n activeBorderColor: [\"#74B731\"],\n activeBgColorType: \"gradient\",\n activeInBorderColor: [\"#BEEC69\",\"#ADD76C\",\"#9BC070\",\"#ADD76C\"],\n icon: true,\n iconImage: 'url('+document.location.protocol+'//consultsystems.ru/script/im/button/icons.png) no-repeat -2px 1px',\n iconSize: [24,24],\n paddingFromIcon: 5,\n status: \"online\",\n statusShow: \"always\",\n statusSpanSize: 70,\n statusOnlineImgX: 'url('+$CS.buttonImagesUrl+'online.png) no-repeat 0px 0px',\n statusOnlineImgY: 'url('+$CS.buttonImagesUrl+'online.png) no-repeat 0px -30px',\n statusOfflineImgX: 'url('+$CS.buttonImagesUrl+'offline.png) no-repeat 0px 0px',\n statusOfflineImgY: 'url('+$CS.buttonImagesUrl+'offline.png) no-repeat 0px -30px',\n borderRadius: 5,\n title: \"Консультант\",\n titleFlatten: '
',\n showBubble: 2000,\n bubbleAutoHide: 0,\n bubbleText: \"Здравствуйте!
Чем могу помочь?\",\n bubbleBg: \"#F9F5F1\" });\n\n\n\n $CS.styleInit();\n\n if ($CS.preopen) {\n preopen($button);\n }\n\n var d = new Date();\n var random = d.getTime();\n\n if($CS.userStatus=='online'){\n getJSONP($CS.urlVisit+\"&sitehash=\"+$CSN.siteHash+\"&title=\" + encodeURIComponent(document.title.substr(0,100)) + \"&tid=\"+$CS.tarifId+\"&referer=\" + encodeURIComponent(document.referrer) + \"&rnd=\"+$CS.getUnixTime(),$CS.callbackVisit, function(data){\n\n });\n\n\n if($CS.tarifId!=2 && $CS.userReq){\n\n $CSN.urlCheckInterval = setInterval(function(){\n getJSONP($CS.urlCheck+'&maxid='+$CS.checkMaxId+'&site_id='+$CSN.siteId+'&rnd='+$CS.getUnixTime(),$CS.callbackCheck, function(data){\n if(data.maxid>0) $CS.checkMaxId = data.maxid;\n if (data.data) {\n if (!$CS.opened) {\n $CS.lastOpener = $button.wrap;\n $CS.show ($CS.savedOffset.x, $CS.savedOffset.y, $button.wrap);\n }\n }\n });\n },5000);\n\n }\n\n }\n\n }\n\n\n $CS.domReady = true;\n\n })\n\n\n function preopen ($button) {\n $CS.lastOpener = $button.wrap;\n $CS.show ($CS.savedOffset.x, $CS.savedOffset.y, $button.wrap);\n addClass($CS.lastOpener,\"consultsystems_button_preopen\");\n setTimeout(function(){\n removeClass($CS.lastOpener,\"consultsystems_button_preopen\");\n },555)\n }\n\n\n\n\n $CS.styleInit = function () {\n styleTag ($CS.defaultStyle);\n }\n\n\n\n\n\n\n\n\n\n $CS.fixed = function () { $CS.isFixed = true; return this; }\n $CS.static = function () { $CS.isFixed = false; return this; }\n\n\n $CS.show = function (x, y, from_x, from_y) {\n\n if ('ontouchstart' in document.documentElement) { $CS.touchSupport = true }\n\n $CS.opened = true;\n\n $CS.fixedSupport = browserPositionFixed(); //false; //\n\n if (!$CS.fixedSupport) {\n $CS.scrolltop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;\n }\n\n var ev = false;\n\n if (arguments.length==1 && isClickEvent(arguments[0])) { ev = arguments[0] }\n if (arguments.length==3 && isClickEvent(arguments[2])) { ev = arguments[2] }\n\n if (!ev && window.event) { ev = window.event }\n\n if (arguments.length==1 && typeof arguments[2] == \"object\" && arguments[2].nodeType==1) {\n var obj = arguments[0];\n x = from_x = obj.offsetLeft;\n y = from_y = obj.offsetTop;\n }\n\n else if (arguments.length==3 && typeof arguments[2] == \"object\" && arguments[2].nodeType==1) {\n var obj = arguments[2];\n from_x = obj.offsetLeft;\n from_y = obj.offsetTop;\n }\n\n else if (arguments.length==2 && ( ev && (ev.target || ev.srcElement) )) {\n var obj = ev.target || ev.srcElement;\n from_x = obj.offsetLeft;\n from_y = obj.offsetTop;\n }\n\n else if (!obj && ev && (ev.target || ev.srcElement)) {\n var obj = ev.target || ev.srcElement;\n }\n\n\n if (obj && obj.offsetWidth && obj.offsetHeight) {\n from_x = from_x + obj.offsetWidth/2;\n from_y = from_y + obj.offsetHeight/2;\n }\n\n\n $CS.opener = { x: from_x, y: from_y, fixed: (obj && hasClass(obj,$CS.fixedClass) || $CS.isFixed) ? true : false }\n\n if (!$CS.opener.fixed) {\n from_y -= (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);\n }\n\n x = x || from_x;\n y = y || from_y;\n\n $CS.offset = {\n x: $CS.savedOffset.x || x || 0,\n y: $CS.savedOffset.y || y || 0\n }\n\n if ($CS.savedOffset.x===0) { $CS.offset.x = 0 }\n if ($CS.savedOffset.y===0) { $CS.offset.y = 0 }\n\n var postop = $CS.offset.y;\n\n if (!$CS.fixedSupport && $CS.scrolltop) {\n postop+=$CS.scrolltop;\n }\n\n browserWindow();\n\n\n if (!$CS.div) {\n $CS.div = document.createElement('div');\n $CS.div.id=\"consultsystems\";\n\n $CS.div.style.width = $CS.min[0]+\"px\";\n $CS.div.style.height = $CS.min[1]+\"px\";\n\n var cstitle = $CSN.windowTitle;\n $CS.div.innerHTML = '';\n\n $CS.div.className = 'consultsystems';\n\n if ($CS.fixedSupport) {\n $CS.div.className+=' consultsystems_fixed'\n }\n\n if (window.CSEditorMode) {\n $el(\"export-preview\").appendChild($CS.div);\n $CS.div.style.position = \"absolute\"\n } else {\n document.body.appendChild($CS.div);\n }\n\n $CS.sizes = {\n titleHeight: 37,\n bottomHeight: 12\n }\n\n\n if (!window.CSEditorMode) {\n var dragndrop = new drag(\"dragndrop\");\n\n dragndrop.init({\n id: \"consultsystems_title\",\n target: $CS.div.id,\n min: $CS.min,\n max: $CS.max\n });\n\n var resizer = new drag(\"resize\");\n\n resizer.init({\n id: \"consultsystems_resizer\",\n target: $CS.div.id,\n min: $CS.min,\n max: $CS.max\n });\n }\n\n\n if (!$CS.fixedSupport) {\n addEvent (window, \"scroll\", function(e){\n $CS.scrolltop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;\n if ($CS.div){\n $CS.div.style.top = ($CS.offset.y + $CS.scrolltop)+\"px\";\n }\n });\n }\n\n addEvent (window, \"resize\", function(e){\n shake();\n });\n }\n\n\n else {\n removeClass($CS.div,\"consultsystems_closed\");\n }\n\n var w = $CS.savedSize[0] || parseFloat($CS.div.offsetWidth) || $CS.min[0];\n var h = $CS.savedSize[1] || parseFloat($CS.div.offsetHeight) || $CS.min[1];\n\n if ($CS.fixedSupport) {\n\n if ($CS.opener) {\n var ho = {};\n } else {\n var ho = hiddenOffsetDetermine(w,h);\n }\n\n divpos (from_x||ho.left||0, (from_y||ho.top||0)+$CS.scrolltop, 0, 0);\n\n var sht = 0;\n\n if (!window.CSEditorMode && !$CS.preopen){\n addClass($CS.div,\"consultsystems_hidden\");\n setTimeout(function(){addClass($CS.div,\"consultsystems_pre\")},2);\n sht = 15;\n }\n\n setTimeout(show,sht);\n }\n\n else {\n show();\n }\n\n\n function show () {\n\n if(typeof(window.webconsult_clientinfo) != \"undefined\"){\n\n getJSONP($CS.urlParams+\"&site_id=\"+$CSN.siteId+\"¶ms=\"+encodeURIComponent(JSON.stringify(window.webconsult_clientinfo))+\"&rnd=\"+$CS.getUnixTime(),$CS.callbackParams, function(data){\n\n });\n }\n\n if($CS.needReload) {\n document.getElementById('consultsystems_iframe').src = document.getElementById('consultsystems_iframe').src;\n $CS.needReload = false;\n }\n postop = $CS.offset.y+$CS.scrolltop;\n divpos ($CS.offset.x, postop, w, h);\n addClass($CS.div,\"consultsystems_visible\");\n setTimeout(function(){removeClass($CS.div,\"consultsystems_pre\");adjust()},333);\n var d = new Date();\n var n = new Date(d.getTime()+1000*3600);\n setCookie(\"bubbleclose\",\"1\", {\n expires: n, path: \"/\"\n });\n\n\n\n shake ();\n\n }\n\n\n\n\n\n\n\n if ($CS.toggleHide) {\n $CS.hideTarget();\n\n\n }\n\n }\n\n $CS.showWindow = $CS.show;\n\n $CS.hide = function (x, y, from_x, from_y) {\n\n if (window.CSEditorMode) {return false;}\n\n $CS.opened = false;\n $CS.preopen = false;\n\n var d = new Date();\n var n = new Date(d.getTime()+1000*3600*24*30);\n setCookie(\"consultsystemswindow\", \"hide|\"+$CS.savedOffset.x+\"|\"+$CS.savedOffset.y+\"|\"+$CS.savedSize[0]+\"|\"+$CS.savedSize[1], {\n expires: n, path: \"/\"\n });\n\n if ($CS.div) {\n\n var with_arguments = true;\n\n if (arguments.length==1 && typeof arguments[2] == \"object\" && arguments[2].nodeType==1) {\n var obj = arguments[0];\n x = from_x = obj.offsetLeft;\n y = from_y = obj.offsetTop;\n }\n\n else if (arguments.length==3 && typeof arguments[2] == \"object\" && arguments[2].nodeType==1) {\n var obj = arguments[2];\n from_x = obj.offsetLeft;\n from_y = obj.offsetTop;\n }\n\n else {\n with_arguments = false;\n from_x = $CS.opener.x;\n from_y = $CS.opener.y;\n }\n\n\n if (!$CS.opener.fixed) {\n from_y -= (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);\n }\n\n\n x = x || from_x;\n y = y || from_y;\n\n var w = parseFloat($CS.div.offsetWidth) || $CS.min[0];\n var h = parseFloat($CS.div.offsetHeight) || $CS.min[1];\n\n if ($CS.fixedSupport) {\n addClass($CS.div,\"consultsystems_pre\");\n removeClass($CS.div,\"consultsystems_visible\");\n setTimeout(hide,5);\n } else {\n hide();\n addClass($CS.div,\"consultsystems_closed\")\n }\n }\n\n function hide (){\n\n if (with_arguments) {\n var ho = hiddenOffsetDetermine(w,h);\n } else {\n var ho = {}\n }\n\n\n divpos (from_x||ho.left||0, (from_y||ho.top||0)+$CS.scrolltop, 0, 0);\n addClass($CS.div,\"consultsystems_hidden\");\n setTimeout(function(){\n removeClass($CS.div,\"consultsystems_pre\");\n addClass($CS.div,\"consultsystems_closed\");\n $CS.div.style.width = w+\"px\";\n $CS.div.style.height = h+\"px\";\n },333);\n }\n\n if ($CS.toggleHide) {\n $CS.showTarget ();\n }\n }\n\n $CS.hideWindow = $CS.hide;\n\n $CS.endDialog = function(){\n\n if(true || confirm(\"Вы действительно хотите закончить диалог?\")){\n getJSONP($CS.urlClose+\"&site_id=\"+$CSN.siteId+\"&rnd=\"+$CS.getUnixTime(),$CS.callbackClose, function(data){\n if(data.data==true){\n $CS.hideWindow();\n $CS.needReload = true;\n }\n });\n }\n }\n\n $CS.toggle = function () {\n if ($CS.opened) {\n $CS.hide.apply(this, arguments);\n } else {\n $CS.show.apply(this, arguments);\n }\n }\n\n $CS.showTarget = function () {\n $CS.openTarget();\n setTimeout(function(){\n removeClass ($CS.lastOpener, \"consultsystems_button_hidden\");\n },5)\n\n }\n\n $CS.getUnixTime = function () {\n d = new Date();\n return d.getTime();\n }\n\n $CS.hideTarget = function () {\n addClass ($CS.lastOpener, \"consultsystems_button_hidden\");\n setTimeout($CS.closeTarget, 500)\n }\n\n $CS.openTarget = function () { removeClass ($CS.lastOpener, \"consultsystems_button_closed\") }\n $CS.closeTarget = function () { addClass ($CS.lastOpener, \"consultsystems_button_closed\") }\n\n $CS.iframeRestyle = function () {\n window.$CSI = window.consultsystems_iframe.ConsultSystemsIframe;\n $CSI.style.fontMessage = $CS.style.windowFontMessage;\n $CSI.style.fontClient = $CS.style.windowFontClient;\n $CSI.style.fontCons = $CS.style.windowFontCons;\n $CSI.style.fontSystem = $CS.style.windowFontSystem;\n $CSI.sendOnEnter = $CS.style.windowSendOnEnter;\n $CSI.restyle();\n }\n\n\n $CS.iframeonload = function () {\n addClass($el(\"consultsystems_iframe_loading\"),\"consultsystems_iframe_loaded\");\n $CS.iframe = window.consultsystems_iframe;\n if (window.CSEditorMode && window.consultsystems_iframe) {\n $CS.iframeRestyle()\n }\n }\n\n function isClickEvent (e) {\n return (e && typeof e==\"object\" && e.type==\"click\");\n }\n\n\n function divpos (x,y,w,h) {\n $CS.div.style.left = x+\"px\";\n $CS.div.style.top = y+\"px\";\n $CS.div.style.width = w+\"px\";\n $CS.div.style.height = h+\"px\";\n }\n\n\n\n function hiddenOffsetDetermine (w,h) {\n var offsetLeft = $CS.offset.x;\n var offsetRight = $CS.window.innerWidth - $CS.offset.x - (parseFloat($CS.div.offsetWidth) || $CS.min[0])\n\n var off = {};\n\n if (offsetLeft>=offsetRight) {\n off.top = 0;\n off.left = $CS.window.innerWidth+w;\n } else {\n off.top = 0;\n off.left = -w;\n }\n\n return off;\n }\n\n\n\n\n function shake () {\n browserWindow();\n\n var w = $CS.savedSize[0] || parseFloat($CS.div.offsetWidth) || $CS.min[0];\n var h = $CS.savedSize[1] || parseFloat($CS.div.offsetHeight) || $CS.min[1];\n\n if (w > $CS.window.innerWidth) { w = $CS.window.innerWidth; }\n if (h > $CS.window.innerHeight) { h = $CS.window.innerHeight; }\n\n if (w < $CS.min[0]) {w = $CS.min[0]}\n if (h < $CS.min[1]) {h = $CS.min[1]}\n\n $CS.div.style.width = w+\"px\";\n $CS.div.style.height= h+\"px\";\n\n $CS.savedSize = [w,h];\n\n autoDrag ({target: $CS.div, width: w, height: h}, $CS.offset.x, $CS.offset.y+$CS.scrolltop);\n }\n\n\n\n\n\n\n\n function $el (e) {\n return document.getElementById(e);\n }\n\n\n\n\n\n function adjust () {\n if ($CS.isIE7) {\n var iframeHeight = ($CS.div.offsetHeight||parseInt($CS.div.style.height))-($CS.sizes.titleHeight+$CS.sizes.bottomHeight);\n $el(\"consultsystems_iframe\").style.height = iframeHeight+\"px\";\n $el(\"consultsystems_iframe_div\").style.height = (iframeHeight+4)+\"px\";\n $el(\"consultsystems_iframe_over\").style.height = iframeHeight+\"px\";\n $el(\"consultsystems_iframe_loading\").style.height = iframeHeight+\"px\";\n }\n\n\n }\n\n\n function addClass(o, c){\n if (o) {\n var re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\", \"g\")\n if (re.test(o.className)) return\n o.className = (o.className + \" \" + c).replace(/\\s+/g, \" \").replace(/(^ | $)/g, \"\")\n }\n }\n\n function removeClass(o, c){\n if (o) {\n var re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\", \"g\")\n o.className = o.className.replace(re, \"$1\").replace(/\\s+/g, \" \").replace(/(^ | $)/g, \"\")\n }\n }\n\n function hasClass (obj, className) {\n if (typeof obj == 'undefined' || obj==null || !RegExp) { return false; }\n var re = new RegExp(\"(^|\\\\s)\" + className + \"(\\\\s|$)\");\n if (typeof(obj)==\"string\") {\n return re.test(obj);\n }\n else if (typeof(obj)==\"object\" && obj.className) {\n return re.test(obj.className);\n }\n return false;\n }\n\n\n function browserWindow () {\n\n var winw, winh,\n dbody = document.body,\n delem = document.documentElement;\n ww = window;\n\n if (dbody && dbody.offsetWidth) {\n winw = dbody.offsetWidth;\n winh = dbody.offsetHeight;\n }\n if (document.compatMode=='CSS1Compat' && delem && delem.offsetWidth ) {\n winw = delem.offsetWidth;\n winh = delem.offsetHeight;\n }\n if (ww.innerWidth && ww.innerHeight) {\n winw = ww.innerWidth;\n winh = ww.innerHeight;\n }\n\n //console.log(dbody.offsetHeight, delem.offsetHeight, ww.innerHeight)\n\n var dcw = dbody.clientWidth;\n var dch = dbody.clientHeight;\n var ddcw = delem.clientWidth;\n var ddch = delem.clientHeight;\n\n $CS.window.width = winw;\n $CS.window.height = winh;\n\n if (ddcw > dcw && ddcw < winw) {\n $CS.window.innerWidth = ddcw;\n } else {\n $CS.window.innerWidth = dcw;\n }\n\n\n if ((ddch > dch && ddch <= winh) || (ddch < dch && ddch > 0)) {\n $CS.window.innerHeight = ddch;\n } else {\n $CS.window.innerHeight = dch;\n }\n\n //console.log($CS.window.innerHeight)\n }\n\n function browserPositionFixed () {\n var testDiv = document.createElement(\"div\");\n testDiv.id = \"testingPositionFixed\";\n testDiv.style.position = \"fixed\";\n testDiv.style.top = \"0px\";\n testDiv.style.right = \"0px\";\n document.body.appendChild(testDiv);\n var offset = 1;\n var supported = false;\n if (typeof testDiv.offsetTop == \"number\") {\n if (testDiv.offsetTop != null) {\n if (testDiv.offsetTop != \"undefined\") {\n offset = parseInt(testDiv.offsetTop);\n }\n }\n }\n if (offset === 0) {\n supported = true;\n }\n\n document.body.removeChild(testDiv)\n return supported;\n }\n\n function browserQuirksMode (){\n if (document.createElement) {\n var el = document.createElement('div');\n if (el && el.style) {\n el.style.width = '1';\n }\n return el.style.width === '1px';\n }\n }\n\n function drag (type) {\n this.type = type;\n this.md = false;\n }\n\n drag.prototype = {\n\n init: function(params) {\n this.params = params;\n this.elem = $el(this.params.id);\n this.target = $el(this.params.target);\n this.elem.onmousedown = this._mouseDown.bind(this);\n\n if ($CS.touchSupport) {\n this.elem.ontouchstart = this._mouseDown.bind(this);\n }\n\n },\n\n _mouseDown: function(e) {\n\n this.md = true;\n\n browserWindow ();\n\n e = e || window.event;\n\n this.elem.onselectstart = function(){ return false };\n this._event_docMouseMove = this._docMouseMove.bind(this);\n this._event_docMouseUp = this._docMouseUp.bind(this);\n\n if (this.onstart) this.onstart();\n\n this.x = e.clientX||e.pageX;\n this.y = e.clientY||e.pageY;\n\n if (e.type==\"touchstart\") {\n this.x = event.touches[0].pageX;\n this.y = event.touches[0].pageY;\n }\n\n this.left = parseFloat(this.target.offsetLeft);\n this.top = parseFloat(this.target.offsetTop);\n\n this.width = parseFloat(this.target.offsetWidth);\n this.height = parseFloat(this.target.offsetHeight);\n\n addEvent(document, 'mousemove', this._event_docMouseMove);\n addEvent(document, 'mouseup', this._event_docMouseUp);\n\n if ($CS.touchSupport) {\n addEvent(document, 'touchmove', this._event_docMouseMove);\n addEvent(document, 'touchend', this._event_docMouseUp);\n }\n\n $CS.offset = {\n x: this.left,\n y: this.top\n }\n\n addClass($el(\"consultsystems_iframe_over\"),\"consultsystems_iframe_over_show\");\n return false;\n },\n\n _docMouseMove: function(e) {\n if (this.md) {\n this.setValuesClick(e);\n if (this.ondrag) this.ondrag();\n }\n },\n\n _docMouseUp: function(e) {\n this.md = false;\n\n removeEvent(document, 'mousemove', this._event_docMouseMove);\n if ($CS.touchSupport){removeEvent(document, 'touchmove', this._event_docMouseMove)}\n if (this.onstop) this.onstop();\n\n removeEvent(document, 'mouseup', this._event_docMouseUp);\n if ($CS.touchSupport){removeEvent(document, 'touchend', this._event_docMouseMove)}\n\n this.width = parseFloat(this.target.offsetWidth);\n this.height = parseFloat(this.target.offsetHeight);\n removeClass($el(\"consultsystems_iframe_over\"),\"consultsystems_iframe_over_show\");\n },\n\n setValuesClick: function(e){\n\n this.mouseX = e.clientX||e.pageX;\n this.mouseY = e.clientY||e.pageY;\n\n if (e.type==\"touchmove\") {\n this.mouseX = event.touches[0].pageX;\n this.mouseY = event.touches[0].pageY;\n }\n\n this.X = this.left + this.mouseX - this.x;\n this.Y = this.top + this.mouseY - this.y;\n\n\n if (this.X<0) {this.X = 0}\n if (this.Y<0) {this.Y = 0}\n\n\n if (this.type==\"dragndrop\") {\n autoDrag (this, this.X, this.Y);\n }\n\n\n else if (this.type==\"resize\" ) {\n\n var w = e.clientX||e.pageX;\n var h = e.clientY||e.pageY;\n\n if (e.type==\"touchmove\") {\n w = event.touches[0].pageX;\n h = event.touches[0].pageY - (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);\n }\n\n w = w - this.left + 5;\n h = h - this.top + 5;\n\n\n autoResize (this, w, h);\n }\n\n }\n }\n\n function autoDrag (wdg, x, y) {\n\n\n if (y - $CS.scrolltop < 0) { y = $CS.scrolltop }\n if (x + wdg.width > $CS.window.innerWidth) { x = $CS.window.innerWidth - wdg.width }\n if (y + wdg.height - $CS.scrolltop > $CS.window.innerHeight) { y = $CS.window.innerHeight - wdg.height + $CS.scrolltop }\n\n $CS.offset = {\n x: x,\n y: y-$CS.scrolltop\n }\n\n $CS.savedOffset = $CS.offset;\n\n wdg.target.style.left = x + \"px\";\n wdg.target.style.top = y + \"px\";\n\n save();\n }\n\n\n function autoResize (wdg, w, h) {\n var oh = h;\n h = h+$CS.scrolltop;\n\n if (w < wdg.params.min[0]) {w = wdg.params.min[0]}\n if (w > wdg.params.max[0]) {w = wdg.params.max[0]}\n\n if (h > wdg.params.max[1]) {h = wdg.params.max[1]}\n if (h < wdg.params.min[1]) {h = wdg.params.min[1]}\n\n if (w + $CS.offset.x > $CS.window.innerWidth) { w = $CS.window.innerWidth - $CS.offset.x }\n if (h + $CS.offset.y > $CS.window.innerHeight) { h = $CS.window.innerHeight - $CS.offset.y }\n\n wdg.X = wdg.left;\n wdg.Y = wdg.top-$CS.scrolltop;\n\n if (w>$CS.window.innerWidth ) { w = $CS.window.innerWidth; }\n if (h>$CS.window.innerHeight ) { h = $CS.window.innerHeight; }\n\n if (w<$CS.min[0]){w=$CS.min[0]}\n if (h<$CS.min[1]){h=$CS.min[1]}\n\n wdg.target.style.width = w+\"px\";\n wdg.target.style.height = h+\"px\";\n\n $CS.offset = {\n x: wdg.X,\n y: wdg.Y\n }\n\n $CS.savedSize = [w,h];\n\n adjust ();\n\n save();\n }\n\n\n var save = debounce(function(){\n var d = new Date();\n var n = new Date(d.getTime()+1000*3600*24*30);\n setCookie(\"consultsystemswindow\", \"open|\"+$CS.savedOffset.x+\"|\"+$CS.savedOffset.y+\"|\"+$CS.savedSize[0]+\"|\"+$CS.savedSize[1], {\n expires: n, path: \"/\"\n });\n },333);\n\n\n\n // возвращает cookie если есть или undefined\n function getCookie(name) {\n var matches = document.cookie.match(new RegExp(\n \"(?:^|; )\" + name.replace(/([\\.$?*|{}\\(\\)\\[\\]\\\\\\/\\+^])/g, '\\\\$1') + \"=([^;]*)\"\n ))\n return matches ? decodeURIComponent(matches[1]) : undefined\n }\n\n // уcтанавливает cookie\n function setCookie(name, value, props) {\n props = props || {}\n var exp = props.expires\n if (typeof exp == \"number\" && exp) {\n var d = new Date()\n d.setTime(d.getTime() + exp*1000)\n exp = props.expires = d\n }\n if(exp && exp.toUTCString) { props.expires = exp.toUTCString() }\n\n value = encodeURIComponent(value)\n var updatedCookie = name + \"=\" + value\n for(var propName in props){\n updatedCookie += \"; \" + propName\n var propValue = props[propName]\n if(propValue !== true){ updatedCookie += \"=\" + propValue }\n }\n document.cookie = updatedCookie\n\n }\n\n // удаляет cookie\n function deleteCookie(name) {\n setCookie(name, null, { expires: -1 })\n }\n\n function debounce ( fn, timeout, invokeAsap, ctx ) {\n\n if(arguments.length == 3 && typeof invokeAsap != 'boolean') {\n ctx = invokeAsap;\n invokeAsap = false;\n }\n\n var timer;\n\n return function() {\n var args = arguments;\n ctx = ctx || this;\n\n invokeAsap && !timer && fn.apply(ctx, args);\n clearTimeout(timer);\n timer = setTimeout(function() {\n !invokeAsap && fn.apply(ctx, args);\n timer = null;\n }, timeout);\n\n }\n }\n\n function addEvent(elem, evType, fn) {\n if (elem.addEventListener) {\n elem.addEventListener(evType, fn, false);\n }\n else if (elem.attachEvent) {\n elem.attachEvent('on' + evType, fn)\n }\n else {\n elem['on' + evType] = fn\n }\n }\n\n function removeEvent(element, type, handler) {\n if (element.removeEventListener) {\n element.removeEventListener(type, handler, false);\n } else {\n if (element.events && element.events[type]) {\n delete element.events[type][handler.$$guid];\n }\n }\n }\n\n\n\n\n function styleTag (val) {\n\n var head = document.getElementsByTagName('head')[0];\n\n var styletag = $el('consultsystems_style');\n if (window.CSEditorMode) {\n if (styletag) {\n head.removeChild(styletag);\n styletag = false;\n }\n }\n\n if (styletag) {\n var append = true;\n var style = styletag;\n } else {\n var append = false;\n var style = document.createElement('style');\n style.type = 'text/css';\n style.id = 'consultsystems_style';\n }\n\n var rules = document.createTextNode(val);\n if (style.styleSheet) { style.styleSheet.cssText = rules.nodeValue }\n else { style.appendChild(rules) }\n\n if (!append) {\n head.appendChild(style);\n }\n }\n\n\n if (!Function.prototype.bind) {\n Function.prototype.bind = function () {\n\n function newApply(Constructor, args) {\n var i = 0, len = args.length, argNames = [];\n while (i < len) {\n argNames.push(\"arg\" + i);\n i++;\n }\n argNames = argNames.join(\",\");\n return Function(\"Constructor\", argNames, \"return new Constructor(\" + argNames + \")\").apply(window, [Constructor].concat(args));\n }\n\n return function (boundThis) {\n var targetFunc = this, boundArgs = Array.prototype.slice.call(arguments, 1);\n function boundFunc() {\n var allArgs, len;\n function NOP() {}\n if (boundFunc._protoMagic) {\n boundFunc._protoMagic = false;\n NOP.prototype = this;\n NOP.prototype.constructor = targetFunc;\n return new NOP;\n }\n else {\n allArgs = boundArgs.concat(Array.prototype.slice.call(arguments));\n len = allArgs.length;\n }\n if (this && this.constructor == boundFunc) {\n boundFunc._protoMagic = true;\n NOP.prototype = len > 1 ? newApply(targetFunc, allArgs) : (len ? new targetFunc(allArgs[0]) : new targetFunc);\n boundFunc.prototype = new NOP;\n boundFunc.prototype.constructor = boundFunc;\n return new boundFunc;\n }\n return len > 1 ? targetFunc.apply(boundThis, allArgs) : (len ? targetFunc.call(boundThis, allArgs[0]) : targetFunc.call(boundThis));\n }\n boundFunc._protoMagic = false;\n return boundFunc;\n };\n }();\n }\n\n\n function extend (what, add) {\n if (!add) { add = {} };\n if (typeof what == \"object\" && typeof add == \"object\") {\n for (var prop in add) {\n what[prop] = add[prop];\n }\n return what;\n }\n }\n\n\n\n\n if(document.getElementsByClassName) {\n\n getElementsByClass = function(classList, node) {\n return (node || document).getElementsByClassName(classList)\n }\n\n } else {\n\n getElementsByClass = function(classList, node) {\n var node = node || document,\n list = node.getElementsByTagName('*'),\n length = list.length,\n classArray = classList.split(/\\s+/),\n classes = classArray.length,\n result = [], i,j\n for(i = 0; i < length; i++) {\n for(j = 0; j < classes; j++) {\n if(list[i].className.search('\\\\b' + classArray[j] + '\\\\b') != -1) {\n result.push(list[i])\n break\n }\n }\n }\n\n return result\n }\n }\n\n\n\n\n function bindReady(handler){\n\n var called = false\n\n function ready() {\n if (called) return\n called = true\n handler()\n }\n\n if ( document.addEventListener ) {\n document.addEventListener( \"DOMContentLoaded\", function(){\n ready()\n }, false )\n } else if ( document.attachEvent ) {\n\n\n if ( document.documentElement.doScroll && window == window.top ) {\n function tryScroll(){\n if (called) return\n if (!document.body) return\n try {\n document.documentElement.doScroll(\"left\")\n ready()\n } catch(e) {\n setTimeout(tryScroll, 0)\n }\n }\n tryScroll()\n }\n\n\n document.attachEvent(\"onreadystatechange\", function(){\n if ( document.readyState === \"complete\" ) {\n ready()\n }\n })\n }\n if (window.addEventListener)\n window.addEventListener('load', ready, false)\n else if (window.attachEvent)\n window.attachEvent('onload', ready)\n }\n\n\n function gradientGenerator (from, to, dir) {\n\n var gr ='background: -moz-linear-gradient('+(dir == \"y\"?'top':'left')+', '+from+' 0%, '+to+' 100%);';\n gr+='background: -webkit-gradient(linear, '+(dir == \"y\"?'left top, left bottom':'left top, right top')+', color-stop(0%,'+from+'), color-stop(100%,'+to+'));';\n gr+='background: -webkit-linear-gradient('+(dir == \"y\"?'top':'left')+', '+from+' 0%, '+to+' 100%);';\n gr+='background: -o-linear-gradient('+(dir == \"y\"?'top':'left')+', '+from+' 0%, '+to+' 100%);';\n gr+='background: -ms-linear-gradient('+(dir == \"y\"?'top':'left')+', '+from+' 0%, '+to+' 100%);';\n gr+='background: linear-gradient('+(dir == \"y\"?'top':'left')+', '+from+' 0%, '+to+' 100%);';\n gr+=\"filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='\"+from+\"', endColorstr='\"+to+\"', GradientType=\"+(dir == 'y'? 0:1)+\" );\";\n\n return gr;\n }\n\n\n\n function borderGenerator (colors, widths) {\n var borders = {\n top: {}, right: {}, bottom: {}, left: {}\n };\n\n if (typeof colors == \"number\" || typeof colors == \"string\") {\n borders[\"top\"].color = colors;\n borders[\"right\"].color = colors;\n borders[\"bottom\"].color = colors;\n borders[\"left\"].color = colors;\n } else if (typeof colors == \"object\" && colors[0]) {\n var firstcolor = colors[0];\n borders[\"top\"].color = colors[0]||firstcolor;\n borders[\"right\"].color = colors[1]||firstcolor;\n borders[\"bottom\"].color = colors[2]||firstcolor;\n borders[\"left\"].color = colors[3]||firstcolor;\n }\n\n\n if (typeof widths == \"number\" || typeof widths == \"string\") {\n borders[\"top\"].width = widths||0;\n borders[\"right\"].width = widths||0;\n borders[\"bottom\"].width = widths||0;\n borders[\"left\"].width = widths||0;\n } else if (typeof widths == \"object\" && (widths[0]||widths[0]===0)) {\n var firstborder = widths[0]||0;\n borders[\"top\"].width = widths[0]||0;\n borders[\"right\"].width = widths[1]||firstborder||0;\n borders[\"bottom\"].width = widths[2]||firstborder||0;\n borders[\"left\"].width = widths[3]||firstborder||0;\n }\n\n var raw = 'border-top: solid '+borders[\"top\"].width+\"px \"+borders[\"top\"].color+';';\n raw+= 'border-right: solid '+borders[\"right\"].width+\"px \"+borders[\"right\"].color+';';\n raw+= 'border-bottom: solid '+borders[\"bottom\"].width+\"px \"+borders[\"bottom\"].color+';';\n raw+= 'border-left: solid '+borders[\"left\"].width+\"px \"+borders[\"left\"].color+';';\n\n return {\n obj: borders,\n raw: raw\n };\n }\n\n\n function getJSONP(url, callback, success) {\n\n var script = document.createElement('script'),\n head = document.getElementsByTagName('head')[0]\n || document.documentElement;\n\n window[callback] = function(data) {\n head.removeChild(script);\n success && success(data);\n window[callback] = null;\n };\n\n script.src = url.replace('callback=?', 'callback=' + callback);\n\n head.appendChild(script);\n\n }\n\n\n\n\n\n})();\n","/*!\n * jQuery Form Plugin\n * version: 2.52 (07-DEC-2010)\n * @requires jQuery v1.3.2 or later\n *\n * Examples and documentation at: http://malsup.com/jquery/form/\n * Dual licensed under the MIT and GPL licenses:\n * http://www.opensource.org/licenses/mit-license.php\n * http://www.gnu.org/licenses/gpl.html\n */\n;(function($) {\n\n/*\n\tUsage Note:\n\t-----------\n\tDo not use both ajaxSubmit and ajaxForm on the same form. These\n\tfunctions are intended to be exclusive. Use ajaxSubmit if you want\n\tto bind your own submit handler to the form. For example,\n\n\t$(document).ready(function() {\n\t\t$('#myForm').bind('submit', function(e) {\n\t\t\te.preventDefault(); // <-- important\n\t\t\t$(this).ajaxSubmit({\n\t\t\t\ttarget: '#output'\n\t\t\t});\n\t\t});\n\t});\n\n\tUse ajaxForm when you want the plugin to manage all the event binding\n\tfor you. For example,\n\n\t$(document).ready(function() {\n\t\t$('#myForm').ajaxForm({\n\t\t\ttarget: '#output'\n\t\t});\n\t});\n\n\tWhen using ajaxForm, the ajaxSubmit function will be invoked for you\n\tat the appropriate time.\n*/\n\n/**\n * ajaxSubmit() provides a mechanism for immediately submitting\n * an HTML form using AJAX.\n */\n$.fn.ajaxSubmit = function(options) {\n\t// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)\n\tif (!this.length) {\n\t\tlog('ajaxSubmit: skipping submit process - no element selected');\n\t\treturn this;\n\t}\n\n\tif (typeof options == 'function') {\n\t\toptions = { success: options };\n\t}\n\n\tvar action = this.attr('action');\n\tvar url = (typeof action === 'string') ? $.trim(action) : '';\n\tif (url) {\n\t\t// clean url (don't include hash vaue)\n\t\turl = (url.match(/^([^#]+)/)||[])[1];\n\t}\n\turl = url || window.location.href || '';\n\n\toptions = $.extend(true, {\n\t\turl: url,\n\t\ttype: this.attr('method') || 'GET',\n\t\tiframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'\n\t}, options);\n\n\t// hook for manipulating the form data before it is extracted;\n\t// convenient for use with rich editors like tinyMCE or FCKEditor\n\tvar veto = {};\n\tthis.trigger('form-pre-serialize', [this, options, veto]);\n\tif (veto.veto) {\n\t\tlog('ajaxSubmit: submit vetoed via form-pre-serialize trigger');\n\t\treturn this;\n\t}\n\n\t// provide opportunity to alter form data before it is serialized\n\tif (options.beforeSerialize && options.beforeSerialize(this, options) === false) {\n\t\tlog('ajaxSubmit: submit aborted via beforeSerialize callback');\n\t\treturn this;\n\t}\n\n\tvar n,v,a = this.formToArray(options.semantic);\n\tif (options.data) {\n\t\toptions.extraData = options.data;\n\t\tfor (n in options.data) {\n\t\t\tif(options.data[n] instanceof Array) {\n\t\t\t\tfor (var k in options.data[n]) {\n\t\t\t\t\ta.push( { name: n, value: options.data[n][k] } );\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tv = options.data[n];\n\t\t\t\tv = $.isFunction(v) ? v() : v; // if value is fn, invoke it\n\t\t\t\ta.push( { name: n, value: v } );\n\t\t\t}\n\t\t}\n\t}\n\n\t// give pre-submit callback an opportunity to abort the submit\n\tif (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {\n\t\tlog('ajaxSubmit: submit aborted via beforeSubmit callback');\n\t\treturn this;\n\t}\n\n\t// fire vetoable 'validate' event\n\tthis.trigger('form-submit-validate', [a, this, options, veto]);\n\tif (veto.veto) {\n\t\tlog('ajaxSubmit: submit vetoed via form-submit-validate trigger');\n\t\treturn this;\n\t}\n\n\tvar q = $.param(a);\n\n\tif (options.type.toUpperCase() == 'GET') {\n\t\toptions.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;\n\t\toptions.data = null; // data is null for 'get'\n\t}\n\telse {\n\t\toptions.data = q; // data is the query string for 'post'\n\t}\n\n\tvar $form = this, callbacks = [];\n\tif (options.resetForm) {\n\t\tcallbacks.push(function() { $form.resetForm(); });\n\t}\n\tif (options.clearForm) {\n\t\tcallbacks.push(function() { $form.clearForm(); });\n\t}\n\n\t// perform a load on the target only if dataType is not provided\n\tif (!options.dataType && options.target) {\n\t\tvar oldSuccess = options.success || function(){};\n\t\tcallbacks.push(function(data) {\n\t\t\tvar fn = options.replaceTarget ? 'replaceWith' : 'html';\n\t\t\t$(options.target)[fn](data).each(oldSuccess, arguments);\n\t\t});\n\t}\n\telse if (options.success) {\n\t\tcallbacks.push(options.success);\n\t}\n\n\toptions.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg\n\t\tvar context = options.context || options; // jQuery 1.4+ supports scope context \n\t\tfor (var i=0, max=callbacks.length; i < max; i++) {\n\t\t\tcallbacks[i].apply(context, [data, status, xhr || $form, $form]);\n\t\t}\n\t};\n\n\t// are there files to upload?\n\tvar fileInputs = $('input:file', this).length > 0;\n\tvar mp = 'multipart/form-data';\n\tvar multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);\n\n\t// options.iframe allows user to force iframe mode\n\t// 06-NOV-09: now defaulting to iframe mode if file input is detected\n if (options.iframe !== false && (fileInputs || options.iframe || multipart)) {\n\t // hack to fix Safari hang (thanks to Tim Molendijk for this)\n\t // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d\n\t if (options.closeKeepAlive) {\n\t\t $.get(options.closeKeepAlive, fileUpload);\n\t\t}\n\t else {\n\t\t fileUpload();\n\t\t}\n }\n else {\n\t $.ajax(options);\n }\n\n\t// fire 'notify' event\n\tthis.trigger('form-submit-notify', [this, options]);\n\treturn this;\n\n\n\t// private function for handling file uploads (hat tip to YAHOO!)\n\tfunction fileUpload() {\n\t\tvar form = $form[0];\n\n\t\tif ($(':input[name=submit],:input[id=submit]', form).length) {\n\t\t\t// if there is an input with a name or id of 'submit' then we won't be\n\t\t\t// able to invoke the submit fn on the form (at least not x-browser)\n\t\t\talert('Error: Form elements must not have name or id of \"submit\".');\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tvar s = $.extend(true, {}, $.ajaxSettings, options);\n\t\ts.context = s.context || s;\n\t\tvar id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id;\n\t\twindow[fn] = function() {\n\t\t\tvar f = $io.data('form-plugin-onload');\n\t\t\tif (f) {\n\t\t\t\tf();\n\t\t\t\twindow[fn] = undefined;\n\t\t\t\ttry { delete window[fn]; } catch(e){}\n\t\t\t}\n\t\t}\n\t\tvar $io = $('');\n\t\tvar io = $io[0];\n\n\t\t$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });\n\n\t\tvar xhr = { // mock object\n\t\t\taborted: 0,\n\t\t\tresponseText: null,\n\t\t\tresponseXML: null,\n\t\t\tstatus: 0,\n\t\t\tstatusText: 'n/a',\n\t\t\tgetAllResponseHeaders: function() {},\n\t\t\tgetResponseHeader: function() {},\n\t\t\tsetRequestHeader: function() {},\n\t\t\tabort: function() {\n\t\t\t\tthis.aborted = 1;\n\t\t\t\t$io.attr('src', s.iframeSrc); // abort op in progress\n\t\t\t}\n\t\t};\n\n\t\tvar g = s.global;\n\t\t// trigger ajax global events so that activity/block indicators work like normal\n\t\tif (g && ! $.active++) {\n\t\t\t$.event.trigger(\"ajaxStart\");\n\t\t}\n\t\tif (g) {\n\t\t\t$.event.trigger(\"ajaxSend\", [xhr, s]);\n\t\t}\n\n\t\tif (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {\n\t\t\tif (s.global) { \n\t\t\t\t$.active--;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (xhr.aborted) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar cbInvoked = false;\n\t\tvar timedOut = 0;\n\n\t\t// add submitting element to data if we know it\n\t\tvar sub = form.clk;\n\t\tif (sub) {\n\t\t\tvar n = sub.name;\n\t\t\tif (n && !sub.disabled) {\n\t\t\t\ts.extraData = s.extraData || {};\n\t\t\t\ts.extraData[n] = sub.value;\n\t\t\t\tif (sub.type == \"image\") {\n\t\t\t\t\ts.extraData[n+'.x'] = form.clk_x;\n\t\t\t\t\ts.extraData[n+'.y'] = form.clk_y;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// take a breath so that pending repaints get some cpu time before the upload starts\n\t\tfunction doSubmit() {\n\t\t\t// make sure form attrs are set\n\t\t\tvar t = $form.attr('target'), a = $form.attr('action');\n\n\t\t\t// update form attrs in IE friendly way\n\t\t\tform.setAttribute('target',id);\n\t\t\tif (form.getAttribute('method') != 'POST') {\n\t\t\t\tform.setAttribute('method', 'POST');\n\t\t\t}\n\t\t\tif (form.getAttribute('action') != s.url) {\n\t\t\t\tform.setAttribute('action', s.url);\n\t\t\t}\n\n\t\t\t// ie borks in some cases when setting encoding\n\t\t\tif (! s.skipEncodingOverride) {\n\t\t\t\t$form.attr({\n\t\t\t\t\tencoding: 'multipart/form-data',\n\t\t\t\t\tenctype: 'multipart/form-data'\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// support timout\n\t\t\tif (s.timeout) {\n\t\t\t\tsetTimeout(function() { timedOut = true; cb(); }, s.timeout);\n\t\t\t}\n\n\t\t\t// add \"extra\" data to form if provided in options\n\t\t\tvar extraInputs = [];\n\t\t\ttry {\n\t\t\t\tif (s.extraData) {\n\t\t\t\t\tfor (var n in s.extraData) {\n\t\t\t\t\t\textraInputs.push(\n\t\t\t\t\t\t\t$('')\n\t\t\t\t\t\t\t\t.appendTo(form)[0]);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// add iframe to doc and submit the form\n\t\t\t\t$io.appendTo('body');\n\t\t\t\t$io.data('form-plugin-onload', cb);\n\t\t\t\tform.submit();\n\t\t\t}\n\t\t\tfinally {\n\t\t\t\t// reset attrs and remove \"extra\" input elements\n\t\t\t\tform.setAttribute('action',a);\n\t\t\t\tif(t) {\n\t\t\t\t\tform.setAttribute('target', t);\n\t\t\t\t} else {\n\t\t\t\t\t$form.removeAttr('target');\n\t\t\t\t}\n\t\t\t\t$(extraInputs).remove();\n\t\t\t}\n\t\t}\n\n\t\tif (s.forceSync) {\n\t\t\tdoSubmit();\n\t\t}\n\t\telse {\n\t\t\tsetTimeout(doSubmit, 10); // this lets dom updates render\n\t\t}\n\t\n\t\tvar data, doc, domCheckCount = 50;\n\n\t\tfunction cb() {\n\t\t\tif (cbInvoked) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$io.removeData('form-plugin-onload');\n\t\t\t\n\t\t\tvar ok = true;\n\t\t\ttry {\n\t\t\t\tif (timedOut) {\n\t\t\t\t\tthrow 'timeout';\n\t\t\t\t}\n\t\t\t\t// extract the server response from the iframe\n\t\t\t\tdoc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;\n\t\t\t\t\n\t\t\t\tvar isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);\n\t\t\t\tlog('isXml='+isXml);\n\t\t\t\tif (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {\n\t\t\t\t\tif (--domCheckCount) {\n\t\t\t\t\t\t// in some browsers (Opera) the iframe DOM is not always traversable when\n\t\t\t\t\t\t// the onload callback fires, so we loop a bit to accommodate\n\t\t\t\t\t\tlog('requeing onLoad callback, DOM not available');\n\t\t\t\t\t\tsetTimeout(cb, 250);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// let this fall through because server response could be an empty document\n\t\t\t\t\t//log('Could not access iframe DOM after mutiple tries.');\n\t\t\t\t\t//throw 'DOMException: not available';\n\t\t\t\t}\n\n\t\t\t\t//log('response detected');\n\t\t\t\tcbInvoked = true;\n\t\t\t\txhr.responseText = doc.documentElement ? doc.documentElement.innerHTML : null; \n\t\t\t\txhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;\n\t\t\t\txhr.getResponseHeader = function(header){\n\t\t\t\t\tvar headers = {'content-type': s.dataType};\n\t\t\t\t\treturn headers[header];\n\t\t\t\t};\n\n\t\t\t\tvar scr = /(json|script)/.test(s.dataType);\n\t\t\t\tif (scr || s.textarea) {\n\t\t\t\t\t// see if user embedded response in textarea\n\t\t\t\t\tvar ta = doc.getElementsByTagName('textarea')[0];\n\t\t\t\t\tif (ta) {\n\t\t\t\t\t\txhr.responseText = ta.value;\n\t\t\t\t\t}\n\t\t\t\t\telse if (scr) {\n\t\t\t\t\t\t// account for browsers injecting pre around json response\n\t\t\t\t\t\tvar pre = doc.getElementsByTagName('pre')[0];\n\t\t\t\t\t\tvar b = doc.getElementsByTagName('body')[0];\n\t\t\t\t\t\tif (pre) {\n\t\t\t\t\t\t\txhr.responseText = pre.textContent;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (b) {\n\t\t\t\t\t\t\txhr.responseText = b.innerHTML;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\t\t\t \n\t\t\t\t}\n\t\t\t\telse if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {\n\t\t\t\t\txhr.responseXML = toXml(xhr.responseText);\n\t\t\t\t}\n\t\t\t\tdata = $.httpData(xhr, s.dataType);\n\t\t\t}\n\t\t\tcatch(e){\n\t\t\t\tlog('error caught:',e);\n\t\t\t\tok = false;\n\t\t\t\txhr.error = e;\n\t\t\t\t$.handleError(s, xhr, 'error', e);\n\t\t\t}\n\t\t\t\n\t\t\tif (xhr.aborted) {\n\t\t\t\tlog('upload aborted');\n\t\t\t\tok = false;\n\t\t\t}\n\n\t\t\t// ordering of these callbacks/triggers is odd, but that's how $.ajax does it\n\t\t\tif (ok) {\n\t\t\t\ts.success.call(s.context, data, 'success', xhr);\n\t\t\t\tif (g) {\n\t\t\t\t\t$.event.trigger(\"ajaxSuccess\", [xhr, s]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (g) {\n\t\t\t\t$.event.trigger(\"ajaxComplete\", [xhr, s]);\n\t\t\t}\n\t\t\tif (g && ! --$.active) {\n\t\t\t\t$.event.trigger(\"ajaxStop\");\n\t\t\t}\n\t\t\tif (s.complete) {\n\t\t\t\ts.complete.call(s.context, xhr, ok ? 'success' : 'error');\n\t\t\t}\n\n\t\t\t// clean up\n\t\t\tsetTimeout(function() {\n\t\t\t\t$io.removeData('form-plugin-onload');\n\t\t\t\t$io.remove();\n\t\t\t\txhr.responseXML = null;\n\t\t\t}, 100);\n\t\t}\n\n\t\tfunction toXml(s, doc) {\n\t\t\tif (window.ActiveXObject) {\n\t\t\t\tdoc = new ActiveXObject('Microsoft.XMLDOM');\n\t\t\t\tdoc.async = 'false';\n\t\t\t\tdoc.loadXML(s);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tdoc = (new DOMParser()).parseFromString(s, 'text/xml');\n\t\t\t}\n\t\t\treturn (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;\n\t\t}\n\t}\n};\n\n/**\n * ajaxForm() provides a mechanism for fully automating form submission.\n *\n * The advantages of using this method instead of ajaxSubmit() are:\n *\n * 1: This method will include coordinates for elements (if the element\n *\tis used to submit the form).\n * 2. This method will include the submit element's name/value data (for the element that was\n *\tused to submit the form).\n * 3. This method binds the submit() method to the form for you.\n *\n * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely\n * passes the options argument along after properly binding events for submit elements and\n * the form itself.\n */\n$.fn.ajaxForm = function(options) {\n\t// in jQuery 1.3+ we can fix mistakes with the ready state\n\tif (this.length === 0) {\n\t\tvar o = { s: this.selector, c: this.context };\n\t\tif (!$.isReady && o.s) {\n\t\t\tlog('DOM not ready, queuing ajaxForm');\n\t\t\t$(function() {\n\t\t\t\t$(o.s,o.c).ajaxForm(options);\n\t\t\t});\n\t\t\treturn this;\n\t\t}\n\t\t// is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()\n\t\tlog('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));\n\t\treturn this;\n\t}\n\t\n\treturn this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {\n\t\tif (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed\n\t\t\te.preventDefault();\n\t\t\t$(this).ajaxSubmit(options);\n\t\t}\n\t}).bind('click.form-plugin', function(e) {\n\t\tvar target = e.target;\n\t\tvar $el = $(target);\n\t\tif (!($el.is(\":submit,input:image\"))) {\n\t\t\t// is this a child element of the submit el? (ex: a span within a button)\n\t\t\tvar t = $el.closest(':submit');\n\t\t\tif (t.length == 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttarget = t[0];\n\t\t}\n\t\tvar form = this;\n\t\tform.clk = target;\n\t\tif (target.type == 'image') {\n\t\t\tif (e.offsetX != undefined) {\n\t\t\t\tform.clk_x = e.offsetX;\n\t\t\t\tform.clk_y = e.offsetY;\n\t\t\t} else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin\n\t\t\t\tvar offset = $el.offset();\n\t\t\t\tform.clk_x = e.pageX - offset.left;\n\t\t\t\tform.clk_y = e.pageY - offset.top;\n\t\t\t} else {\n\t\t\t\tform.clk_x = e.pageX - target.offsetLeft;\n\t\t\t\tform.clk_y = e.pageY - target.offsetTop;\n\t\t\t}\n\t\t}\n\t\t// clear form vars\n\t\tsetTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);\n\t});\n};\n\n// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm\n$.fn.ajaxFormUnbind = function() {\n\treturn this.unbind('submit.form-plugin click.form-plugin');\n};\n\n/**\n * formToArray() gathers form element data into an array of objects that can\n * be passed to any of the following ajax functions: $.get, $.post, or load.\n * Each object in the array has both a 'name' and 'value' property. An example of\n * an array for a simple login form might be:\n *\n * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]\n *\n * It is this array that is passed to pre-submit callback functions provided to the\n * ajaxSubmit() and ajaxForm() methods.\n */\n$.fn.formToArray = function(semantic) {\n\tvar a = [];\n\tif (this.length === 0) {\n\t\treturn a;\n\t}\n\n\tvar form = this[0];\n\tvar els = semantic ? form.getElementsByTagName('*') : form.elements;\n\tif (!els) {\n\t\treturn a;\n\t}\n\t\n\tvar i,j,n,v,el,max,jmax;\n\tfor(i=0, max=els.length; i < max; i++) {\n\t\tel = els[i];\n\t\tn = el.name;\n\t\tif (!n) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (semantic && form.clk && el.type == \"image\") {\n\t\t\t// handle image inputs on the fly when semantic == true\n\t\t\tif(!el.disabled && form.clk == el) {\n\t\t\t\ta.push({name: n, value: $(el).val()});\n\t\t\t\ta.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tv = $.fieldValue(el, true);\n\t\tif (v && v.constructor == Array) {\n\t\t\tfor(j=0, jmax=v.length; j < jmax; j++) {\n\t\t\t\ta.push({name: n, value: v[j]});\n\t\t\t}\n\t\t}\n\t\telse if (v !== null && typeof v != 'undefined') {\n\t\t\ta.push({name: n, value: v});\n\t\t}\n\t}\n\n\tif (!semantic && form.clk) {\n\t\t// input type=='image' are not found in elements array! handle it here\n\t\tvar $input = $(form.clk), input = $input[0];\n\t\tn = input.name;\n\t\tif (n && !input.disabled && input.type == 'image') {\n\t\t\ta.push({name: n, value: $input.val()});\n\t\t\ta.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});\n\t\t}\n\t}\n\treturn a;\n};\n\n/**\n * Serializes form data into a 'submittable' string. This method will return a string\n * in the format: name1=value1&name2=value2\n */\n$.fn.formSerialize = function(semantic) {\n\t//hand off to jQuery.param for proper encoding\n\treturn $.param(this.formToArray(semantic));\n};\n\n/**\n * Serializes all field elements in the jQuery object into a query string.\n * This method will return a string in the format: name1=value1&name2=value2\n */\n$.fn.fieldSerialize = function(successful) {\n\tvar a = [];\n\tthis.each(function() {\n\t\tvar n = this.name;\n\t\tif (!n) {\n\t\t\treturn;\n\t\t}\n\t\tvar v = $.fieldValue(this, successful);\n\t\tif (v && v.constructor == Array) {\n\t\t\tfor (var i=0,max=v.length; i < max; i++) {\n\t\t\t\ta.push({name: n, value: v[i]});\n\t\t\t}\n\t\t}\n\t\telse if (v !== null && typeof v != 'undefined') {\n\t\t\ta.push({name: this.name, value: v});\n\t\t}\n\t});\n\t//hand off to jQuery.param for proper encoding\n\treturn $.param(a);\n};\n\n/**\n * Returns the value(s) of the element in the matched set. For example, consider the following form:\n *\n * \n *\n * var v = $(':text').fieldValue();\n * // if no values are entered into the text inputs\n * v == ['','']\n * // if values entered into the text inputs are 'foo' and 'bar'\n * v == ['foo','bar']\n *\n * var v = $(':checkbox').fieldValue();\n * // if neither checkbox is checked\n * v === undefined\n * // if both checkboxes are checked\n * v == ['B1', 'B2']\n *\n * var v = $(':radio').fieldValue();\n * // if neither radio is checked\n * v === undefined\n * // if first radio is checked\n * v == ['C1']\n *\n * The successful argument controls whether or not the field element must be 'successful'\n * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).\n * The default value of the successful argument is true. If this value is false the value(s)\n * for each element is returned.\n *\n * Note: This method *always* returns an array. If no valid value can be determined the\n *\t array will be empty, otherwise it will contain one or more values.\n */\n$.fn.fieldValue = function(successful) {\n\tfor (var val=[], i=0, max=this.length; i < max; i++) {\n\t\tvar el = this[i];\n\t\tvar v = $.fieldValue(el, successful);\n\t\tif (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {\n\t\t\tcontinue;\n\t\t}\n\t\tv.constructor == Array ? $.merge(val, v) : val.push(v);\n\t}\n\treturn val;\n};\n\n/**\n * Returns the value of the field element.\n */\n$.fieldValue = function(el, successful) {\n\tvar n = el.name, t = el.type, tag = el.tagName.toLowerCase();\n\tif (successful === undefined) {\n\t\tsuccessful = true;\n\t}\n\n\tif (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||\n\t\t(t == 'checkbox' || t == 'radio') && !el.checked ||\n\t\t(t == 'submit' || t == 'image') && el.form && el.form.clk != el ||\n\t\ttag == 'select' && el.selectedIndex == -1)) {\n\t\t\treturn null;\n\t}\n\n\tif (tag == 'select') {\n\t\tvar index = el.selectedIndex;\n\t\tif (index < 0) {\n\t\t\treturn null;\n\t\t}\n\t\tvar a = [], ops = el.options;\n\t\tvar one = (t == 'select-one');\n\t\tvar max = (one ? index+1 : ops.length);\n\t\tfor(var i=(one ? index : 0); i < max; i++) {\n\t\t\tvar op = ops[i];\n\t\t\tif (op.selected) {\n\t\t\t\tvar v = op.value;\n\t\t\t\tif (!v) { // extra pain for IE...\n\t\t\t\t\tv = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;\n\t\t\t\t}\n\t\t\t\tif (one) {\n\t\t\t\t\treturn v;\n\t\t\t\t}\n\t\t\t\ta.push(v);\n\t\t\t}\n\t\t}\n\t\treturn a;\n\t}\n\treturn $(el).val();\n};\n\n/**\n * Clears the form data. Takes the following actions on the form's input fields:\n * - input text fields will have their 'value' property set to the empty string\n * - select elements will have their 'selectedIndex' property set to -1\n * - checkbox and radio inputs will have their 'checked' property set to false\n * - inputs of type submit, button, reset, and hidden will *not* be effected\n * - button elements will *not* be effected\n */\n$.fn.clearForm = function() {\n\treturn this.each(function() {\n\t\t$('input,select,textarea', this).clearFields();\n\t});\n};\n\n/**\n * Clears the selected form elements.\n */\n$.fn.clearFields = $.fn.clearInputs = function() {\n\treturn this.each(function() {\n\t\tvar t = this.type, tag = this.tagName.toLowerCase();\n\t\tif (t == 'text' || t == 'password' || tag == 'textarea') {\n\t\t\tthis.value = '';\n\t\t}\n\t\telse if (t == 'checkbox' || t == 'radio') {\n\t\t\tthis.checked = false;\n\t\t}\n\t\telse if (tag == 'select') {\n\t\t\tthis.selectedIndex = -1;\n\t\t}\n\t});\n};\n\n/**\n * Resets the form data. Causes all form elements to be reset to their original value.\n */\n$.fn.resetForm = function() {\n\treturn this.each(function() {\n\t\t// guard against an input with the name of 'reset'\n\t\t// note that IE reports the reset function as an 'object'\n\t\tif (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {\n\t\t\tthis.reset();\n\t\t}\n\t});\n};\n\n/**\n * Enables or disables any matching elements.\n */\n$.fn.enable = function(b) {\n\tif (b === undefined) {\n\t\tb = true;\n\t}\n\treturn this.each(function() {\n\t\tthis.disabled = !b;\n\t});\n};\n\n/**\n * Checks/unchecks any matching checkboxes or radio buttons and\n * selects/deselects and matching option elements.\n */\n$.fn.selected = function(select) {\n\tif (select === undefined) {\n\t\tselect = true;\n\t}\n\treturn this.each(function() {\n\t\tvar t = this.type;\n\t\tif (t == 'checkbox' || t == 'radio') {\n\t\t\tthis.checked = select;\n\t\t}\n\t\telse if (this.tagName.toLowerCase() == 'option') {\n\t\t\tvar $sel = $(this).parent('select');\n\t\t\tif (select && $sel[0] && $sel[0].type == 'select-one') {\n\t\t\t\t// deselect all other options\n\t\t\t\t$sel.find('option').selected(false);\n\t\t\t}\n\t\t\tthis.selected = select;\n\t\t}\n\t});\n};\n\n// helper fn for console logging\n// set $.fn.ajaxSubmit.debug to true to enable debug logging\nfunction log() {\n\tif ($.fn.ajaxSubmit.debug) {\n\t\tvar msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');\n\t\tif (window.console && window.console.log) {\n\t\t\twindow.console.log(msg);\n\t\t}\n\t\telse if (window.opera && window.opera.postError) {\n\t\t\twindow.opera.postError(msg);\n\t\t}\n\t}\n};\n\n})(jQuery);\n\n\n/*\n * jQuery validation plug-in 1.7\n *\n * http://bassistance.de/jquery-plugins/jquery-plugin-validation/\n * http://docs.jquery.com/Plugins/Validation\n *\n * Copyright (c) 2006 - 2008 Jörn Zaefferer\n *\n * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $\n *\n * Dual licensed under the MIT and GPL licenses:\n * http://www.opensource.org/licenses/mit-license.php\n * http://www.gnu.org/licenses/gpl.html\n */\n(function($){$.extend($.fn,{validate:function(options){if(!this.length){options&&options.debug&&window.console&&console.warn(\"nothing selected, can't validate, returning nothing\");return;}var validator=$.data(this[0],'validator');if(validator){return validator;}validator=new $.validator(options,this[0]);$.data(this[0],'validator',validator);if(validator.settings.onsubmit){this.find(\"input, button\").filter(\".cancel\").click(function(){validator.cancelSubmit=true;});if(validator.settings.submitHandler){this.find(\"input, button\").filter(\":submit\").click(function(){validator.submitButton=this;});}this.submit(function(event){if(validator.settings.debug)event.preventDefault();function handle(){if(validator.settings.submitHandler){if(validator.submitButton){var hidden=$(\"\").attr(\"name\",validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);}validator.settings.submitHandler.call(validator,validator.currentForm);if(validator.submitButton){hidden.remove();}return false;}return true;}if(validator.cancelSubmit){validator.cancelSubmit=false;return handle();}if(validator.form()){if(validator.pendingRequest){validator.formSubmitted=true;return false;}return handle();}else{validator.focusInvalid();return false;}});}return validator;},valid:function(){if($(this[0]).is('form')){return this.validate().form();}else{var valid=true;var validator=$(this[0].form).validate();this.each(function(){valid&=validator.element(this);});return valid;}},removeAttrs:function(attributes){var result={},$element=this;$.each(attributes.split(/\\s/),function(index,value){result[value]=$element.attr(value);$element.removeAttr(value);});return result;},rules:function(command,argument){var element=this[0];if(command){var settings=$.data(element.form,'validator').settings;var staticRules=settings.rules;var existingRules=$.validator.staticRules(element);switch(command){case\"add\":$.extend(existingRules,$.validator.normalizeRule(argument));staticRules[element.name]=existingRules;if(argument.messages)settings.messages[element.name]=$.extend(settings.messages[element.name],argument.messages);break;case\"remove\":if(!argument){delete staticRules[element.name];return existingRules;}var filtered={};$.each(argument.split(/\\s/),function(index,method){filtered[method]=existingRules[method];delete existingRules[method];});return filtered;}}var data=$.validator.normalizeRules($.extend({},$.validator.metadataRules(element),$.validator.classRules(element),$.validator.attributeRules(element),$.validator.staticRules(element)),element);if(data.required){var param=data.required;delete data.required;data=$.extend({required:param},data);}return data;}});$.extend($.expr[\":\"],{blank:function(a){return!$.trim(\"\"+a.value);},filled:function(a){return!!$.trim(\"\"+a.value);},unchecked:function(a){return!a.checked;}});$.validator=function(options,form){this.settings=$.extend(true,{},$.validator.defaults,options);this.currentForm=form;this.init();};$.validator.format=function(source,params){if(arguments.length==1)return function(){var args=$.makeArray(arguments);args.unshift(source);return $.validator.format.apply(this,args);};if(arguments.length>2&¶ms.constructor!=Array){params=$.makeArray(arguments).slice(1);}if(params.constructor!=Array){params=[params];}$.each(params,function(i,n){source=source.replace(new RegExp(\"\\\\{\"+i+\"\\\\}\",\"g\"),n);});return source;};$.extend($.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:\"error\",validClass:\"valid\",errorElement:\"label\",focusInvalid:true,errorContainer:$([]),errorLabelContainer:$([]),onsubmit:true,ignore:[],ignoreTitle:false,onfocusin:function(element){this.lastActive=element;if(this.settings.focusCleanup&&!this.blockFocusCleanup){this.settings.unhighlight&&this.settings.unhighlight.call(this,element,this.settings.errorClass,this.settings.validClass);this.errorsFor(element).hide();}},onfocusout:function(element){if(!this.checkable(element)&&(element.name in this.submitted||!this.optional(element))){this.element(element);}},onkeyup:function(element){if(element.name in this.submitted||element==this.lastElement){this.element(element);}},onclick:function(element){if(element.name in this.submitted)this.element(element);else if(element.parentNode.name in this.submitted)this.element(element.parentNode);},highlight:function(element,errorClass,validClass){$(element).addClass(errorClass).removeClass(validClass);},unhighlight:function(element,errorClass,validClass){$(element).removeClass(errorClass).addClass(validClass);}},setDefaults:function(settings){$.extend($.validator.defaults,settings);},messages:{required:\"This field is required.\",remote:\"Please fix this field.\",email:\"Please enter a valid email address.\",url:\"Please enter a valid URL.\",date:\"Please enter a valid date.\",dateISO:\"Please enter a valid date (ISO).\",number:\"Please enter a valid number.\",digits:\"Please enter only digits.\",creditcard:\"Please enter a valid credit card number.\",equalTo:\"Please enter the same value again.\",accept:\"Please enter a value with a valid extension.\",maxlength:$.validator.format(\"Please enter no more than {0} characters.\"),minlength:$.validator.format(\"Please enter at least {0} characters.\"),rangelength:$.validator.format(\"Please enter a value between {0} and {1} characters long.\"),range:$.validator.format(\"Please enter a value between {0} and {1}.\"),max:$.validator.format(\"Please enter a value less than or equal to {0}.\"),min:$.validator.format(\"Please enter a value greater than or equal to {0}.\")},autoCreateRanges:false,prototype:{init:function(){this.labelContainer=$(this.settings.errorLabelContainer);this.errorContext=this.labelContainer.length&&this.labelContainer||$(this.currentForm);this.containers=$(this.settings.errorContainer).add(this.settings.errorLabelContainer);this.submitted={};this.valueCache={};this.pendingRequest=0;this.pending={};this.invalid={};this.reset();var groups=(this.groups={});$.each(this.settings.groups,function(key,value){$.each(value.split(/\\s/),function(index,name){groups[name]=key;});});var rules=this.settings.rules;$.each(rules,function(key,value){rules[key]=$.validator.normalizeRule(value);});function delegate(event){var validator=$.data(this[0].form,\"validator\"),eventType=\"on\"+event.type.replace(/^validate/,\"\");validator.settings[eventType]&&validator.settings[eventType].call(validator,this[0]);}$(this.currentForm).validateDelegate(\":text, :password, :file, select, textarea\",\"focusin focusout keyup\",delegate).validateDelegate(\":radio, :checkbox, select, option\",\"click\",delegate);if(this.settings.invalidHandler)$(this.currentForm).bind(\"invalid-form.validate\",this.settings.invalidHandler);},form:function(){this.checkForm();$.extend(this.submitted,this.errorMap);this.invalid=$.extend({},this.errorMap);if(!this.valid())$(this.currentForm).triggerHandler(\"invalid-form\",[this]);this.showErrors();return this.valid();},checkForm:function(){this.prepareForm();for(var i=0,elements=(this.currentElements=this.elements());elements[i];i++){this.check(elements[i]);}return this.valid();},element:function(element){element=this.clean(element);this.lastElement=element;this.prepareElement(element);this.currentElements=$(element);var result=this.check(element);if(result){delete this.invalid[element.name];}else{this.invalid[element.name]=true;}if(!this.numberOfInvalids()){this.toHide=this.toHide.add(this.containers);}this.showErrors();return result;},showErrors:function(errors){if(errors){$.extend(this.errorMap,errors);this.errorList=[];for(var name in errors){this.errorList.push({message:errors[name],element:this.findByName(name)[0]});}this.successList=$.grep(this.successList,function(element){return!(element.name in errors);});}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors();},resetForm:function(){if($.fn.resetForm)$(this.currentForm).resetForm();this.submitted={};this.prepareForm();this.hideErrors();this.elements().removeClass(this.settings.errorClass);},numberOfInvalids:function(){return this.objectLength(this.invalid);},objectLength:function(obj){var count=0;for(var i in obj)count++;return count;},hideErrors:function(){this.addWrapper(this.toHide).hide();},valid:function(){return this.size()==0;},size:function(){return this.errorList.length;},focusInvalid:function(){if(this.settings.focusInvalid){try{$(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(\":visible\").focus().trigger(\"focusin\");}catch(e){}}},findLastActive:function(){var lastActive=this.lastActive;return lastActive&&$.grep(this.errorList,function(n){return n.element.name==lastActive.name;}).length==1&&lastActive;},elements:function(){var validator=this,rulesCache={};return $([]).add(this.currentForm.elements).filter(\":input\").not(\":submit, :reset, :image, [disabled]\").not(this.settings.ignore).filter(function(){!this.name&&validator.settings.debug&&window.console&&console.error(\"%o has no name assigned\",this);if(this.name in rulesCache||!validator.objectLength($(this).rules()))return false;rulesCache[this.name]=true;return true;});},clean:function(selector){return $(selector)[0];},errors:function(){return $(this.settings.errorElement+\".\"+this.settings.errorClass,this.errorContext);},reset:function(){this.successList=[];this.errorList=[];this.errorMap={};this.toShow=$([]);this.toHide=$([]);this.currentElements=$([]);},prepareForm:function(){this.reset();this.toHide=this.errors().add(this.containers);},prepareElement:function(element){this.reset();this.toHide=this.errorsFor(element);},check:function(element){element=this.clean(element);if(this.checkable(element)){element=this.findByName(element.name)[0];}var rules=$(element).rules();var dependencyMismatch=false;for(method in rules){var rule={method:method,parameters:rules[method]};try{var result=$.validator.methods[method].call(this,element.value.replace(/\\r/g,\"\"),element,rule.parameters);if(result==\"dependency-mismatch\"){dependencyMismatch=true;continue;}dependencyMismatch=false;if(result==\"pending\"){this.toHide=this.toHide.not(this.errorsFor(element));return;}if(!result){this.formatAndAdd(element,rule);return false;}}catch(e){this.settings.debug&&window.console&&console.log(\"exception occured when checking element \"+element.id\n+\", check the '\"+rule.method+\"' method\",e);throw e;}}if(dependencyMismatch)return;if(this.objectLength(rules))this.successList.push(element);return true;},customMetaMessage:function(element,method){if(!$.metadata)return;var meta=this.settings.meta?$(element).metadata()[this.settings.meta]:$(element).metadata();return meta&&meta.messages&&meta.messages[method];},customMessage:function(name,method){var m=this.settings.messages[name];return m&&(m.constructor==String?m:m[method]);},findDefined:function(){for(var i=0;iWarning: No message defined for \"+element.name+\"\");},formatAndAdd:function(element,rule){var message=this.defaultMessage(element,rule.method),theregex=/\\$?\\{(\\d+)\\}/g;if(typeof message==\"function\"){message=message.call(this,rule.parameters,element);}else if(theregex.test(message)){message=jQuery.format(message.replace(theregex,'{$1}'),rule.parameters);}this.errorList.push({message:message,element:element});this.errorMap[element.name]=message;this.submitted[element.name]=message;},addWrapper:function(toToggle){if(this.settings.wrapper)toToggle=toToggle.add(toToggle.parent(this.settings.wrapper));return toToggle;},defaultShowErrors:function(){for(var i=0;this.errorList[i];i++){var error=this.errorList[i];this.settings.highlight&&this.settings.highlight.call(this,error.element,this.settings.errorClass,this.settings.validClass);this.showLabel(error.element,error.message);}if(this.errorList.length){this.toShow=this.toShow.add(this.containers);}if(this.settings.success){for(var i=0;this.successList[i];i++){this.showLabel(this.successList[i]);}}if(this.settings.unhighlight){for(var i=0,elements=this.validElements();elements[i];i++){this.settings.unhighlight.call(this,elements[i],this.settings.errorClass,this.settings.validClass);}}this.toHide=this.toHide.not(this.toShow);this.hideErrors();this.addWrapper(this.toShow).show();},validElements:function(){return this.currentElements.not(this.invalidElements());},invalidElements:function(){return $(this.errorList).map(function(){return this.element;});},showLabel:function(element,message){var label=this.errorsFor(element);if(label.length){label.removeClass().addClass(this.settings.errorClass);label.attr(\"generated\")&&label.html(message);}else{label=$(\"<\"+this.settings.errorElement+\"/>\").attr({\"for\":this.idOrName(element),generated:true}).addClass(this.settings.errorClass).html(message||\"\");if(this.settings.wrapper){label=label.hide().show().wrap(\"<\"+this.settings.wrapper+\"/>\").parent();}if(!this.labelContainer.append(label).length)this.settings.errorPlacement?this.settings.errorPlacement(label,$(element)):label.insertAfter(element);}if(!message&&this.settings.success){label.text(\"\");typeof this.settings.success==\"string\"?label.addClass(this.settings.success):this.settings.success(label);}this.toShow=this.toShow.add(label);},errorsFor:function(element){var name=this.idOrName(element);return this.errors().filter(function(){return $(this).attr('for')==name;});},idOrName:function(element){return this.groups[element.name]||(this.checkable(element)?element.name:element.id||element.name);},checkable:function(element){return/radio|checkbox/i.test(element.type);},findByName:function(name){var form=this.currentForm;return $(document.getElementsByName(name)).map(function(index,element){return element.form==form&&element.name==name&&element||null;});},getLength:function(value,element){switch(element.nodeName.toLowerCase()){case'select':return $(\"option:selected\",element).length;case'input':if(this.checkable(element))return this.findByName(element.name).filter(':checked').length;}return value.length;},depend:function(param,element){return this.dependTypes[typeof param]?this.dependTypes[typeof param](param,element):true;},dependTypes:{\"boolean\":function(param,element){return param;},\"string\":function(param,element){return!!$(param,element.form).length;},\"function\":function(param,element){return param(element);}},optional:function(element){return!$.validator.methods.required.call(this,$.trim(element.value),element)&&\"dependency-mismatch\";},startRequest:function(element){if(!this.pending[element.name]){this.pendingRequest++;this.pending[element.name]=true;}},stopRequest:function(element,valid){this.pendingRequest--;if(this.pendingRequest<0)this.pendingRequest=0;delete this.pending[element.name];if(valid&&this.pendingRequest==0&&this.formSubmitted&&this.form()){$(this.currentForm).submit();this.formSubmitted=false;}else if(!valid&&this.pendingRequest==0&&this.formSubmitted){$(this.currentForm).triggerHandler(\"invalid-form\",[this]);this.formSubmitted=false;}},previousValue:function(element){return $.data(element,\"previousValue\")||$.data(element,\"previousValue\",{old:null,valid:true,message:this.defaultMessage(element,\"remote\")});}},classRuleSettings:{required:{required:true},email:{email:true},url:{url:true},date:{date:true},dateISO:{dateISO:true},dateDE:{dateDE:true},number:{number:true},numberDE:{numberDE:true},digits:{digits:true},creditcard:{creditcard:true}},addClassRules:function(className,rules){className.constructor==String?this.classRuleSettings[className]=rules:$.extend(this.classRuleSettings,className);},classRules:function(element){var rules={};var classes=$(element).attr('class');classes&&$.each(classes.split(' '),function(){if(this in $.validator.classRuleSettings){$.extend(rules,$.validator.classRuleSettings[this]);}});return rules;},attributeRules:function(element){var rules={};var $element=$(element);for(method in $.validator.methods){var value=$element.attr(method);if(value){rules[method]=value;}}if(rules.maxlength&&/-1|2147483647|524288/.test(rules.maxlength)){delete rules.maxlength;}return rules;},metadataRules:function(element){if(!$.metadata)return{};var meta=$.data(element.form,'validator').settings.meta;return meta?$(element).metadata()[meta]:$(element).metadata();},staticRules:function(element){var rules={};var validator=$.data(element.form,'validator');if(validator.settings.rules){rules=$.validator.normalizeRule(validator.settings.rules[element.name])||{};}return rules;},normalizeRules:function(rules,element){$.each(rules,function(prop,val){if(val===false){delete rules[prop];return;}if(val.param||val.depends){var keepRule=true;switch(typeof val.depends){case\"string\":keepRule=!!$(val.depends,element.form).length;break;case\"function\":keepRule=val.depends.call(element,element);break;}if(keepRule){rules[prop]=val.param!==undefined?val.param:true;}else{delete rules[prop];}}});$.each(rules,function(rule,parameter){rules[rule]=$.isFunction(parameter)?parameter(element):parameter;});$.each(['minlength','maxlength','min','max'],function(){if(rules[this]){rules[this]=Number(rules[this]);}});$.each(['rangelength','range'],function(){if(rules[this]){rules[this]=[Number(rules[this][0]),Number(rules[this][1])];}});if($.validator.autoCreateRanges){if(rules.min&&rules.max){rules.range=[rules.min,rules.max];delete rules.min;delete rules.max;}if(rules.minlength&&rules.maxlength){rules.rangelength=[rules.minlength,rules.maxlength];delete rules.minlength;delete rules.maxlength;}}if(rules.messages){delete rules.messages;}return rules;},normalizeRule:function(data){if(typeof data==\"string\"){var transformed={};$.each(data.split(/\\s/),function(){transformed[this]=true;});data=transformed;}return data;},addMethod:function(name,method,message){$.validator.methods[name]=method;$.validator.messages[name]=message!=undefined?message:$.validator.messages[name];if(method.length<3){$.validator.addClassRules(name,$.validator.normalizeRule(name));}},methods:{required:function(value,element,param){if(!this.depend(param,element))return\"dependency-mismatch\";switch(element.nodeName.toLowerCase()){case'select':var val=$(element).val();return val&&val.length>0;case'input':if(this.checkable(element))return this.getLength(value,element)>0;default:return $.trim(value).length>0;}},remote:function(value,element,param){if(this.optional(element))return\"dependency-mismatch\";var previous=this.previousValue(element);if(!this.settings.messages[element.name])this.settings.messages[element.name]={};previous.originalMessage=this.settings.messages[element.name].remote;this.settings.messages[element.name].remote=previous.message;param=typeof param==\"string\"&&{url:param}||param;if(previous.old!==value){previous.old=value;var validator=this;this.startRequest(element);var data={};data[element.name]=value;$.ajax($.extend(true,{url:param,mode:\"abort\",port:\"validate\"+element.name,dataType:\"json\",data:data,success:function(response){validator.settings.messages[element.name].remote=previous.originalMessage;var valid=response===true;if(valid){var submitted=validator.formSubmitted;validator.prepareElement(element);validator.formSubmitted=submitted;validator.successList.push(element);validator.showErrors();}else{var errors={};var message=(previous.message=response||validator.defaultMessage(element,\"remote\"));errors[element.name]=$.isFunction(message)?message(value):message;validator.showErrors(errors);}previous.valid=valid;validator.stopRequest(element,valid);}},param));return\"pending\";}else if(this.pending[element.name]){return\"pending\";}return previous.valid;},minlength:function(value,element,param){return this.optional(element)||this.getLength($.trim(value),element)>=param;},maxlength:function(value,element,param){return this.optional(element)||this.getLength($.trim(value),element)<=param;},rangelength:function(value,element,param){var length=this.getLength($.trim(value),element);return this.optional(element)||(length>=param[0]&&length<=param[1]);},min:function(value,element,param){return this.optional(element)||value>=param;},max:function(value,element,param){return this.optional(element)||value<=param;},range:function(value,element,param){return this.optional(element)||(value>=param[0]&&value<=param[1]);},email:function(value,element){return this.optional(element)||/^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?$/i.test(value);},url:function(value,element){return this.optional(element)||/^(https?|ftp):\\/\\/(((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:)*@)?(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?)(:\\d*)?)(\\/((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)+(\\/(([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)*)*)?)?(\\?((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)|[\\uE000-\\uF8FF]|\\/|\\?)*)?(\\#((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)|\\/|\\?)*)?$/i.test(value);},date:function(value,element){return this.optional(element)||!/Invalid|NaN/.test(new Date(value));},dateISO:function(value,element){return this.optional(element)||/^\\d{4}[\\/-]\\d{1,2}[\\/-]\\d{1,2}$/.test(value);},number:function(value,element){return this.optional(element)||/^-?(?:\\d+|\\d{1,3}(?:,\\d{3})+)(?:\\.\\d+)?$/.test(value);},digits:function(value,element){return this.optional(element)||/^\\d+$/.test(value);},creditcard:function(value,element){if(this.optional(element))return\"dependency-mismatch\";if(/[^0-9-]+/.test(value))return false;var nCheck=0,nDigit=0,bEven=false;value=value.replace(/\\D/g,\"\");for(var n=value.length-1;n>=0;n--){var cDigit=value.charAt(n);var nDigit=parseInt(cDigit,10);if(bEven){if((nDigit*=2)>9)nDigit-=9;}nCheck+=nDigit;bEven=!bEven;}return(nCheck%10)==0;},accept:function(value,element,param){param=typeof param==\"string\"?param.replace(/,/g,'|'):\"png|jpe?g|gif\";return this.optional(element)||value.match(new RegExp(\".(\"+param+\")$\",\"i\"));},equalTo:function(value,element,param){var target=$(param).unbind(\".validate-equalTo\").bind(\"blur.validate-equalTo\",function(){$(element).valid();});return value==target.val();}}});$.format=$.validator.format;})(jQuery);;(function($){var ajax=$.ajax;var pendingRequests={};$.ajax=function(settings){settings=$.extend(settings,$.extend({},$.ajaxSettings,settings));var port=settings.port;if(settings.mode==\"abort\"){if(pendingRequests[port]){pendingRequests[port].abort();}return(pendingRequests[port]=ajax.apply(this,arguments));}return ajax.apply(this,arguments);};})(jQuery);;(function($){if(!jQuery.event.special.focusin&&!jQuery.event.special.focusout&&document.addEventListener){$.each({focus:'focusin',blur:'focusout'},function(original,fix){$.event.special[fix]={setup:function(){this.addEventListener(original,handler,true);},teardown:function(){this.removeEventListener(original,handler,true);},handler:function(e){arguments[0]=$.event.fix(e);arguments[0].type=fix;return $.event.handle.apply(this,arguments);}};function handler(e){e=$.event.fix(e);e.type=fix;return $.event.handle.call(this,e);}});};$.extend($.fn,{validateDelegate:function(delegate,type,handler){return this.bind(type,function(event){var target=$(event.target);if(target.is(delegate)){return handler.apply(target,arguments);}});}});})(jQuery);\n","window.showLoadingIndicator = function() {\n $('').appendTo('body');\n}\n\nwindow.hideLoadingIndicator = function() {\n $('body > #loading').remove();\n}\n","import \"../constants.js\"\nimport \"./ui.js\"\nimport \"../vendors/xdLocalStorage.js\"\n\nclass window.LocationController\n constructor: (blankPage, apiKey, countryBounds) ->\n @blankPage = blankPage\n @apiKey = apiKey\n @countryBounds = countryBounds\n @ymapsInitCallbacks = []\n @ymapsInitialized = false\n @temporaryLocation = false\n\n # При первом открытии пытаемся получить \"запомненное\" местоположение.\n # Если мы его получили, то ничего делать не надо.\n #@initLocalStorage()\n # .then @getStoredLocation\n # .catch =>\n # # Получаем координаты юзера через яндекс (он определяет по IP)\n # @initializeYandexMapsAPI()\n # .then @requestYandexLocation\n # .then @geoCode\n # .then @ui.setMenuLocation\n # .then @ui.showModal\n # .then @ui.askForCorrectLocation\n # .catch (data) ->\n # console?.log(\"error\", data)\n\n @ui = new LocationUIController(@)\n\n window.showAndOpenCityMenu = =>\n @ui.openMenu()\n .then @ui.initializeCityMenu\n\n $(window).scrollTo(0, ANConstants.ANIM_DURATION, axis: \"y\")\n\n # Инициализация Локального хранилища\n initLocalStorage: =>\n new Promise (resolve, reject) =>\n if xdLocalStorage.wasInit()\n resolve()\n else\n xdLocalStorage.init {\n iframeUrl: @blankPage,\n initCallback: resolve\n }\n\n # Получение местоположения из хранилища\n getStoredLocation: ->\n new Promise (resolve, reject) ->\n if localStorage[\"location\"]\n resolve(JSON.parse localStorage[\"location\"])\n else\n xdLocalStorage.getItem \"location\", (data) ->\n if data.value\n try\n location = JSON.parse data.value\n if String(typeof(location)).toLowerCase() == \"object\" && location.name && location.coords\n resolve(location)\n return\n catch\n reject()\n\n # Сохранение местоположения в хранилище\n setStoredLocation: (location) =>\n new Promise (resolve, reject) =>\n xdLocalStorage.setItem \"location\", JSON.stringify(location), ->\n resolve(location)\n\n # Запрос на получение геопозиции из браузера\n requestDeviceLocation: ->\n new Promise (resolve, reject) ->\n try\n navigator.geolocation.getCurrentPosition(resolve, reject)\n catch\n reject(\"no stored location\")\n\n # Запрос на получение геопозиции из яндекса\n requestYandexLocation: ->\n new Promise (resolve, reject) ->\n try\n ymaps.geolocation.get({autoReverseGeocode: true, provider: \"yandex\", timeout: 5000})\n .then (data) ->\n resolve data.geoObjects.position\n catch e\n reject(e)\n\n # Инициализация API яндекс карт\n initializeYandexMapsAPI: =>\n new Promise (resolve, reject) =>\n return resolve() if @ymapsInitialized\n\n if @ymapsInitCallbacks.length > 0\n @ymapsInitCallbacks.push resolve\n return\n\n @ymapsInitCallbacks.push resolve\n $script = $(\"