// source --> https://homelive.pt/wp-includes/js/utils.min.js?ver=6.9.4 
/*! This file is auto-generated */
window.wpCookies={each:function(e,t,n){var i,s;if(!e)return 0;if(n=n||e,void 0!==e.length){for(i=0,s=e.length;i<s;i++)if(!1===t.call(n,e[i],i,e))return 0}else for(i in e)if(e.hasOwnProperty(i)&&!1===t.call(n,e[i],i,e))return 0;return 1},getHash:function(e){var t,e=this.get(e);return e&&this.each(e.split("&"),function(e){e=e.split("="),(t=t||{})[e[0]]=e[1]}),t},setHash:function(e,t,n,i,s,r){var o="";this.each(t,function(e,t){o+=(o?"&":"")+t+"="+e}),this.set(e,o,n,i,s,r)},get:function(e){var t,n,i=document.cookie,e=e+"=";if(i){if(-1===(n=i.indexOf("; "+e))){if(0!==(n=i.indexOf(e)))return null}else n+=2;return-1===(t=i.indexOf(";",n))&&(t=i.length),decodeURIComponent(i.substring(n+e.length,t))}},set:function(e,t,n,i,s,r){var o=new Date;n="object"==typeof n&&n.toGMTString?n.toGMTString():parseInt(n,10)?(o.setTime(o.getTime()+1e3*parseInt(n,10)),o.toGMTString()):"",document.cookie=e+"="+encodeURIComponent(t)+(n?"; expires="+n:"")+(i?"; path="+i:"")+(s?"; domain="+s:"")+(r?"; secure":"")},remove:function(e,t,n,i){this.set(e,"",-1e3,t,n,i)}},window.getUserSetting=function(e,t){var n=getAllUserSettings();return n.hasOwnProperty(e)?n[e]:void 0!==t?t:""},window.setUserSetting=function(e,t,n){var i,s,r,o;return"object"==typeof userSettings&&(i=userSettings.uid,s=wpCookies.getHash("wp-settings-"+i),r=userSettings.url,o=!!userSettings.secure,e=e.toString().replace(/[^A-Za-z0-9_-]/g,""),t="number"==typeof t?parseInt(t,10):t.toString().replace(/[^A-Za-z0-9_-]/g,""),s=s||{},n?delete s[e]:s[e]=t,wpCookies.setHash("wp-settings-"+i,s,31536e3,r,"",o),wpCookies.set("wp-settings-time-"+i,userSettings.time,31536e3,r,"",o),e)},window.deleteUserSetting=function(e){return setUserSetting(e,"",1)},window.getAllUserSettings=function(){return"object"==typeof userSettings&&wpCookies.getHash("wp-settings-"+userSettings.uid)||{}};
// source --> https://homelive.pt/wp-includes/js/plupload/moxie.min.js?ver=1.3.5.1 
var MXI_DEBUG=!1;!function(o,x){"use strict";var s={};function n(e,t){for(var i,n=[],r=0;r<e.length;++r){if(!(i=s[e[r]]||function(e){for(var t=o,i=e.split(/[.\/]/),n=0;n<i.length;++n){if(!t[i[n]])return;t=t[i[n]]}return t}(e[r])))throw"module definition dependecy not found: "+e[r];n.push(i)}t.apply(null,n)}function e(e,t,i){if("string"!=typeof e)throw"invalid module definition, module id must be defined and be a string";if(t===x)throw"invalid module definition, dependencies must be specified";if(i===x)throw"invalid module definition, definition function must be specified";n(t,function(){s[e]=i.apply(null,arguments)})}e("moxie/core/utils/Basic",[],function(){function n(i){return s(arguments,function(e,t){0<t&&s(e,function(e,t){void 0!==e&&(o(i[t])===o(e)&&~r(o(e),["array","object"])?n(i[t],e):i[t]=e)})}),i}function s(e,t){var i,n,r;if(e)if("number"===o(e.length)){for(r=0,i=e.length;r<i;r++)if(!1===t(e[r],r))return}else if("object"===o(e))for(n in e)if(e.hasOwnProperty(n)&&!1===t(e[n],n))return}function r(e,t){if(t){if(Array.prototype.indexOf)return Array.prototype.indexOf.call(t,e);for(var i=0,n=t.length;i<n;i++)if(t[i]===e)return i}return-1}var o=function(e){return void 0===e?"undefined":null===e?"null":e.nodeType?"node":{}.toString.call(e).match(/\s([a-z|A-Z]+)/)[1].toLowerCase()};a=0;var a;return{guid:function(e){for(var t=(new Date).getTime().toString(32),i=0;i<5;i++)t+=Math.floor(65535*Math.random()).toString(32);return(e||"o_")+t+(a++).toString(32)},typeOf:o,extend:n,each:s,isEmptyObj:function(e){if(e&&"object"===o(e))for(var t in e)return!1;return!0},inSeries:function(e,n){var r=e.length;"function"!==o(n)&&(n=function(){}),e&&e.length||n(),function t(i){"function"===o(e[i])&&e[i](function(e){++i<r&&!e?t(i):n(e)})}(0)},inParallel:function(e,i){var n=0,r=e.length,o=new Array(r);s(e,function(e,t){e(function(e){if(e)return i(e);e=[].slice.call(arguments);e.shift(),o[t]=e,++n===r&&(o.unshift(null),i.apply(this,o))})})},inArray:r,arrayDiff:function(e,t){var i,n=[];for(i in"array"!==o(e)&&(e=[e]),"array"!==o(t)&&(t=[t]),e)-1===r(e[i],t)&&n.push(e[i]);return!!n.length&&n},arrayIntersect:function(e,t){var i=[];return s(e,function(e){-1!==r(e,t)&&i.push(e)}),i.length?i:null},toArray:function(e){for(var t=[],i=0;i<e.length;i++)t[i]=e[i];return t},trim:function(e){return e&&(String.prototype.trim?String.prototype.trim.call(e):e.toString().replace(/^\s*/,"").replace(/\s*$/,""))},sprintf:function(e){var t=[].slice.call(arguments,1);return e.replace(/%[a-z]/g,function(){var e=t.shift();return"undefined"!==o(e)?e:""})},parseSizeStr:function(e){var t,i;return"string"!=typeof e?e:(t={t:1099511627776,g:1073741824,m:1048576,k:1024},i=(e=/^([0-9\.]+)([tmgk]?)$/.exec(e.toLowerCase().replace(/[^0-9\.tmkg]/g,"")))[2],e=+e[1],t.hasOwnProperty(i)&&(e*=t[i]),Math.floor(e))}}}),e("moxie/core/utils/Env",["moxie/core/utils/Basic"],function(n){m="function",h="object",r=function(e,t){return-1!==t.toLowerCase().indexOf(e.toLowerCase())},o={browser:[[/(opera\smini)\/([\w\.-]+)/i,/(opera\s[mobiletab]+).+version\/([\w\.-]+)/i,/(opera).+version\/([\w\.]+)/i,/(opera)[\/\s]+([\w\.]+)/i],[a="name",c="version"],[/\s(opr)\/([\w\.]+)/i],[[a,"Opera"],c],[/(kindle)\/([\w\.]+)/i,/(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]+)*/i,/(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i,/(?:ms|\()(ie)\s([\w\.]+)/i,/(rekonq)\/([\w\.]+)*/i,/(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi)\/([\w\.-]+)/i],[a,c],[/(trident).+rv[:\s]([\w\.]+).+like\sgecko/i],[[a,"IE"],c],[/(edge)\/((\d+)?[\w\.]+)/i],[a,c],[/(yabrowser)\/([\w\.]+)/i],[[a,"Yandex"],c],[/(comodo_dragon)\/([\w\.]+)/i],[[a,/_/g," "],c],[/(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i,/(uc\s?browser|qqbrowser)[\/\s]?([\w\.]+)/i],[a,c],[/(dolfin)\/([\w\.]+)/i],[[a,"Dolphin"],c],[/((?:android.+)crmo|crios)\/([\w\.]+)/i],[[a,"Chrome"],c],[/XiaoMi\/MiuiBrowser\/([\w\.]+)/i],[c,[a,"MIUI Browser"]],[/android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)/i],[c,[a,"Android Browser"]],[/FBAV\/([\w\.]+);/i],[c,[a,"Facebook"]],[/version\/([\w\.]+).+?mobile\/\w+\s(safari)/i],[c,[a,"Mobile Safari"]],[/version\/([\w\.]+).+?(mobile\s?safari|safari)/i],[c,a],[/webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i],[a,[c,(i={rgx:function(){for(var e,t,i,n,r,o,s,a=0,u=arguments;a<u.length;a+=2){var c=u[a],l=u[a+1];if(void 0===e)for(n in e={},l)typeof(r=l[n])==h?e[r[0]]=d:e[r]=d;for(t=i=0;t<c.length;t++)if(o=c[t].exec(this.getUA())){for(n=0;n<l.length;n++)s=o[++i],typeof(r=l[n])==h&&0<r.length?2==r.length?typeof r[1]==m?e[r[0]]=r[1].call(this,s):e[r[0]]=r[1]:3==r.length?typeof r[1]!=m||r[1].exec&&r[1].test?e[r[0]]=s?s.replace(r[1],r[2]):d:e[r[0]]=s?r[1].call(this,s,r[2]):d:4==r.length&&(e[r[0]]=s?r[3].call(this,s.replace(r[1],r[2])):d):e[r]=s||d;break}if(o)break}return e},str:function(e,t){for(var i in t)if(typeof t[i]==h&&0<t[i].length){for(var n=0;n<t[i].length;n++)if(r(t[i][n],e))return"?"===i?d:i}else if(r(t[i],e))return"?"===i?d:i;return e}}).str,(e={browser:{oldsafari:{major:{1:["/8","/1","/3"],2:"/4","?":"/"},version:{"1.0":"/8",1.2:"/1",1.3:"/3","2.0":"/412","2.0.2":"/416","2.0.3":"/417","2.0.4":"/419","?":"/"}}},device:{sprint:{model:{"Evo Shift 4G":"7373KT"},vendor:{HTC:"APA",Sprint:"Sprint"}}},os:{windows:{version:{ME:"4.90","NT 3.11":"NT3.51","NT 4.0":"NT4.0",2e3:"NT 5.0",XP:["NT 5.1","NT 5.2"],Vista:"NT 6.0",7:"NT 6.1",8:"NT 6.2",8.1:"NT 6.3",RT:"ARM"}}}}).browser.oldsafari.version]],[/(konqueror)\/([\w\.]+)/i,/(webkit|khtml)\/([\w\.]+)/i],[a,c],[/(navigator|netscape)\/([\w\.-]+)/i],[[a,"Netscape"],c],[/(swiftfox)/i,/(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i,/(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/([\w\.-]+)/i,/(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i,/(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf)[\/\s]?([\w\.]+)/i,/(links)\s\(([\w\.]+)/i,/(gobrowser)\/?([\w\.]+)*/i,/(ice\s?browser)\/v?([\w\._]+)/i,/(mosaic)[\/\s]([\w\.]+)/i],[a,c]],engine:[[/windows.+\sedge\/([\w\.]+)/i],[c,[a,"EdgeHTML"]],[/(presto)\/([\w\.]+)/i,/(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i,/(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i,/(icab)[\/\s]([23]\.[\d\.]+)/i],[a,c],[/rv\:([\w\.]+).*(gecko)/i],[c,a]],os:[[/microsoft\s(windows)\s(vista|xp)/i],[a,c],[/(windows)\snt\s6\.2;\s(arm)/i,/(windows\sphone(?:\sos)*|windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i],[a,[c,i.str,e.os.windows.version]],[/(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i],[[a,"Windows"],[c,i.str,e.os.windows.version]],[/\((bb)(10);/i],[[a,"BlackBerry"],c],[/(blackberry)\w*\/?([\w\.]+)*/i,/(tizen)[\/\s]([\w\.]+)/i,/(android|webos|palm\os|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]+)*/i,/linux;.+(sailfish);/i],[a,c],[/(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i],[[a,"Symbian"],c],[/\((series40);/i],[a],[/mozilla.+\(mobile;.+gecko.+firefox/i],[[a,"Firefox OS"],c],[/(nintendo|playstation)\s([wids3portablevu]+)/i,/(mint)[\/\s\(]?(\w+)*/i,/(mageia|vectorlinux)[;\s]/i,/(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?([\w\.-]+)*/i,/(hurd|linux)\s?([\w\.]+)*/i,/(gnu)\s?([\w\.]+)*/i],[a,c],[/(cros)\s[\w]+\s([\w\.]+\w)/i],[[a,"Chromium OS"],c],[/(sunos)\s?([\w\.]+\d)*/i],[[a,"Solaris"],c],[/\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i],[a,c],[/(ip[honead]+)(?:.*os\s*([\w]+)*\slike\smac|;\sopera)/i],[[a,"iOS"],[c,/_/g,"."]],[/(mac\sos\sx)\s?([\w\s\.]+\w)*/i,/(macintosh|mac(?=_powerpc)\s)/i],[[a,"Mac OS"],[c,/_/g,"."]],[/((?:open)?solaris)[\/\s-]?([\w\.]+)*/i,/(haiku)\s(\w+)/i,/(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i,/(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms)/i,/(unix)\s?([\w\.]+)*/i],[a,c]]};var d,m,h,r,i,o,e=function(e){var t=e||(window&&window.navigator&&window.navigator.userAgent?window.navigator.userAgent:"");this.getBrowser=function(){return i.rgx.apply(this,o.browser)},this.getEngine=function(){return i.rgx.apply(this,o.engine)},this.getOS=function(){return i.rgx.apply(this,o.os)},this.getResult=function(){return{ua:this.getUA(),browser:this.getBrowser(),engine:this.getEngine(),os:this.getOS()}},this.getUA=function(){return t},this.setUA=function(e){return t=e,this},this.setUA(t)};function t(e){var t=[].slice.call(arguments);return t.shift(),"function"===n.typeOf(u[e])?u[e].apply(this,t):!!u[e]}u={define_property:!1,create_canvas:!(!(a=document.createElement("canvas")).getContext||!a.getContext("2d")),return_response_type:function(e){try{if(-1!==n.inArray(e,["","text","document"]))return!0;if(window.XMLHttpRequest){var t=new XMLHttpRequest;if(t.open("get","/"),"responseType"in t)return t.responseType=e,t.responseType===e}}catch(e){}return!1},use_data_uri:((s=new Image).onload=function(){u.use_data_uri=1===s.width&&1===s.height},setTimeout(function(){s.src="data:image/gif;base64,R0lGODlhAQABAIAAAP8AAAAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw=="},1),!1),use_data_uri_over32kb:function(){return u.use_data_uri&&("IE"!==l.browser||9<=l.version)},use_data_uri_of:function(e){return u.use_data_uri&&e<33e3||u.use_data_uri_over32kb()},use_fileinput:function(){var e;return!navigator.userAgent.match(/(Android (1.0|1.1|1.5|1.6|2.0|2.1))|(Windows Phone (OS 7|8.0))|(XBLWP)|(ZuneWP)|(w(eb)?OSBrowser)|(webOS)|(Kindle\/(1.0|2.0|2.5|3.0))/)&&((e=document.createElement("input")).setAttribute("type","file"),!e.disabled)}};var s,a,u,c=(new e).getResult(),l={can:t,uaParser:e,browser:c.browser.name,version:c.browser.version,os:c.os.name,osVersion:c.os.version,verComp:function(e,t,i){function n(e){return(e=(e=(""+e).replace(/[_\-+]/g,".")).replace(/([^.\d]+)/g,".$1.").replace(/\.{2,}/g,".")).length?e.split("."):[-8]}function r(e){return e?isNaN(e)?u[e]||-7:parseInt(e,10):0}var o,s=0,a=0,u={dev:-6,alpha:-5,a:-5,beta:-4,b:-4,RC:-3,rc:-3,"#":-2,p:1,pl:1};for(e=n(e),t=n(t),o=Math.max(e.length,t.length),s=0;s<o;s++)if(e[s]!=t[s]){if(e[s]=r(e[s]),t[s]=r(t[s]),e[s]<t[s]){a=-1;break}if(e[s]>t[s]){a=1;break}}if(!i)return a;switch(i){case">":case"gt":return 0<a;case">=":case"ge":return 0<=a;case"<=":case"le":return a<=0;case"==":case"=":case"eq":return 0===a;case"<>":case"!=":case"ne":return 0!==a;case"":case"<":case"lt":return a<0;default:return null}},global_event_dispatcher:"moxie.core.EventTarget.instance.dispatchEvent"};return l.OS=l.os,MXI_DEBUG&&(l.debug={runtime:!0,events:!1},l.log=function(){var e,t,i=arguments[0];"string"===n.typeOf(i)&&(i=n.sprintf.apply(this,arguments)),window&&window.console&&window.console.log?window.console.log(i):document&&((e=document.getElementById("moxie-console"))||((e=document.createElement("pre")).id="moxie-console",document.body.appendChild(e)),-1!==n.inArray(n.typeOf(i),["object","array"])?(t=i,e.appendChild(document.createTextNode(t+"\n"))):e.appendChild(document.createTextNode(i+"\n")))}),l}),e("moxie/core/I18n",["moxie/core/utils/Basic"],function(i){var t={};return{addI18n:function(e){return i.extend(t,e)},translate:function(e){return t[e]||e},_:function(e){return this.translate(e)},sprintf:function(e){var t=[].slice.call(arguments,1);return e.replace(/%[a-z]/g,function(){var e=t.shift();return"undefined"!==i.typeOf(e)?e:""})}}}),e("moxie/core/utils/Mime",["moxie/core/utils/Basic","moxie/core/I18n"],function(a,n){var e={mimes:{},extensions:{},addMimeType:function(e){for(var t,i,n=e.split(/,/),r=0;r<n.length;r+=2){for(i=n[r+1].split(/ /),t=0;t<i.length;t++)this.mimes[i[t]]=n[r];this.extensions[n[r]]=i}},extList2mimes:function(e,t){for(var i,n,r,o=[],s=0;s<e.length;s++)for(i=e[s].extensions.split(/\s*,\s*/),n=0;n<i.length;n++){if("*"===i[n])return[];if((r=this.mimes[i[n]])&&-1===a.inArray(r,o)&&o.push(r),t&&/^\w+$/.test(i[n]))o.push("."+i[n]);else if(!r)return[]}return o},mimes2exts:function(e){var n=this,r=[];return a.each(e,function(e){if("*"===e)return!(r=[]);var i=e.match(/^(\w+)\/(\*|\w+)$/);i&&("*"===i[2]?a.each(n.extensions,function(e,t){new RegExp("^"+i[1]+"/").test(t)&&[].push.apply(r,n.extensions[t])}):n.extensions[e]&&[].push.apply(r,n.extensions[e]))}),r},mimes2extList:function(e){var t=[],i=[];return"string"===a.typeOf(e)&&(e=a.trim(e).split(/\s*,\s*/)),i=this.mimes2exts(e),t.push({title:n.translate("Files"),extensions:i.length?i.join(","):"*"}),t.mimes=e,t},getFileExtension:function(e){e=e&&e.match(/\.([^.]+)$/);return e?e[1].toLowerCase():""},getFileMime:function(e){return this.mimes[this.getFileExtension(e)]||""}};return e.addMimeType("application/msword,doc dot,application/pdf,pdf,application/pgp-signature,pgp,application/postscript,ps ai eps,application/rtf,rtf,application/vnd.ms-excel,xls xlb,application/vnd.ms-powerpoint,ppt pps pot,application/zip,zip,application/x-shockwave-flash,swf swfl,application/vnd.openxmlformats-officedocument.wordprocessingml.document,docx,application/vnd.openxmlformats-officedocument.wordprocessingml.template,dotx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,xlsx,application/vnd.openxmlformats-officedocument.presentationml.presentation,pptx,application/vnd.openxmlformats-officedocument.presentationml.template,potx,application/vnd.openxmlformats-officedocument.presentationml.slideshow,ppsx,application/x-javascript,js,application/json,json,audio/mpeg,mp3 mpga mpega mp2,audio/x-wav,wav,audio/x-m4a,m4a,audio/ogg,oga ogg,audio/aiff,aiff aif,audio/flac,flac,audio/aac,aac,audio/ac3,ac3,audio/x-ms-wma,wma,image/bmp,bmp,image/gif,gif,image/jpeg,jpg jpeg jpe,image/photoshop,psd,image/png,png,image/svg+xml,svg svgz,image/tiff,tiff tif,text/plain,asc txt text diff log,text/html,htm html xhtml,text/css,css,text/csv,csv,text/rtf,rtf,video/mpeg,mpeg mpg mpe m2v,video/quicktime,qt mov,video/mp4,mp4,video/x-m4v,m4v,video/x-flv,flv,video/x-ms-wmv,wmv,video/avi,avi,video/webm,webm,video/3gpp,3gpp 3gp,video/3gpp2,3g2,video/vnd.rn-realvideo,rv,video/ogg,ogv,video/x-matroska,mkv,application/vnd.oasis.opendocument.formula-template,otf,application/octet-stream,exe"),e}),e("moxie/core/utils/Dom",["moxie/core/utils/Env"],function(c){function i(e,t){return!!e.className&&new RegExp("(^|\\s+)"+t+"(\\s+|$)").test(e.className)}return{get:function(e){return"string"!=typeof e?e:document.getElementById(e)},hasClass:i,addClass:function(e,t){i(e,t)||(e.className=e.className?e.className.replace(/\s+$/,"")+" "+t:t)},removeClass:function(e,t){e.className&&(t=new RegExp("(^|\\s+)"+t+"(\\s+|$)"),e.className=e.className.replace(t,function(e,t,i){return" "===t&&" "===i?" ":""}))},getStyle:function(e,t){return e.currentStyle?e.currentStyle[t]:window.getComputedStyle?window.getComputedStyle(e,null)[t]:void 0},getPos:function(e,t){var i,n,r,o=0,s=0,a=document;function u(e){var t,i=0,n=0;return e&&(e=e.getBoundingClientRect(),t="CSS1Compat"===a.compatMode?a.documentElement:a.body,i=e.left+t.scrollLeft,n=e.top+t.scrollTop),{x:i,y:n}}if(t=t||a.body,e&&e.getBoundingClientRect&&"IE"===c.browser&&(!a.documentMode||a.documentMode<8))return n=u(e),r=u(t),{x:n.x-r.x,y:n.y-r.y};for(i=e;i&&i!=t&&i.nodeType;)o+=i.offsetLeft||0,s+=i.offsetTop||0,i=i.offsetParent;for(i=e.parentNode;i&&i!=t&&i.nodeType;)o-=i.scrollLeft||0,s-=i.scrollTop||0,i=i.parentNode;return{x:o,y:s}},getSize:function(e){return{w:e.offsetWidth||e.clientWidth,h:e.offsetHeight||e.clientHeight}}}}),e("moxie/core/Exceptions",["moxie/core/utils/Basic"],function(e){function t(e,t){for(var i in e)if(e[i]===t)return i;return null}return{RuntimeError:(a={NOT_INIT_ERR:1,NOT_SUPPORTED_ERR:9,JS_ERR:4},e.extend(d,a),d.prototype=Error.prototype,d),OperationNotAllowedException:(e.extend(l,{NOT_ALLOWED_ERR:1}),l.prototype=Error.prototype,l),ImageError:(s={WRONG_FORMAT:1,MAX_RESOLUTION_ERR:2,INVALID_META_ERR:3},e.extend(c,s),c.prototype=Error.prototype,c),FileException:(o={NOT_FOUND_ERR:1,SECURITY_ERR:2,ABORT_ERR:3,NOT_READABLE_ERR:4,ENCODING_ERR:5,NO_MODIFICATION_ALLOWED_ERR:6,INVALID_STATE_ERR:7,SYNTAX_ERR:8},e.extend(u,o),u.prototype=Error.prototype,u),DOMException:(r={INDEX_SIZE_ERR:1,DOMSTRING_SIZE_ERR:2,HIERARCHY_REQUEST_ERR:3,WRONG_DOCUMENT_ERR:4,INVALID_CHARACTER_ERR:5,NO_DATA_ALLOWED_ERR:6,NO_MODIFICATION_ALLOWED_ERR:7,NOT_FOUND_ERR:8,NOT_SUPPORTED_ERR:9,INUSE_ATTRIBUTE_ERR:10,INVALID_STATE_ERR:11,SYNTAX_ERR:12,INVALID_MODIFICATION_ERR:13,NAMESPACE_ERR:14,INVALID_ACCESS_ERR:15,VALIDATION_ERR:16,TYPE_MISMATCH_ERR:17,SECURITY_ERR:18,NETWORK_ERR:19,ABORT_ERR:20,URL_MISMATCH_ERR:21,QUOTA_EXCEEDED_ERR:22,TIMEOUT_ERR:23,INVALID_NODE_TYPE_ERR:24,DATA_CLONE_ERR:25},e.extend(n,r),n.prototype=Error.prototype,n),EventException:(e.extend(i,{UNSPECIFIED_EVENT_TYPE_ERR:0}),i.prototype=Error.prototype,i)};function i(e){this.code=e,this.name="EventException"}function n(e){this.code=e,this.name=t(r,e),this.message=this.name+": DOMException "+this.code}var r,o,s,a;function u(e){this.code=e,this.name=t(o,e),this.message=this.name+": FileException "+this.code}function c(e){this.code=e,this.name=t(s,e),this.message=this.name+": ImageError "+this.code}function l(e){this.code=e,this.name="OperationNotAllowedException"}function d(e){this.code=e,this.name=t(a,e),this.message=this.name+": RuntimeError "+this.code}}),e("moxie/core/EventTarget",["moxie/core/utils/Env","moxie/core/Exceptions","moxie/core/utils/Basic"],function(c,l,d){function e(){var u={};d.extend(this,{uid:null,init:function(){this.uid||(this.uid=d.guid("uid_"))},addEventListener:function(e,t,i,n){var r,o=this;this.hasOwnProperty("uid")||(this.uid=d.guid("uid_")),e=d.trim(e),/\s/.test(e)?d.each(e.split(/\s+/),function(e){o.addEventListener(e,t,i,n)}):(e=e.toLowerCase(),i=parseInt(i,10)||0,(r=u[this.uid]&&u[this.uid][e]||[]).push({fn:t,priority:i,scope:n||this}),u[this.uid]||(u[this.uid]={}),u[this.uid][e]=r)},hasEventListener:function(e){e=e?u[this.uid]&&u[this.uid][e]:u[this.uid];return e||!1},removeEventListener:function(e,t){e=e.toLowerCase();var i,n=u[this.uid]&&u[this.uid][e];if(n){if(t){for(i=n.length-1;0<=i;i--)if(n[i].fn===t){n.splice(i,1);break}}else n=[];n.length||(delete u[this.uid][e],d.isEmptyObj(u[this.uid])&&delete u[this.uid])}},removeAllEventListeners:function(){u[this.uid]&&delete u[this.uid]},dispatchEvent:function(e){var t,i,n,r,o,s={},a=!0;if("string"!==d.typeOf(e)){if(r=e,"string"!==d.typeOf(r.type))throw new l.EventException(l.EventException.UNSPECIFIED_EVENT_TYPE_ERR);e=r.type,void 0!==r.total&&void 0!==r.loaded&&(s.total=r.total,s.loaded=r.loaded),s.async=r.async||!1}return-1!==e.indexOf("::")?(r=e.split("::"),t=r[0],e=r[1]):t=this.uid,e=e.toLowerCase(),(i=u[t]&&u[t][e])&&(i.sort(function(e,t){return t.priority-e.priority}),(n=[].slice.call(arguments)).shift(),s.type=e,n.unshift(s),MXI_DEBUG&&c.debug.events&&c.log("Event '%s' fired on %u",s.type,t),o=[],d.each(i,function(t){n[0].target=t.scope,o.push(s.async?function(e){setTimeout(function(){e(!1===t.fn.apply(t.scope,n))},1)}:function(e){e(!1===t.fn.apply(t.scope,n))})}),o.length)&&d.inSeries(o,function(e){a=!e}),a},bind:function(){this.addEventListener.apply(this,arguments)},unbind:function(){this.removeEventListener.apply(this,arguments)},unbindAll:function(){this.removeAllEventListeners.apply(this,arguments)},trigger:function(){return this.dispatchEvent.apply(this,arguments)},handleEventProps:function(e){var t=this;this.bind(e.join(" "),function(e){e="on"+e.type.toLowerCase();"function"===d.typeOf(this[e])&&this[e].apply(this,arguments)}),d.each(e,function(e){e="on"+e.toLowerCase(e),"undefined"===d.typeOf(t[e])&&(t[e]=null)})}})}return e.instance=new e,e}),e("moxie/runtime/Runtime",["moxie/core/utils/Env","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/EventTarget"],function(c,l,d,i){var n={},m={};function h(e,t,r,i,n){var o,s,a=this,u=l.guid(t+"_"),n=n||"browser";e=e||{},m[u]=this,r=l.extend({access_binary:!1,access_image_binary:!1,display_media:!1,do_cors:!1,drag_and_drop:!1,filter_by_extension:!0,resize_image:!1,report_upload_progress:!1,return_response_headers:!1,return_response_type:!1,return_status_code:!0,send_custom_headers:!1,select_file:!1,select_folder:!1,select_multiple:!0,send_binary_string:!1,send_browser_cookies:!0,send_multipart:!0,slice_blob:!1,stream_upload:!1,summon_file_dialog:!1,upload_filesize:!0,use_http_method:!0},r),e.preferred_caps&&(n=h.getMode(i,e.preferred_caps,n)),MXI_DEBUG&&c.debug.runtime&&c.log("\tdefault mode: %s",n),s={},o={exec:function(e,t,i,n){if(o[t]&&(s[e]||(s[e]={context:this,instance:new o[t]}),s[e].instance[i]))return s[e].instance[i].apply(this,n)},removeInstance:function(e){delete s[e]},removeAllInstances:function(){var i=this;l.each(s,function(e,t){"function"===l.typeOf(e.instance.destroy)&&e.instance.destroy.call(e.context),i.removeInstance(t)})}},l.extend(this,{initialized:!1,uid:u,type:t,mode:h.getMode(i,e.required_caps,n),shimid:u+"_container",clients:0,options:e,can:function(e,t){var i,n=arguments[2]||r;if("string"===l.typeOf(e)&&"undefined"===l.typeOf(t)&&(e=h.parseCaps(e)),"object"!==l.typeOf(e))return"function"===l.typeOf(n[e])?n[e].call(this,t):t===n[e];for(i in e)if(!this.can(i,e[i],n))return!1;return!0},getShimContainer:function(){var e,t=d.get(this.shimid);return t||(e=this.options.container?d.get(this.options.container):document.body,(t=document.createElement("div")).id=this.shimid,t.className="moxie-shim moxie-shim-"+this.type,l.extend(t.style,{position:"absolute",top:"0px",left:"0px",width:"1px",height:"1px",overflow:"hidden"}),e.appendChild(t),e=null),t},getShim:function(){return o},shimExec:function(e,t){var i=[].slice.call(arguments,2);return a.getShim().exec.call(this,this.uid,e,t,i)},exec:function(e,t){var i=[].slice.call(arguments,2);return a[e]&&a[e][t]?a[e][t].apply(this,i):a.shimExec.apply(this,arguments)},destroy:function(){var e;a&&((e=d.get(this.shimid))&&e.parentNode.removeChild(e),o&&o.removeAllInstances(),this.unbindAll(),delete m[this.uid],this.uid=null,a=o=null)}}),this.mode&&e.required_caps&&!this.can(e.required_caps)&&(this.mode=!1)}return h.order="html5,html4",h.getRuntime=function(e){return m[e]||!1},h.addConstructor=function(e,t){t.prototype=i.instance,n[e]=t},h.getConstructor=function(e){return n[e]||null},h.getInfo=function(e){var t=h.getRuntime(e);return t?{uid:t.uid,type:t.type,mode:t.mode,can:function(){return t.can.apply(t,arguments)}}:null},h.parseCaps=function(e){var t={};return"string"!==l.typeOf(e)?e||{}:(l.each(e.split(","),function(e){t[e]=!0}),t)},h.can=function(e,t){var e=h.getConstructor(e);return!!e&&(t=(e=new e({required_caps:t})).mode,e.destroy(),!!t)},h.thatCan=function(e,t){var i,n=(t||h.order).split(/\s*,\s*/);for(i in n)if(h.can(n[i],e))return n[i];return null},h.getMode=function(n,e,t){var r=null;if("undefined"===l.typeOf(t)&&(t="browser"),e&&!l.isEmptyObj(n)){if(l.each(e,function(e,t){if(n.hasOwnProperty(t)){var i=n[t](e);if("string"==typeof i&&(i=[i]),r){if(!(r=l.arrayIntersect(r,i)))return MXI_DEBUG&&c.debug.runtime&&c.log("\t\t%c: %v (conflicting mode requested: %s)",t,e,i),r=!1}else r=i}MXI_DEBUG&&c.debug.runtime&&c.log("\t\t%c: %v (compatible modes: %s)",t,e,r)}),r)return-1!==l.inArray(t,r)?t:r[0];if(!1===r)return!1}return t},h.capTrue=function(){return!0},h.capFalse=function(){return!1},h.capTest=function(e){return function(){return!!e}},h}),e("moxie/runtime/RuntimeClient",["moxie/core/utils/Env","moxie/core/Exceptions","moxie/core/utils/Basic","moxie/runtime/Runtime"],function(a,u,t,c){return function(){var s;t.extend(this,{connectRuntime:function(r){var e,o=this;if("string"===t.typeOf(r)?e=r:"string"===t.typeOf(r.ruid)&&(e=r.ruid),e){if(s=c.getRuntime(e))return s.clients++,s;throw new u.RuntimeError(u.RuntimeError.NOT_INIT_ERR)}!function e(t){var i,n;t.length?(i=t.shift().toLowerCase(),(n=c.getConstructor(i))?(MXI_DEBUG&&a.debug.runtime&&(a.log("Trying runtime: %s",i),a.log(r)),(s=new n(r)).bind("Init",function(){s.initialized=!0,MXI_DEBUG&&a.debug.runtime&&a.log("Runtime '%s' initialized",s.type),setTimeout(function(){s.clients++,o.trigger("RuntimeInit",s)},1)}),s.bind("Error",function(){MXI_DEBUG&&a.debug.runtime&&a.log("Runtime '%s' failed to initialize",s.type),s.destroy(),e(t)}),MXI_DEBUG&&a.debug.runtime&&a.log("\tselected mode: %s",s.mode),s.mode?s.init():s.trigger("Error")):e(t)):(o.trigger("RuntimeError",new u.RuntimeError(u.RuntimeError.NOT_INIT_ERR)),s=null)}((r.runtime_order||c.order).split(/\s*,\s*/))},disconnectRuntime:function(){s&&--s.clients<=0&&s.destroy(),s=null},getRuntime:function(){return s&&s.uid?s:s=null},exec:function(){return s?s.exec.apply(this,arguments):null}})}}),e("moxie/file/FileInput",["moxie/core/utils/Basic","moxie/core/utils/Env","moxie/core/utils/Mime","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/I18n","moxie/runtime/Runtime","moxie/runtime/RuntimeClient"],function(o,i,n,s,a,e,u,c,l){var d=["ready","change","cancel","mouseenter","mouseleave","mousedown","mouseup"];function t(r){MXI_DEBUG&&i.log("Instantiating FileInput...");var e,t=this;if(-1!==o.inArray(o.typeOf(r),["string","node"])&&(r={browse_button:r}),!(e=s.get(r.browse_button)))throw new a.DOMException(a.DOMException.NOT_FOUND_ERR);e={accept:[{title:u.translate("All Files"),extensions:"*"}],name:"file",multiple:!1,required_caps:!1,container:e.parentNode||document.body},"string"==typeof(r=o.extend({},e,r)).required_caps&&(r.required_caps=c.parseCaps(r.required_caps)),"string"==typeof r.accept&&(r.accept=n.mimes2extList(r.accept)),e=(e=s.get(r.container))||document.body,"static"===s.getStyle(e,"position")&&(e.style.position="relative"),e=null,l.call(t),o.extend(t,{uid:o.guid("uid_"),ruid:null,shimid:null,files:null,init:function(){t.bind("RuntimeInit",function(e,n){t.ruid=n.uid,t.shimid=n.shimid,t.bind("Ready",function(){t.trigger("Refresh")},999),t.bind("Refresh",function(){var e,t=s.get(r.browse_button),i=s.get(n.shimid);t&&(e=s.getPos(t,s.get(r.container)),t=s.getSize(t),i)&&o.extend(i.style,{top:e.y+"px",left:e.x+"px",width:t.w+"px",height:t.h+"px"})}),n.exec.call(t,"FileInput","init",r)}),t.connectRuntime(o.extend({},r,{required_caps:{select_file:!0}}))},disable:function(e){var t=this.getRuntime();t&&t.exec.call(this,"FileInput","disable","undefined"===o.typeOf(e)||e)},refresh:function(){t.trigger("Refresh")},destroy:function(){var e=this.getRuntime();e&&(e.exec.call(this,"FileInput","destroy"),this.disconnectRuntime()),"array"===o.typeOf(this.files)&&o.each(this.files,function(e){e.destroy()}),this.files=null,this.unbindAll()}}),this.handleEventProps(d)}return t.prototype=e.instance,t}),e("moxie/core/utils/Encode",[],function(){function d(e){return unescape(encodeURIComponent(e))}function m(e){return decodeURIComponent(escape(e))}return{utf8_encode:d,utf8_decode:m,atob:function(e,t){if("function"==typeof window.atob)return t?m(window.atob(e)):window.atob(e);var i,n,r,o,s,a,u="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",c=0,l=0,d=[];if(!e)return e;for(e+="";i=(s=u.indexOf(e.charAt(c++))<<18|u.indexOf(e.charAt(c++))<<12|(r=u.indexOf(e.charAt(c++)))<<6|(o=u.indexOf(e.charAt(c++))))>>16&255,n=s>>8&255,s=255&s,d[l++]=64==r?String.fromCharCode(i):64==o?String.fromCharCode(i,n):String.fromCharCode(i,n,s),c<e.length;);return a=d.join(""),t?m(a):a},btoa:function(e,t){if(t&&(e=d(e)),"function"==typeof window.btoa)return window.btoa(e);var i,n,r,o,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",a=0,u=0,t="",c=[];if(!e)return e;for(;i=(o=e.charCodeAt(a++)<<16|e.charCodeAt(a++)<<8|e.charCodeAt(a++))>>12&63,n=o>>6&63,r=63&o,c[u++]=s.charAt(o>>18&63)+s.charAt(i)+s.charAt(n)+s.charAt(r),a<e.length;);var t=c.join(""),l=e.length%3;return(l?t.slice(0,l-3):t)+"===".slice(l||3)}}}),e("moxie/file/Blob",["moxie/core/utils/Basic","moxie/core/utils/Encode","moxie/runtime/RuntimeClient"],function(o,i,n){var s={};return function r(e,t){n.call(this),e&&this.connectRuntime(e),t?"string"===o.typeOf(t)&&(t={data:t}):t={},o.extend(this,{uid:t.uid||o.guid("uid_"),ruid:e,size:t.size||0,type:t.type||"",slice:function(e,t,i){return this.isDetached()?function(e,t,i){var n=s[this.uid];return"string"===o.typeOf(n)&&n.length?((i=new r(null,{type:i,size:t-e})).detach(n.substr(e,i.size)),i):null}.apply(this,arguments):this.getRuntime().exec.call(this,"Blob","slice",this.getSource(),e,t,i)},getSource:function(){return s[this.uid]||null},detach:function(e){var t;this.ruid&&(this.getRuntime().exec.call(this,"Blob","destroy"),this.disconnectRuntime(),this.ruid=null),"data:"==(e=e||"").substr(0,5)&&(t=e.indexOf(";base64,"),this.type=e.substring(5,t),e=i.atob(e.substring(t+8))),this.size=e.length,s[this.uid]=e},isDetached:function(){return!this.ruid&&"string"===o.typeOf(s[this.uid])},destroy:function(){this.detach(),delete s[this.uid]}}),t.data?this.detach(t.data):s[this.uid]=t}}),e("moxie/file/File",["moxie/core/utils/Basic","moxie/core/utils/Mime","moxie/file/Blob"],function(r,o,s){function e(e,t){var i,n;t=t||{},s.apply(this,arguments),this.type||(this.type=o.getFileMime(t.name)),t.name?n=(n=t.name.replace(/\\/g,"/")).substr(n.lastIndexOf("/")+1):this.type&&(i=this.type.split("/")[0],n=r.guid((""!==i?i:"file")+"_"),o.extensions[this.type])&&(n+="."+o.extensions[this.type][0]),r.extend(this,{name:n||r.guid("file_"),relativePath:"",lastModifiedDate:t.lastModifiedDate||(new Date).toLocaleString()})}return e.prototype=s.prototype,e}),e("moxie/file/FileDrop",["moxie/core/I18n","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/utils/Basic","moxie/core/utils/Env","moxie/file/File","moxie/runtime/RuntimeClient","moxie/core/EventTarget","moxie/core/utils/Mime"],function(t,r,e,o,s,i,a,n,u){var c=["ready","dragenter","dragleave","drop","error"];function l(i){MXI_DEBUG&&s.log("Instantiating FileDrop...");var e,n=this;"string"==typeof i&&(i={drop_zone:i}),e={accept:[{title:t.translate("All Files"),extensions:"*"}],required_caps:{drag_and_drop:!0}},(i="object"==typeof i?o.extend({},e,i):e).container=r.get(i.drop_zone)||document.body,"static"===r.getStyle(i.container,"position")&&(i.container.style.position="relative"),"string"==typeof i.accept&&(i.accept=u.mimes2extList(i.accept)),a.call(n),o.extend(n,{uid:o.guid("uid_"),ruid:null,files:null,init:function(){n.bind("RuntimeInit",function(e,t){n.ruid=t.uid,t.exec.call(n,"FileDrop","init",i),n.dispatchEvent("ready")}),n.connectRuntime(i)},destroy:function(){var e=this.getRuntime();e&&(e.exec.call(this,"FileDrop","destroy"),this.disconnectRuntime()),this.files=null,this.unbindAll()}}),this.handleEventProps(c)}return l.prototype=n.instance,l}),e("moxie/file/FileReader",["moxie/core/utils/Basic","moxie/core/utils/Encode","moxie/core/Exceptions","moxie/core/EventTarget","moxie/file/Blob","moxie/runtime/RuntimeClient"],function(e,n,r,t,o,i){var s=["loadstart","progress","load","abort","error","loadend"];function a(){function t(e,t){if(this.trigger("loadstart"),this.readyState===a.LOADING)this.trigger("error",new r.DOMException(r.DOMException.INVALID_STATE_ERR)),this.trigger("loadend");else if(t instanceof o)if(this.result=null,this.readyState=a.LOADING,t.isDetached()){var i=t.getSource();switch(e){case"readAsText":case"readAsBinaryString":this.result=i;break;case"readAsDataURL":this.result="data:"+t.type+";base64,"+n.btoa(i)}this.readyState=a.DONE,this.trigger("load"),this.trigger("loadend")}else this.connectRuntime(t.ruid),this.exec("FileReader","read",e,t);else this.trigger("error",new r.DOMException(r.DOMException.NOT_FOUND_ERR)),this.trigger("loadend")}i.call(this),e.extend(this,{uid:e.guid("uid_"),readyState:a.EMPTY,result:null,error:null,readAsBinaryString:function(e){t.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){t.call(this,"readAsDataURL",e)},readAsText:function(e){t.call(this,"readAsText",e)},abort:function(){this.result=null,-1===e.inArray(this.readyState,[a.EMPTY,a.DONE])&&(this.readyState===a.LOADING&&(this.readyState=a.DONE),this.exec("FileReader","abort"),this.trigger("abort"),this.trigger("loadend"))},destroy:function(){this.abort(),this.exec("FileReader","destroy"),this.disconnectRuntime(),this.unbindAll()}}),this.handleEventProps(s),this.bind("Error",function(e,t){this.readyState=a.DONE,this.error=t},999),this.bind("Load",function(e){this.readyState=a.DONE},999)}return a.EMPTY=0,a.LOADING=1,a.DONE=2,a.prototype=t.instance,a}),e("moxie/core/utils/Url",[],function(){function s(e,t){for(var i=["source","scheme","authority","userInfo","user","pass","host","port","relative","path","directory","file","query","fragment"],n=i.length,r={},o=/^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/.exec(e||"");n--;)o[n]&&(r[i[n]]=o[n]);return r.scheme||(t&&"string"!=typeof t||(t=s(t||document.location.href)),r.scheme=t.scheme,r.host=t.host,r.port=t.port,e="",/^[^\/]/.test(r.path)&&(e=t.path,e=/\/[^\/]*\.[^\/]*$/.test(e)?e.replace(/\/[^\/]+$/,"/"):e.replace(/\/?$/,"/")),r.path=e+(r.path||"")),r.port||(r.port={http:80,https:443}[r.scheme]||80),r.port=parseInt(r.port,10),r.path||(r.path="/"),delete r.source,r}return{parseUrl:s,resolveUrl:function(e){e="object"==typeof e?e:s(e);return e.scheme+"://"+e.host+(e.port!=={http:80,https:443}[e.scheme]?":"+e.port:"")+e.path+(e.query||"")},hasSameOrigin:function(e){function t(e){return[e.scheme,e.host,e.port].join("/")}return"string"==typeof e&&(e=s(e)),t(s())===t(e)}}}),e("moxie/runtime/RuntimeTarget",["moxie/core/utils/Basic","moxie/runtime/RuntimeClient","moxie/core/EventTarget"],function(e,t,i){function n(){this.uid=e.guid("uid_"),t.call(this),this.destroy=function(){this.disconnectRuntime(),this.unbindAll()}}return n.prototype=i.instance,n}),e("moxie/file/FileReaderSync",["moxie/core/utils/Basic","moxie/runtime/RuntimeClient","moxie/core/utils/Encode"],function(e,i,a){return function(){function t(e,t){var i;if(!t.isDetached())return i=this.connectRuntime(t.ruid).exec.call(this,"FileReaderSync","read",e,t),this.disconnectRuntime(),i;var n=t.getSource();switch(e){case"readAsBinaryString":return n;case"readAsDataURL":return"data:"+t.type+";base64,"+a.btoa(n);case"readAsText":for(var r="",o=0,s=n.length;o<s;o++)r+=String.fromCharCode(n[o]);return r}}i.call(this),e.extend(this,{uid:e.guid("uid_"),readAsBinaryString:function(e){return t.call(this,"readAsBinaryString",e)},readAsDataURL:function(e){return t.call(this,"readAsDataURL",e)},readAsText:function(e){return t.call(this,"readAsText",e)}})}}),e("moxie/xhr/FormData",["moxie/core/Exceptions","moxie/core/utils/Basic","moxie/file/Blob"],function(e,s,a){return function(){var r,o=[];s.extend(this,{append:function(i,e){var n=this,t=s.typeOf(e);e instanceof a?r={name:i,value:e}:"array"===t?(i+="[]",s.each(e,function(e){n.append(i,e)})):"object"===t?s.each(e,function(e,t){n.append(i+"["+t+"]",e)}):"null"===t||"undefined"===t||"number"===t&&isNaN(e)?n.append(i,"false"):o.push({name:i,value:e.toString()})},hasBlob:function(){return!!this.getBlob()},getBlob:function(){return r&&r.value||null},getBlobName:function(){return r&&r.name||null},each:function(t){s.each(o,function(e){t(e.value,e.name)}),r&&t(r.value,r.name)},destroy:function(){r=null,o=[]}})}}),e("moxie/xhr/XMLHttpRequest",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/core/EventTarget","moxie/core/utils/Encode","moxie/core/utils/Url","moxie/runtime/Runtime","moxie/runtime/RuntimeTarget","moxie/file/Blob","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/core/utils/Env","moxie/core/utils/Mime"],function(_,b,e,A,I,T,S,r,t,O,D,N){var C={100:"Continue",101:"Switching Protocols",102:"Processing",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",306:"Reserved",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",426:"Upgrade Required",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",510:"Not Extended"};function M(){this.uid=_.guid("uid_")}M.prototype=e.instance;var L=["loadstart","progress","abort","error","load","timeout","loadend"];function F(){var o,s,a,u,c,t,i=this,n={timeout:0,readyState:F.UNSENT,withCredentials:!1,status:0,statusText:"",responseType:"",responseXML:null,responseText:null,response:null},l=!0,d={},m=null,h=null,f=!1,p=!1,g=!1,x=!1,E=!1,y=!1,w={},v="";function R(e,t){if(n.hasOwnProperty(e))return 1===arguments.length?(D.can("define_property")?n:i)[e]:void(D.can("define_property")?n[e]=t:i[e]=t)}_.extend(this,n,{uid:_.guid("uid_"),upload:new M,open:function(e,t,i,n,r){if(!e||!t)throw new b.DOMException(b.DOMException.SYNTAX_ERR);if(/[\u0100-\uffff]/.test(e)||A.utf8_encode(e)!==e)throw new b.DOMException(b.DOMException.SYNTAX_ERR);if(~_.inArray(e.toUpperCase(),["CONNECT","DELETE","GET","HEAD","OPTIONS","POST","PUT","TRACE","TRACK"])&&(s=e.toUpperCase()),~_.inArray(s,["CONNECT","TRACE","TRACK"]))throw new b.DOMException(b.DOMException.SECURITY_ERR);if(t=A.utf8_encode(t),e=I.parseUrl(t),y=I.hasSameOrigin(e),o=I.resolveUrl(t),(n||r)&&!y)throw new b.DOMException(b.DOMException.INVALID_ACCESS_ERR);if(a=n||e.user,u=r||e.pass,!1===(l=i||!0)&&(R("timeout")||R("withCredentials")||""!==R("responseType")))throw new b.DOMException(b.DOMException.INVALID_ACCESS_ERR);f=!l,p=!1,d={},function(){R("responseText",""),R("responseXML",null),R("response",null),R("status",0),R("statusText",""),0}.call(this),R("readyState",F.OPENED),this.dispatchEvent("readystatechange")},setRequestHeader:function(e,t){if(R("readyState")!==F.OPENED||p)throw new b.DOMException(b.DOMException.INVALID_STATE_ERR);if(/[\u0100-\uffff]/.test(e)||A.utf8_encode(e)!==e)throw new b.DOMException(b.DOMException.SYNTAX_ERR);return e=_.trim(e).toLowerCase(),!~_.inArray(e,["accept-charset","accept-encoding","access-control-request-headers","access-control-request-method","connection","content-length","cookie","cookie2","content-transfer-encoding","date","expect","host","keep-alive","origin","referer","te","trailer","transfer-encoding","upgrade","user-agent","via"])&&!/^(proxy\-|sec\-)/.test(e)&&(d[e]?d[e]+=", "+t:d[e]=t,!0)},getAllResponseHeaders:function(){return v||""},getResponseHeader:function(e){return e=e.toLowerCase(),!E&&!~_.inArray(e,["set-cookie","set-cookie2"])&&v&&""!==v&&(t||(t={},_.each(v.split(/\r\n/),function(e){e=e.split(/:\s+/);2===e.length&&(e[0]=_.trim(e[0]),t[e[0].toLowerCase()]={header:e[0],value:_.trim(e[1])})})),t.hasOwnProperty(e))?t[e].header+": "+t[e].value:null},overrideMimeType:function(e){var t,i;if(~_.inArray(R("readyState"),[F.LOADING,F.DONE]))throw new b.DOMException(b.DOMException.INVALID_STATE_ERR);if(e=_.trim(e.toLowerCase()),/;/.test(e)&&(t=e.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))&&(e=t[1],t[2])&&(i=t[2]),!N.mimes[e])throw new b.DOMException(b.DOMException.SYNTAX_ERR);0},send:function(e,t){if(w="string"===_.typeOf(t)?{ruid:t}:t||{},this.readyState!==F.OPENED||p)throw new b.DOMException(b.DOMException.INVALID_STATE_ERR);e instanceof r?(w.ruid=e.ruid,h=e.type||"application/octet-stream"):e instanceof O?e.hasBlob()&&(t=e.getBlob(),w.ruid=t.ruid,h=t.type||"application/octet-stream"):"string"==typeof e&&(m="UTF-8",h="text/plain;charset=UTF-8",e=A.utf8_encode(e)),this.withCredentials||(this.withCredentials=w.required_caps&&w.required_caps.send_browser_cookies&&!y),g=!f&&this.upload.hasEventListener(),E=!1,x=!e,f||(p=!0),function(e){var i=this;function n(){c&&(c.destroy(),c=null),i.dispatchEvent("loadend"),i=null}function r(t){c.bind("LoadStart",function(e){R("readyState",F.LOADING),i.dispatchEvent("readystatechange"),i.dispatchEvent(e),g&&i.upload.dispatchEvent(e)}),c.bind("Progress",function(e){R("readyState")!==F.LOADING&&(R("readyState",F.LOADING),i.dispatchEvent("readystatechange")),i.dispatchEvent(e)}),c.bind("UploadProgress",function(e){g&&i.upload.dispatchEvent({type:"progress",lengthComputable:!1,total:e.total,loaded:e.loaded})}),c.bind("Load",function(e){R("readyState",F.DONE),R("status",Number(t.exec.call(c,"XMLHttpRequest","getStatus")||0)),R("statusText",C[R("status")]||""),R("response",t.exec.call(c,"XMLHttpRequest","getResponse",R("responseType"))),~_.inArray(R("responseType"),["text",""])?R("responseText",R("response")):"document"===R("responseType")&&R("responseXML",R("response")),v=t.exec.call(c,"XMLHttpRequest","getAllResponseHeaders"),i.dispatchEvent("readystatechange"),0<R("status")?(g&&i.upload.dispatchEvent(e),i.dispatchEvent(e)):(E=!0,i.dispatchEvent("error")),n()}),c.bind("Abort",function(e){i.dispatchEvent(e),n()}),c.bind("Error",function(e){E=!0,R("readyState",F.DONE),i.dispatchEvent("readystatechange"),x=!0,i.dispatchEvent(e),n()}),t.exec.call(c,"XMLHttpRequest","send",{url:o,method:s,async:l,user:a,password:u,headers:d,mimeType:h,encoding:m,responseType:i.responseType,withCredentials:i.withCredentials,options:w},e)}(new Date).getTime(),c=new S,"string"==typeof w.required_caps&&(w.required_caps=T.parseCaps(w.required_caps));w.required_caps=_.extend({},w.required_caps,{return_response_type:i.responseType}),e instanceof O&&(w.required_caps.send_multipart=!0);_.isEmptyObj(d)||(w.required_caps.send_custom_headers=!0);y||(w.required_caps.do_cors=!0);w.ruid?r(c.connectRuntime(w)):(c.bind("RuntimeInit",function(e,t){r(t)}),c.bind("RuntimeError",function(e,t){i.dispatchEvent("RuntimeError",t)}),c.connectRuntime(w))}.call(this,e)},abort:function(){if(f=!(E=!0),~_.inArray(R("readyState"),[F.UNSENT,F.OPENED,F.DONE]))R("readyState",F.UNSENT);else{if(R("readyState",F.DONE),p=!1,!c)throw new b.DOMException(b.DOMException.INVALID_STATE_ERR);c.getRuntime().exec.call(c,"XMLHttpRequest","abort",x),x=!0}},destroy:function(){c&&("function"===_.typeOf(c.destroy)&&c.destroy(),c=null),this.unbindAll(),this.upload&&(this.upload.unbindAll(),this.upload=null)}}),this.handleEventProps(L.concat(["readystatechange"])),this.upload.handleEventProps(L)}return F.UNSENT=0,F.OPENED=1,F.HEADERS_RECEIVED=2,F.LOADING=3,F.DONE=4,F.prototype=e.instance,F}),e("moxie/runtime/Transporter",["moxie/core/utils/Basic","moxie/core/utils/Encode","moxie/runtime/RuntimeClient","moxie/core/EventTarget"],function(m,t,e,i){function h(){var o,n,s,a,r,u;function c(){a=r=0,s=this.result=null}function l(e,t){var i=this;n=t,i.bind("TransportingProgress",function(e){(r=e.loaded)<a&&-1===m.inArray(i.state,[h.IDLE,h.DONE])&&d.call(i)},999),i.bind("TransportingComplete",function(){r=a,i.state=h.DONE,s=null,i.result=n.exec.call(i,"Transporter","getAsBlob",e||"")},999),i.state=h.BUSY,i.trigger("TransportingStarted"),d.call(i)}function d(){var e=a-r;e<u&&(u=e),e=t.btoa(s.substr(r,u)),n.exec.call(this,"Transporter","receive",e,a)}e.call(this),m.extend(this,{uid:m.guid("uid_"),state:h.IDLE,result:null,transport:function(e,i,t){var n,r=this;t=m.extend({chunk_size:204798},t),(o=t.chunk_size%3)&&(t.chunk_size+=3-o),u=t.chunk_size,c.call(this),a=(s=e).length,"string"===m.typeOf(t)||t.ruid?l.call(r,i,this.connectRuntime(t)):(n=function(e,t){r.unbind("RuntimeInit",n),l.call(r,i,t)},this.bind("RuntimeInit",n),this.connectRuntime(t))},abort:function(){this.state=h.IDLE,n&&(n.exec.call(this,"Transporter","clear"),this.trigger("TransportingAborted")),c.call(this)},destroy:function(){this.unbindAll(),n=null,this.disconnectRuntime(),c.call(this)}})}return h.IDLE=0,h.BUSY=1,h.DONE=2,h.prototype=i.instance,h}),e("moxie/image/Image",["moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/file/FileReaderSync","moxie/xhr/XMLHttpRequest","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/runtime/Transporter","moxie/core/utils/Env","moxie/core/EventTarget","moxie/file/Blob","moxie/file/File","moxie/core/utils/Encode"],function(a,n,u,e,o,s,t,c,l,i,d,m,h){var f=["progress","load","error","resize","embedded"];function p(){function i(e){var t=a.typeOf(e);try{if(e instanceof p){if(!e.size)throw new u.DOMException(u.DOMException.INVALID_STATE_ERR);!function(e,t){var i=this.connectRuntime(e.ruid);this.ruid=i.uid,i.exec.call(this,"Image","loadFromImage",e,"undefined"===a.typeOf(t)||t)}.apply(this,arguments)}else if(e instanceof d){if(!~a.inArray(e.type,["image/jpeg","image/png"]))throw new u.ImageError(u.ImageError.WRONG_FORMAT);r.apply(this,arguments)}else if(-1!==a.inArray(t,["blob","file"]))i.call(this,new m(null,e),arguments[1]);else if("string"===t)"data:"===e.substr(0,5)?i.call(this,new d(null,{data:e}),arguments[1]):function(e,t){var i,n=this;(i=new o).open("get",e),i.responseType="blob",i.onprogress=function(e){n.trigger(e)},i.onload=function(){r.call(n,i.response,!0)},i.onerror=function(e){n.trigger(e)},i.onloadend=function(){i.destroy()},i.bind("RuntimeError",function(e,t){n.trigger("RuntimeError",t)}),i.send(null,t)}.apply(this,arguments);else{if("node"!==t||"img"!==e.nodeName.toLowerCase())throw new u.DOMException(u.DOMException.TYPE_MISMATCH_ERR);i.call(this,e.src,arguments[1])}}catch(e){this.trigger("error",e.code)}}function r(t,e){var i=this;function n(e){i.ruid=e.uid,e.exec.call(i,"Image","loadFromBlob",t)}i.name=t.name||"",t.isDetached()?(this.bind("RuntimeInit",function(e,t){n(t)}),e&&"string"==typeof e.required_caps&&(e.required_caps=s.parseCaps(e.required_caps)),this.connectRuntime(a.extend({required_caps:{access_image_binary:!0,resize_image:!0}},e))):n(this.connectRuntime(t.ruid))}t.call(this),a.extend(this,{uid:a.guid("uid_"),ruid:null,name:"",size:0,width:0,height:0,type:"",meta:{},clone:function(){this.load.apply(this,arguments)},load:function(){i.apply(this,arguments)},downsize:function(e){var t={width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90,crop:!1,preserveHeaders:!0,resample:!1};e="object"==typeof e?a.extend(t,e):a.extend(t,{width:arguments[0],height:arguments[1],crop:arguments[2],preserveHeaders:arguments[3]});try{if(!this.size)throw new u.DOMException(u.DOMException.INVALID_STATE_ERR);if(this.width>p.MAX_RESIZE_WIDTH||this.height>p.MAX_RESIZE_HEIGHT)throw new u.ImageError(u.ImageError.MAX_RESOLUTION_ERR);this.exec("Image","downsize",e.width,e.height,e.crop,e.preserveHeaders)}catch(e){this.trigger("error",e.code)}},crop:function(e,t,i){this.downsize(e,t,!0,i)},getAsCanvas:function(){if(l.can("create_canvas"))return this.connectRuntime(this.ruid).exec.call(this,"Image","getAsCanvas");throw new u.RuntimeError(u.RuntimeError.NOT_SUPPORTED_ERR)},getAsBlob:function(e,t){if(this.size)return this.exec("Image","getAsBlob",e||"image/jpeg",t||90);throw new u.DOMException(u.DOMException.INVALID_STATE_ERR)},getAsDataURL:function(e,t){if(this.size)return this.exec("Image","getAsDataURL",e||"image/jpeg",t||90);throw new u.DOMException(u.DOMException.INVALID_STATE_ERR)},getAsBinaryString:function(e,t){e=this.getAsDataURL(e,t);return h.atob(e.substring(e.indexOf("base64,")+7))},embed:function(r,e){var o,s=this;e=a.extend({width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90},e||{});try{if(!(r=n.get(r)))throw new u.DOMException(u.DOMException.INVALID_NODE_TYPE_ERR);if(!this.size)throw new u.DOMException(u.DOMException.INVALID_STATE_ERR);this.width>p.MAX_RESIZE_WIDTH||this.height;var t=new p;return t.bind("Resize",function(){!function(e,t){var i=this;if(l.can("create_canvas")){var n=i.getAsCanvas();if(n)return r.appendChild(n),i.destroy(),void s.trigger("embedded")}if(!(n=i.getAsDataURL(e,t)))throw new u.ImageError(u.ImageError.WRONG_FORMAT);l.can("use_data_uri_of",n.length)?(r.innerHTML='<img src="'+n+'" width="'+i.width+'" height="'+i.height+'" />',i.destroy(),s.trigger("embedded")):((t=new c).bind("TransportingComplete",function(){o=s.connectRuntime(this.result.ruid),s.bind("Embedded",function(){a.extend(o.getShimContainer().style,{top:"0px",left:"0px",width:i.width+"px",height:i.height+"px"}),o=null},999),o.exec.call(s,"ImageView","display",this.result.uid,width,height),i.destroy()}),t.transport(h.atob(n.substring(n.indexOf("base64,")+7)),e,{required_caps:{display_media:!0},runtime_order:"flash,silverlight",container:r}))}.call(this,e.type,e.quality)}),t.bind("Load",function(){t.downsize(e)}),this.meta.thumb&&this.meta.thumb.width>=e.width&&this.meta.thumb.height>=e.height?t.load(this.meta.thumb.data):t.clone(this,!1),t}catch(e){this.trigger("error",e.code)}},destroy:function(){this.ruid&&(this.getRuntime().exec.call(this,"Image","destroy"),this.disconnectRuntime()),this.unbindAll()}}),this.handleEventProps(f),this.bind("Load Resize",function(){!function(e){e=e||this.exec("Image","getInfo");this.size=e.size,this.width=e.width,this.height=e.height,this.type=e.type,this.meta=e.meta,""===this.name&&(this.name=e.name)}.call(this)},999)}return p.MAX_RESIZE_WIDTH=8192,p.MAX_RESIZE_HEIGHT=8192,p.prototype=i.instance,p}),e("moxie/runtime/html5/Runtime",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/Runtime","moxie/core/utils/Env"],function(s,e,a,u){var c={};return a.addConstructor("html5",function(e){var t,i=this,n=a.capTest,r=a.capTrue,o=s.extend({access_binary:n(window.FileReader||window.File&&window.File.getAsDataURL),access_image_binary:function(){return i.can("access_binary")&&!!c.Image},display_media:n(u.can("create_canvas")||u.can("use_data_uri_over32kb")),do_cors:n(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest),drag_and_drop:n(("draggable"in(o=document.createElement("div"))||"ondragstart"in o&&"ondrop"in o)&&("IE"!==u.browser||u.verComp(u.version,9,">"))),filter_by_extension:n("Chrome"===u.browser&&u.verComp(u.version,28,">=")||"IE"===u.browser&&u.verComp(u.version,10,">=")||"Safari"===u.browser&&u.verComp(u.version,7,">=")),return_response_headers:r,return_response_type:function(e){return!("json"!==e||!window.JSON)||u.can("return_response_type",e)},return_status_code:r,report_upload_progress:n(window.XMLHttpRequest&&(new XMLHttpRequest).upload),resize_image:function(){return i.can("access_binary")&&u.can("create_canvas")},select_file:function(){return u.can("use_fileinput")&&window.File},select_folder:function(){return i.can("select_file")&&"Chrome"===u.browser&&u.verComp(u.version,21,">=")},select_multiple:function(){return i.can("select_file")&&!("Safari"===u.browser&&"Windows"===u.os)&&!("iOS"===u.os&&u.verComp(u.osVersion,"7.0.0",">")&&u.verComp(u.osVersion,"8.0.0","<"))},send_binary_string:n(window.XMLHttpRequest&&((new XMLHttpRequest).sendAsBinary||window.Uint8Array&&window.ArrayBuffer)),send_custom_headers:n(window.XMLHttpRequest),send_multipart:function(){return!!(window.XMLHttpRequest&&(new XMLHttpRequest).upload&&window.FormData)||i.can("send_binary_string")},slice_blob:n(window.File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice)),stream_upload:function(){return i.can("slice_blob")&&i.can("send_multipart")},summon_file_dialog:function(){return i.can("select_file")&&("Firefox"===u.browser&&u.verComp(u.version,4,">=")||"Opera"===u.browser&&u.verComp(u.version,12,">=")||"IE"===u.browser&&u.verComp(u.version,10,">=")||!!~s.inArray(u.browser,["Chrome","Safari"]))},upload_filesize:r},arguments[2]);a.call(this,e,arguments[1]||"html5",o),s.extend(this,{init:function(){this.trigger("Init")},destroy:(t=this.destroy,function(){t.call(i),t=i=null})}),s.extend(this.getShim(),c)}),c}),e("moxie/core/utils/Events",["moxie/core/utils/Basic"],function(o){var s={},a="moxie_"+o.guid();function u(){this.returnValue=!1}function c(){this.cancelBubble=!0}function r(t,e,i){if(e=e.toLowerCase(),t[a]&&s[t[a]]&&s[t[a]][e]){for(var n,r=(n=s[t[a]][e]).length-1;0<=r&&(n[r].orig!==i&&n[r].key!==i||(t.removeEventListener?t.removeEventListener(e,n[r].func,!1):t.detachEvent&&t.detachEvent("on"+e,n[r].func),n[r].orig=null,n[r].func=null,n.splice(r,1),void 0===i));r--);if(n.length||delete s[t[a]][e],o.isEmptyObj(s[t[a]])){delete s[t[a]];try{delete t[a]}catch(e){t[a]=void 0}}}}return{addEvent:function(e,t,i,n){var r;t=t.toLowerCase(),e.addEventListener?e.addEventListener(t,r=i,!1):e.attachEvent&&e.attachEvent("on"+t,r=function(){var e=window.event;e.target||(e.target=e.srcElement),e.preventDefault=u,e.stopPropagation=c,i(e)}),e[a]||(e[a]=o.guid()),s.hasOwnProperty(e[a])||(s[e[a]]={}),(e=s[e[a]]).hasOwnProperty(t)||(e[t]=[]),e[t].push({func:r,orig:i,key:n})},removeEvent:r,removeAllEvents:function(i,n){i&&i[a]&&o.each(s[i[a]],function(e,t){r(i,t,n)})}}}),e("moxie/runtime/html5/file/FileInput",["moxie/runtime/html5/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/utils/Mime","moxie/core/utils/Env"],function(e,a,u,c,l,d,m){return e.FileInput=function(){var s;u.extend(this,{init:function(e){var t,i,n,r=this,o=r.getRuntime(),e=(s=e).accept.mimes||d.extList2mimes(s.accept,o.can("filter_by_extension"));(t=o.getShimContainer()).innerHTML='<input id="'+o.uid+'" type="file" style="font-size:999px;opacity:0;"'+(s.multiple&&o.can("select_multiple")?"multiple":"")+(s.directory&&o.can("select_folder")?"webkitdirectory directory":"")+(e?' accept="'+e.join(",")+'"':"")+" />",e=c.get(o.uid),u.extend(e.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),i=c.get(s.browse_button),o.can("summon_file_dialog")&&("static"===c.getStyle(i,"position")&&(i.style.position="relative"),n=parseInt(c.getStyle(i,"z-index"),10)||1,i.style.zIndex=n,t.style.zIndex=n-1,l.addEvent(i,"click",function(e){var t=c.get(o.uid);t&&!t.disabled&&t.click(),e.preventDefault()},r.uid)),n=o.can("summon_file_dialog")?i:t,l.addEvent(n,"mouseover",function(){r.trigger("mouseenter")},r.uid),l.addEvent(n,"mouseout",function(){r.trigger("mouseleave")},r.uid),l.addEvent(n,"mousedown",function(){r.trigger("mousedown")},r.uid),l.addEvent(c.get(s.container),"mouseup",function(){r.trigger("mouseup")},r.uid),e.onchange=function e(t){var i;r.files=[],u.each(this.files,function(e){var t="";if(s.directory&&"."==e.name)return!0;e.webkitRelativePath&&(t="/"+e.webkitRelativePath.replace(/^\//,"")),(e=new a(o.uid,e)).relativePath=t,r.files.push(e)}),"IE"!==m.browser&&"IEMobile"!==m.browser?this.value="":(i=this.cloneNode(!0),this.parentNode.replaceChild(i,this),i.onchange=e),r.files.length&&r.trigger("change")},r.trigger({type:"ready",async:!0})},disable:function(e){var t=this.getRuntime();(t=c.get(t.uid))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),e=e.getShimContainer();l.removeAllEvents(e,this.uid),l.removeAllEvents(s&&c.get(s.container),this.uid),l.removeAllEvents(s&&c.get(s.browse_button),this.uid),e&&(e.innerHTML=""),t.removeInstance(this.uid),s=null}})}}),e("moxie/runtime/html5/file/Blob",["moxie/runtime/html5/Runtime","moxie/file/Blob"],function(e,t){return e.Blob=function(){this.slice=function(){return new t(this.getRuntime().uid,function(t,i,n){var e;if(!window.File.prototype.slice)return(e=window.File.prototype.webkitSlice||window.File.prototype.mozSlice)?e.call(t,i,n):null;try{return t.slice(),t.slice(i,n)}catch(e){return t.slice(i,n-i)}}.apply(this,arguments))}}}),e("moxie/runtime/html5/file/FileDrop",["moxie/runtime/html5/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/utils/Mime"],function(e,r,l,i,d,m){return e.FileDrop=function(){var t,n,o=[],s=[];function a(e){if(e.dataTransfer&&e.dataTransfer.types)return e=l.toArray(e.dataTransfer.types||[]),-1!==l.inArray("Files",e)||-1!==l.inArray("public.file-url",e)||-1!==l.inArray("application/x-moz-file",e)}function u(e,t){var i;i=e,s.length&&(i=m.getFileExtension(i.name))&&-1===l.inArray(i,s)||((i=new r(n,e)).relativePath=t||"",o.push(i))}function c(e,t){var i=[];l.each(e,function(s){i.push(function(e){{var t,n,r;(o=e,(i=s).isFile)?i.file(function(e){u(e,i.fullPath),o()},function(){o()}):i.isDirectory?(t=o,n=[],r=(e=i).createReader(),function t(i){r.readEntries(function(e){e.length?([].push.apply(n,e),t(i)):i()},i)}(function(){c(n,t)})):o()}var i,o})}),l.inSeries(i,function(){t()})}l.extend(this,{init:function(e){var r=this;t=e,n=r.ruid,s=function(e){for(var t=[],i=0;i<e.length;i++)[].push.apply(t,e[i].extensions.split(/\s*,\s*/));return-1===l.inArray("*",t)?t:[]}(t.accept),e=t.container,d.addEvent(e,"dragover",function(e){a(e)&&(e.preventDefault(),e.dataTransfer.dropEffect="copy")},r.uid),d.addEvent(e,"drop",function(e){var t,i,n;a(e)&&(e.preventDefault(),o=[],e.dataTransfer.items&&e.dataTransfer.items[0].webkitGetAsEntry?(t=e.dataTransfer.items,i=function(){r.files=o,r.trigger("drop")},n=[],l.each(t,function(e){var t=e.webkitGetAsEntry();t&&(t.isFile?u(e.getAsFile(),t.fullPath):n.push(t))}),n.length?c(n,i):i()):(l.each(e.dataTransfer.files,function(e){u(e)}),r.files=o,r.trigger("drop")))},r.uid),d.addEvent(e,"dragenter",function(e){r.trigger("dragenter")},r.uid),d.addEvent(e,"dragleave",function(e){r.trigger("dragleave")},r.uid)},destroy:function(){d.removeAllEvents(t&&i.get(t.container),this.uid),n=o=s=t=null}})}}),e("moxie/runtime/html5/file/FileReader",["moxie/runtime/html5/Runtime","moxie/core/utils/Encode","moxie/core/utils/Basic"],function(e,o,s){return e.FileReader=function(){var n,r=!1;s.extend(this,{read:function(e,t){var i=this;i.result="",(n=new window.FileReader).addEventListener("progress",function(e){i.trigger(e)}),n.addEventListener("load",function(e){var t;i.result=r?(t=n.result,o.atob(t.substring(t.indexOf("base64,")+7))):n.result,i.trigger(e)}),n.addEventListener("error",function(e){i.trigger(e,n.error)}),n.addEventListener("loadend",function(e){n=null,i.trigger(e)}),"function"===s.typeOf(n[e])?(r=!1,n[e](t.getSource())):"readAsBinaryString"===e&&(r=!0,n.readAsDataURL(t.getSource()))},abort:function(){n&&n.abort()},destroy:function(){n=null}})}}),e("moxie/runtime/html5/xhr/XMLHttpRequest",["moxie/runtime/html5/Runtime","moxie/core/utils/Basic","moxie/core/utils/Mime","moxie/core/utils/Url","moxie/file/File","moxie/file/Blob","moxie/xhr/FormData","moxie/core/Exceptions","moxie/core/utils/Env"],function(e,m,u,h,f,p,g,x,E){return e.XMLHttpRequest=function(){var c,l,d=this;m.extend(this,{send:function(e,t){var i,n=this,r="Mozilla"===E.browser&&E.verComp(E.version,4,">=")&&E.verComp(E.version,7,"<"),o="Android Browser"===E.browser,s=!1;if(l=e.url.replace(/^.+?\/([\w\-\.]+)$/,"$1").toLowerCase(),(c=!window.XMLHttpRequest||"IE"===E.browser&&E.verComp(E.version,8,"<")?function(){for(var e=["Msxml2.XMLHTTP.6.0","Microsoft.XMLHTTP"],t=0;t<e.length;t++)try{return new ActiveXObject(e[t])}catch(e){}}():new window.XMLHttpRequest).open(e.method,e.url,e.async,e.user,e.password),t instanceof p)t.isDetached()&&(s=!0),t=t.getSource();else if(t instanceof g){if(t.hasBlob())if(t.getBlob().isDetached())t=function(e){var i="----moxieboundary"+(new Date).getTime(),n="\r\n",r="";if(this.getRuntime().can("send_binary_string"))return c.setRequestHeader("Content-Type","multipart/form-data; boundary="+i),e.each(function(e,t){e instanceof p?r+="--"+i+n+'Content-Disposition: form-data; name="'+t+'"; filename="'+unescape(encodeURIComponent(e.name||"blob"))+'"'+n+"Content-Type: "+(e.type||"application/octet-stream")+n+n+e.getSource()+n:r+="--"+i+n+'Content-Disposition: form-data; name="'+t+'"'+n+n+unescape(encodeURIComponent(e))+n}),r+="--"+i+"--"+n;throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR)}.call(n,t),s=!0;else if((r||o)&&"blob"===m.typeOf(t.getBlob().getSource())&&window.FileReader)return void function(e,t){var i,n,r=this;i=t.getBlob().getSource(),(n=new window.FileReader).onload=function(){t.append(t.getBlobName(),new p(null,{type:i.type,data:n.result})),d.send.call(r,e,t)},n.readAsBinaryString(i)}.call(n,e,t);t instanceof g&&(i=new window.FormData,t.each(function(e,t){e instanceof p?i.append(t,e.getSource()):i.append(t,e)}),t=i)}if(c.upload?(e.withCredentials&&(c.withCredentials=!0),c.addEventListener("load",function(e){n.trigger(e)}),c.addEventListener("error",function(e){n.trigger(e)}),c.addEventListener("progress",function(e){n.trigger(e)}),c.upload.addEventListener("progress",function(e){n.trigger({type:"UploadProgress",loaded:e.loaded,total:e.total})})):c.onreadystatechange=function(){switch(c.readyState){case 1:case 2:break;case 3:var t,i;try{h.hasSameOrigin(e.url)&&(t=c.getResponseHeader("Content-Length")||0),c.responseText&&(i=c.responseText.length)}catch(e){t=i=0}n.trigger({type:"progress",lengthComputable:!!t,total:parseInt(t,10),loaded:i});break;case 4:c.onreadystatechange=function(){},0===c.status?n.trigger("error"):n.trigger("load")}},m.isEmptyObj(e.headers)||m.each(e.headers,function(e,t){c.setRequestHeader(t,e)}),""!==e.responseType&&"responseType"in c&&("json"!==e.responseType||E.can("return_response_type","json")?c.responseType=e.responseType:c.responseType="text"),s)if(c.sendAsBinary)c.sendAsBinary(t);else{for(var a=new Uint8Array(t.length),u=0;u<t.length;u++)a[u]=255&t.charCodeAt(u);c.send(a.buffer)}else c.send(t);n.trigger("loadstart")},getStatus:function(){try{if(c)return c.status}catch(e){}return 0},getResponse:function(e){var t=this.getRuntime();try{switch(e){case"blob":var i,n=new f(t.uid,c.response),r=c.getResponseHeader("Content-Disposition");return r&&(i=r.match(/filename=([\'\"'])([^\1]+)\1/))&&(l=i[2]),n.name=l,n.type||(n.type=u.getFileMime(l)),n;case"json":return E.can("return_response_type","json")?c.response:200===c.status&&window.JSON?JSON.parse(c.responseText):null;case"document":var o=c,s=o.responseXML,a=o.responseText;return"IE"===E.browser&&a&&s&&!s.documentElement&&/[^\/]+\/[^\+]+\+xml/.test(o.getResponseHeader("Content-Type"))&&((s=new window.ActiveXObject("Microsoft.XMLDOM")).async=!1,s.validateOnParse=!1,s.loadXML(a)),s&&("IE"===E.browser&&0!==s.parseError||!s.documentElement||"parsererror"===s.documentElement.tagName)?null:s;default:return""!==c.responseText?c.responseText:null}}catch(e){return null}},getAllResponseHeaders:function(){try{return c.getAllResponseHeaders()}catch(e){}return""},abort:function(){c&&c.abort()},destroy:function(){d=l=null}})}}),e("moxie/runtime/html5/utils/BinaryReader",["moxie/core/utils/Basic"],function(t){function e(e){(e instanceof ArrayBuffer?function(r){var o=new DataView(r);t.extend(this,{readByteAt:function(e){return o.getUint8(e)},writeByteAt:function(e,t){o.setUint8(e,t)},SEGMENT:function(e,t,i){switch(arguments.length){case 2:return r.slice(e,e+t);case 1:return r.slice(e);case 3:if((i=null===i?new ArrayBuffer:i)instanceof ArrayBuffer){var n=new Uint8Array(this.length()-t+i.byteLength);0<e&&n.set(new Uint8Array(r.slice(0,e)),0),n.set(new Uint8Array(i),e),n.set(new Uint8Array(r.slice(e+t)),e+i.byteLength),this.clear(),r=n.buffer,o=new DataView(r);break}default:return r}},length:function(){return r?r.byteLength:0},clear:function(){o=r=null}})}:function(n){function r(e,t,i){i=3===arguments.length?i:n.length-t-1,n=n.substr(0,t)+e+n.substr(i+t)}t.extend(this,{readByteAt:function(e){return n.charCodeAt(e)},writeByteAt:function(e,t){r(String.fromCharCode(t),e,1)},SEGMENT:function(e,t,i){switch(arguments.length){case 1:return n.substr(e);case 2:return n.substr(e,t);case 3:r(null!==i?i:"",e,t);break;default:return n}},length:function(){return n?n.length:0},clear:function(){n=null}})}).apply(this,arguments)}return t.extend(e.prototype,{littleEndian:!1,read:function(e,t){var i,n,r;if(e+t>this.length())throw new Error("You are trying to read outside the source boundaries.");for(n=this.littleEndian?0:-8*(t-1),i=r=0;r<t;r++)i|=this.readByteAt(e+r)<<Math.abs(n+8*r);return i},write:function(e,t,i){var n,r;if(e>this.length())throw new Error("You are trying to write outside the source boundaries.");for(n=this.littleEndian?0:-8*(i-1),r=0;r<i;r++)this.writeByteAt(e+r,t>>Math.abs(n+8*r)&255)},BYTE:function(e){return this.read(e,1)},SHORT:function(e){return this.read(e,2)},LONG:function(e){return this.read(e,4)},SLONG:function(e){e=this.read(e,4);return 2147483647<e?e-4294967296:e},CHAR:function(e){return String.fromCharCode(this.read(e,1))},STRING:function(e,t){return this.asArray("CHAR",e,t).join("")},asArray:function(e,t,i){for(var n=[],r=0;r<i;r++)n[r]=this[e](t+r);return n}}),e}),e("moxie/runtime/html5/image/JPEGHeaders",["moxie/runtime/html5/utils/BinaryReader","moxie/core/Exceptions"],function(a,u){return function o(e){var r,t,i,s=[],n=new a(e);if(65496!==n.SHORT(0))throw n.clear(),new u.ImageError(u.ImageError.WRONG_FORMAT);for(r=2;r<=n.length();)if(65488<=(t=n.SHORT(r))&&t<=65495)r+=2;else{if(65498===t||65497===t)break;i=n.SHORT(r+2)+2,65505<=t&&t<=65519&&s.push({hex:t,name:"APP"+(15&t),start:r,length:i,segment:n.SEGMENT(r,i)}),r+=i}return n.clear(),{headers:s,restore:function(e){var t,i,n=new a(e);for(r=65504==n.SHORT(2)?4+n.SHORT(4):2,i=0,t=s.length;i<t;i++)n.SEGMENT(r,0,s[i].segment),r+=s[i].length;return e=n.SEGMENT(),n.clear(),e},strip:function(e){var t,i,n=new o(e),r=n.headers;for(n.purge(),t=new a(e),i=r.length;i--;)t.SEGMENT(r[i].start,r[i].length,"");return e=t.SEGMENT(),t.clear(),e},get:function(e){for(var t=[],i=0,n=s.length;i<n;i++)s[i].name===e.toUpperCase()&&t.push(s[i].segment);return t},set:function(e,t){var i,n,r,o=[];for("string"==typeof t?o.push(t):o=t,i=n=0,r=s.length;i<r&&(s[i].name===e.toUpperCase()&&(s[i].segment=o[n],s[i].length=o[n].length,n++),!(n>=o.length));i++);},purge:function(){this.headers=s=[]}}}}),e("moxie/runtime/html5/image/ExifParser",["moxie/core/utils/Basic","moxie/runtime/html5/utils/BinaryReader","moxie/core/Exceptions"],function(p,o,g){function s(e){var t,l,h,f,i;if(o.call(this,e),l={tiff:{274:"Orientation",270:"ImageDescription",271:"Make",272:"Model",305:"Software",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37386:"FocalLength",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"},thumb:{513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength"}},h={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}},n=(f={tiffHeader:10}).tiffHeader,t={clear:this.clear},p.extend(this,{read:function(){try{return s.prototype.read.apply(this,arguments)}catch(e){throw new g.ImageError(g.ImageError.INVALID_META_ERR)}},write:function(){try{return s.prototype.write.apply(this,arguments)}catch(e){throw new g.ImageError(g.ImageError.INVALID_META_ERR)}},UNDEFINED:function(){return this.BYTE.apply(this,arguments)},RATIONAL:function(e){return this.LONG(e)/this.LONG(e+4)},SRATIONAL:function(e){return this.SLONG(e)/this.SLONG(e+4)},ASCII:function(e){return this.CHAR(e)},TIFF:function(){return i||null},EXIF:function(){var e=null;if(f.exifIFD){try{e=r.call(this,f.exifIFD,l.exif)}catch(e){return null}if(e.ExifVersion&&"array"===p.typeOf(e.ExifVersion)){for(var t=0,i="";t<e.ExifVersion.length;t++)i+=String.fromCharCode(e.ExifVersion[t]);e.ExifVersion=i}}return e},GPS:function(){var e=null;if(f.gpsIFD){try{e=r.call(this,f.gpsIFD,l.gps)}catch(e){return null}e.GPSVersionID&&"array"===p.typeOf(e.GPSVersionID)&&(e.GPSVersionID=e.GPSVersionID.join("."))}return e},thumb:function(){if(f.IFD1)try{var e=r.call(this,f.IFD1,l.thumb);if("JPEGInterchangeFormat"in e)return this.SEGMENT(f.tiffHeader+e.JPEGInterchangeFormat,e.JPEGInterchangeFormatLength)}catch(e){}return null},setExif:function(e,t){return("PixelXDimension"===e||"PixelYDimension"===e)&&function(e,t,i){var n,r,o,s=0;if("string"==typeof t){var a,u=l[e.toLowerCase()];for(a in u)if(u[a]===t){t=a;break}}n=f[e.toLowerCase()+"IFD"],r=this.SHORT(n);for(var c=0;c<r;c++)if(o=n+12*c+2,this.SHORT(o)==t){s=o+8;break}if(!s)return!1;try{this.write(s,i,4)}catch(e){return!1}return!0}.call(this,"exif",e,t)},clear:function(){t.clear(),e=l=h=i=f=t=null}}),65505!==this.SHORT(0)||"EXIF\0"!==this.STRING(4,5).toUpperCase())throw new g.ImageError(g.ImageError.INVALID_META_ERR);if(this.littleEndian=18761==this.SHORT(n),42!==this.SHORT(n+=2))throw new g.ImageError(g.ImageError.INVALID_META_ERR);f.IFD0=f.tiffHeader+this.LONG(n+=2),"ExifIFDPointer"in(i=r.call(this,f.IFD0,l.tiff))&&(f.exifIFD=f.tiffHeader+i.ExifIFDPointer,delete i.ExifIFDPointer),"GPSInfoIFDPointer"in i&&(f.gpsIFD=f.tiffHeader+i.GPSInfoIFDPointer,delete i.GPSInfoIFDPointer),p.isEmptyObj(i)&&(i=null);var n=this.LONG(f.IFD0+12*this.SHORT(f.IFD0)+2);function r(e,t){for(var i,n,r,o,s,a=this,u={},c={1:"BYTE",7:"UNDEFINED",2:"ASCII",3:"SHORT",4:"LONG",5:"RATIONAL",9:"SLONG",10:"SRATIONAL"},l={BYTE:1,UNDEFINED:1,ASCII:1,SHORT:2,LONG:4,RATIONAL:8,SLONG:4,SRATIONAL:8},d=a.SHORT(e),m=0;m<d;m++)if((i=t[a.SHORT(r=e+2+12*m)])!==x){if(o=c[a.SHORT(r+=2)],n=a.LONG(r+=2),!(s=l[o]))throw new g.ImageError(g.ImageError.INVALID_META_ERR);if(r+=4,(r=4<s*n?a.LONG(r)+f.tiffHeader:r)+s*n>=this.length())throw new g.ImageError(g.ImageError.INVALID_META_ERR);"ASCII"===o?u[i]=p.trim(a.STRING(r,n).replace(/\0$/,"")):(s=a.asArray(o,r,n),o=1==n?s[0]:s,h.hasOwnProperty(i)&&"object"!=typeof o?u[i]=h[i][o]:u[i]=o)}return u}n&&(f.IFD1=f.tiffHeader+n)}return s.prototype=o.prototype,s}),e("moxie/runtime/html5/image/JPEG",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/html5/image/JPEGHeaders","moxie/runtime/html5/utils/BinaryReader","moxie/runtime/html5/image/ExifParser"],function(s,a,u,c,l){return function(e){var i,n,t,r=new c(e);if(65496!==r.SHORT(0))throw new a.ImageError(a.ImageError.WRONG_FORMAT);i=new u(e);try{n=new l(i.get("app1")[0])}catch(e){}function o(e){var t,i=0;for(e=e||r;i<=e.length();){if(65472<=(t=e.SHORT(i+=2))&&t<=65475)return i+=5,{height:e.SHORT(i),width:e.SHORT(i+=2)};t=e.SHORT(i+=2),i+=t-2}return null}t=o.call(this),s.extend(this,{type:"image/jpeg",size:r.length(),width:t&&t.width||0,height:t&&t.height||0,setExif:function(e,t){if(!n)return!1;"object"===s.typeOf(e)?s.each(e,function(e,t){n.setExif(t,e)}):n.setExif(e,t),i.set("app1",n.SEGMENT())},writeHeaders:function(){return arguments.length?i.restore(arguments[0]):i.restore(e)},stripHeaders:function(e){return i.strip(e)},purge:function(){!function(){n&&i&&r&&(n.clear(),i.purge(),r.clear(),t=i=n=r=null)}.call(this)}}),n&&(this.meta={tiff:n.TIFF(),exif:n.EXIF(),gps:n.GPS(),thumb:function(){var e,t,i=n.thumb();if(i&&(e=new c(i),t=o(e),e.clear(),t))return t.data=i,t;return null}()})}}),e("moxie/runtime/html5/image/PNG",["moxie/core/Exceptions","moxie/core/utils/Basic","moxie/runtime/html5/utils/BinaryReader"],function(a,u,c){return function(e){for(var t,r=new c(e),i=0,n=0,o=[35152,20039,3338,6666],n=0;n<o.length;n++,i+=2)if(o[n]!=r.SHORT(i))throw new a.ImageError(a.ImageError.WRONG_FORMAT);function s(){r&&(r.clear(),e=t=r=null)}t=function(){var e=function(e){var t,i,n;return t=r.LONG(e),i=r.STRING(e+=4,4),n=e+=4,e=r.LONG(e+t),{length:t,type:i,start:n,CRC:e}}.call(this,8);return"IHDR"==e.type?(e=e.start,{width:r.LONG(e),height:r.LONG(e+=4)}):null}.call(this),u.extend(this,{type:"image/png",size:r.length(),width:t.width,height:t.height,purge:function(){s.call(this)}}),s.call(this)}}),e("moxie/runtime/html5/image/ImageInfo",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/html5/image/JPEG","moxie/runtime/html5/image/PNG"],function(n,r,o,s){return function(t){var i=[o,s],e=function(){for(var e=0;e<i.length;e++)try{return new i[e](t)}catch(e){}throw new r.ImageError(r.ImageError.WRONG_FORMAT)}();n.extend(this,{type:"",size:0,width:0,height:0,setExif:function(){},writeHeaders:function(e){return e},stripHeaders:function(e){return e},purge:function(){t=null}}),n.extend(this,e),this.purge=function(){e.purge(),e=null}}}),e("moxie/runtime/html5/image/MegaPixel",[],function(){function R(e){var t,i=e.naturalWidth;return 1048576<i*e.naturalHeight&&((t=document.createElement("canvas")).width=t.height=1,(t=t.getContext("2d")).drawImage(e,1-i,0),0===t.getImageData(0,0,1,1).data[3])}return{isSubsampled:R,renderTo:function(e,t,i){for(var n=e.naturalWidth,r=e.naturalHeight,o=i.width,s=i.height,a=i.x||0,u=i.y||0,c=t.getContext("2d"),l=(R(e)&&(n/=2,r/=2),1024),d=document.createElement("canvas"),m=(d.width=d.height=l,d.getContext("2d")),h=function(e,t){var i=document.createElement("canvas"),n=(i.width=1,i.height=t,i.getContext("2d")),r=(n.drawImage(e,0,0),n.getImageData(0,0,1,t).data),o=0,s=t,a=t;for(;o<a;)0===r[4*(a-1)+3]?s=a:o=a,a=s+o>>1;i=null;e=a/t;return 0==e?1:e}(e,r),f=0;f<r;){for(var p=r<f+l?r-f:l,g=0;g<n;){var x=n<g+l?n-g:l,E=(m.clearRect(0,0,l,l),m.drawImage(e,-g,-f),g*o/n+a<<0),y=Math.ceil(x*o/n),w=f*s/r/h+u<<0,v=Math.ceil(p*s/r/h);c.drawImage(d,0,0,x,p,E,w,y,v),g+=l}f+=l}}}}),e("moxie/runtime/html5/image/Image",["moxie/runtime/html5/Runtime","moxie/core/utils/Basic","moxie/core/Exceptions","moxie/core/utils/Encode","moxie/file/Blob","moxie/file/File","moxie/runtime/html5/image/ImageInfo","moxie/runtime/html5/image/MegaPixel","moxie/core/utils/Mime","moxie/core/utils/Env"],function(e,g,d,x,t,E,y,w,v,R){return e.Image=function(){var i,n,m,r,o,s=this,h=!1,f=!0;function p(){if(m||i)return m||i;throw new d.ImageError(d.DOMException.INVALID_STATE_ERR)}function a(e){return x.atob(e.substring(e.indexOf("base64,")+7))}function u(e){var t=this;(i=new Image).onerror=function(){l.call(this),t.trigger("error",d.ImageError.WRONG_FORMAT)},i.onload=function(){t.trigger("load")},i.src="data:"==e.substr(0,5)?e:"data:"+(o.type||"")+";base64,"+x.btoa(e)}function c(e,t,i,n){var r,o,s,a=0,u=0;if(f=n,o=this.meta&&this.meta.tiff&&this.meta.tiff.Orientation||1,-1!==g.inArray(o,[5,6,7,8])&&(s=e,e=t,t=s),s=p(),!(1<(r=i?(e=Math.min(e,s.width),t=Math.min(t,s.height),Math.max(e/s.width,t/s.height)):Math.min(e/s.width,t/s.height))&&!i&&n)){if(m=m||document.createElement("canvas"),n=Math.round(s.width*r),r=Math.round(s.height*r),i?(m.width=e,m.height=t,e<n&&(a=Math.round((n-e)/2)),t<r&&(u=Math.round((r-t)/2))):(m.width=n,m.height=r),!f){var c=m.width,l=m.height,i=o;switch(i){case 5:case 6:case 7:case 8:m.width=l,m.height=c;break;default:m.width=c,m.height=l}var d=m.getContext("2d");switch(i){case 2:d.translate(c,0),d.scale(-1,1);break;case 3:d.translate(c,l),d.rotate(Math.PI);break;case 4:d.translate(0,l),d.scale(1,-1);break;case 5:d.rotate(.5*Math.PI),d.scale(1,-1);break;case 6:d.rotate(.5*Math.PI),d.translate(0,-l);break;case 7:d.rotate(.5*Math.PI),d.translate(c,-l),d.scale(-1,1);break;case 8:d.rotate(-.5*Math.PI),d.translate(-c,0)}}!function(e,t,i,n,r,o){"iOS"===R.OS?w.renderTo(e,t,{width:r,height:o,x:i,y:n}):t.getContext("2d").drawImage(e,i,n,r,o)}.call(this,s,m,-a,-u,n,r),this.width=m.width,this.height=m.height,h=!0}this.trigger("Resize")}function l(){n&&(n.purge(),n=null),r=i=m=o=null,h=!1}g.extend(this,{loadFromBlob:function(e){var t=this,i=t.getRuntime(),n=!(1<arguments.length)||arguments[1];if(!i.can("access_binary"))throw new d.RuntimeError(d.RuntimeError.NOT_SUPPORTED_ERR);(o=e).isDetached()?(r=e.getSource(),u.call(this,r)):function(e,t){var i,n=this;{if(!window.FileReader)return t(e.getAsDataURL());(i=new FileReader).onload=function(){t(this.result)},i.onerror=function(){n.trigger("error",d.ImageError.WRONG_FORMAT)},i.readAsDataURL(e)}}.call(this,e.getSource(),function(e){n&&(r=a(e)),u.call(t,e)})},loadFromImage:function(e,t){this.meta=e.meta,o=new E(null,{name:e.name,size:e.size,type:e.type}),u.call(this,t?r=e.getAsBinaryString():e.getAsDataURL())},getInfo:function(){var e=this.getRuntime();return!n&&r&&e.can("access_image_binary")&&(n=new y(r)),!(e={width:p().width||0,height:p().height||0,type:o.type||v.getFileMime(o.name),size:r&&r.length||o.size||0,name:o.name||"",meta:n&&n.meta||this.meta||{}}).meta||!e.meta.thumb||e.meta.thumb.data instanceof t||(e.meta.thumb.data=new t(null,{type:"image/jpeg",data:e.meta.thumb.data})),e},downsize:function(){c.apply(this,arguments)},getAsCanvas:function(){return m&&(m.id=this.uid+"_canvas"),m},getAsBlob:function(e,t){return e!==this.type&&c.call(this,this.width,this.height,!1),new E(null,{name:o.name||"",type:e,data:s.getAsBinaryString.call(this,e,t)})},getAsDataURL:function(e){var t=arguments[1]||90;if(!h)return i.src;if("image/jpeg"!==e)return m.toDataURL("image/png");try{return m.toDataURL("image/jpeg",t/100)}catch(e){return m.toDataURL("image/jpeg")}},getAsBinaryString:function(e,t){if(!h)return r=r||a(s.getAsDataURL(e,t));if("image/jpeg"!==e)r=a(s.getAsDataURL(e,t));else{var i;t=t||90;try{i=m.toDataURL("image/jpeg",t/100)}catch(e){i=m.toDataURL("image/jpeg")}r=a(i),n&&(r=n.stripHeaders(r),f&&(n.meta&&n.meta.exif&&n.setExif({PixelXDimension:this.width,PixelYDimension:this.height}),r=n.writeHeaders(r)),n.purge(),n=null)}return h=!1,r},destroy:function(){s=null,l.call(this),this.getRuntime().getShim().removeInstance(this.uid)}})}}),e("moxie/runtime/flash/Runtime",[],function(){return{}}),e("moxie/runtime/silverlight/Runtime",[],function(){return{}}),e("moxie/runtime/html4/Runtime",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/Runtime","moxie/core/utils/Env"],function(o,e,s,a){var u={};return s.addConstructor("html4",function(e){var t,i=this,n=s.capTest,r=s.capTrue;s.call(this,e,"html4",{access_binary:n(window.FileReader||window.File&&File.getAsDataURL),access_image_binary:!1,display_media:n(u.Image&&(a.can("create_canvas")||a.can("use_data_uri_over32kb"))),do_cors:!1,drag_and_drop:!1,filter_by_extension:n("Chrome"===a.browser&&a.verComp(a.version,28,">=")||"IE"===a.browser&&a.verComp(a.version,10,">=")||"Safari"===a.browser&&a.verComp(a.version,7,">=")),resize_image:function(){return u.Image&&i.can("access_binary")&&a.can("create_canvas")},report_upload_progress:!1,return_response_headers:!1,return_response_type:function(e){return!("json"!==e||!window.JSON)||!!~o.inArray(e,["text","document",""])},return_status_code:function(e){return!o.arrayDiff(e,[200,404])},select_file:function(){return a.can("use_fileinput")},select_multiple:!1,send_binary_string:!1,send_custom_headers:!1,send_multipart:!0,slice_blob:!1,stream_upload:function(){return i.can("select_file")},summon_file_dialog:function(){return i.can("select_file")&&("Firefox"===a.browser&&a.verComp(a.version,4,">=")||"Opera"===a.browser&&a.verComp(a.version,12,">=")||"IE"===a.browser&&a.verComp(a.version,10,">=")||!!~o.inArray(a.browser,["Chrome","Safari"]))},upload_filesize:r,use_http_method:function(e){return!o.arrayDiff(e,["GET","POST"])}}),o.extend(this,{init:function(){this.trigger("Init")},destroy:(t=this.destroy,function(){t.call(i),t=i=null})}),o.extend(this.getShim(),u)}),u}),e("moxie/runtime/html4/file/FileInput",["moxie/runtime/html4/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/utils/Mime","moxie/core/utils/Env"],function(e,d,m,h,f,s,p){return e.FileInput=function(){var a,u,c=[];function l(){var e,t,i,n=this,r=n.getRuntime(),o=m.guid("uid_"),s=r.getShimContainer();a&&(e=h.get(a+"_form"))&&m.extend(e.style,{top:"100%"}),(t=document.createElement("form")).setAttribute("id",o+"_form"),t.setAttribute("method","post"),t.setAttribute("enctype","multipart/form-data"),t.setAttribute("encoding","multipart/form-data"),m.extend(t.style,{overflow:"hidden",position:"absolute",top:0,left:0,width:"100%",height:"100%"}),(i=document.createElement("input")).setAttribute("id",o),i.setAttribute("type","file"),i.setAttribute("name",u.name||"Filedata"),i.setAttribute("accept",c.join(",")),m.extend(i.style,{fontSize:"999px",opacity:0}),t.appendChild(i),s.appendChild(t),m.extend(i.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),"IE"===p.browser&&p.verComp(p.version,10,"<")&&m.extend(i.style,{filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"}),i.onchange=function(){var e;if(this.value){if(this.files){if(0===(e=this.files[0]).size)return void t.parentNode.removeChild(t)}else e={name:this.value};e=new d(r.uid,e),this.onchange=function(){},l.call(n),n.files=[e],i.setAttribute("id",e.uid),t.setAttribute("id",e.uid+"_form"),n.trigger("change"),i=t=null}},r.can("summon_file_dialog")&&(e=h.get(u.browse_button),f.removeEvent(e,"click",n.uid),f.addEvent(e,"click",function(e){i&&!i.disabled&&i.click(),e.preventDefault()},n.uid)),a=o}m.extend(this,{init:function(e){var t,i,n,r=this,o=r.getRuntime();c=(u=e).accept.mimes||s.extList2mimes(e.accept,o.can("filter_by_extension")),t=o.getShimContainer(),n=h.get(e.browse_button),o.can("summon_file_dialog")&&("static"===h.getStyle(n,"position")&&(n.style.position="relative"),i=parseInt(h.getStyle(n,"z-index"),10)||1,n.style.zIndex=i,t.style.zIndex=i-1),i=o.can("summon_file_dialog")?n:t,f.addEvent(i,"mouseover",function(){r.trigger("mouseenter")},r.uid),f.addEvent(i,"mouseout",function(){r.trigger("mouseleave")},r.uid),f.addEvent(i,"mousedown",function(){r.trigger("mousedown")},r.uid),f.addEvent(h.get(e.container),"mouseup",function(){r.trigger("mouseup")},r.uid),l.call(this),t=null,r.trigger({type:"ready",async:!0})},disable:function(e){var t;(t=h.get(a))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),e=e.getShimContainer();f.removeAllEvents(e,this.uid),f.removeAllEvents(u&&h.get(u.container),this.uid),f.removeAllEvents(u&&h.get(u.browse_button),this.uid),e&&(e.innerHTML=""),t.removeInstance(this.uid),a=c=u=null}})}}),e("moxie/runtime/html4/file/FileReader",["moxie/runtime/html4/Runtime","moxie/runtime/html5/file/FileReader"],function(e,t){return e.FileReader=t}),e("moxie/runtime/html4/xhr/XMLHttpRequest",["moxie/runtime/html4/Runtime","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Url","moxie/core/Exceptions","moxie/core/utils/Events","moxie/file/Blob","moxie/xhr/FormData"],function(e,m,h,f,p,g,x,E){return e.XMLHttpRequest=function(){var u,c,l;function d(t){var e,i,n,r=this,o=!1;if(l){if(e=l.id.replace(/_iframe$/,""),e=h.get(e+"_form")){for(n=(i=e.getElementsByTagName("input")).length;n--;)switch(i[n].getAttribute("type")){case"hidden":i[n].parentNode.removeChild(i[n]);break;case"file":o=!0}i=[],o||e.parentNode.removeChild(e),e=null}setTimeout(function(){g.removeEvent(l,"load",r.uid),l.parentNode&&l.parentNode.removeChild(l);var e=r.getRuntime().getShimContainer();e.children.length||e.parentNode.removeChild(e),e=l=null,t()},1)}}m.extend(this,{send:function(t,e){var i,n,r,o,s=this,a=s.getRuntime();if(u=c=null,e instanceof E&&e.hasBlob()){if(o=e.getBlob(),i=o.uid,r=h.get(i),!(n=h.get(i+"_form")))throw new p.DOMException(p.DOMException.NOT_FOUND_ERR)}else i=m.guid("uid_"),(n=document.createElement("form")).setAttribute("id",i+"_form"),n.setAttribute("method",t.method),n.setAttribute("enctype","multipart/form-data"),n.setAttribute("encoding","multipart/form-data"),a.getShimContainer().appendChild(n);n.setAttribute("target",i+"_iframe"),e instanceof E&&e.each(function(e,t){var i;e instanceof x?r&&r.setAttribute("name",t):(i=document.createElement("input"),m.extend(i,{type:"hidden",name:t,value:e}),r?n.insertBefore(i,r):n.appendChild(i))}),n.setAttribute("action",t.url),e=a.getShimContainer()||document.body,(a=document.createElement("div")).innerHTML='<iframe id="'+i+'_iframe" name="'+i+'_iframe" src="javascript:&quot;&quot;" style="display:none"></iframe>',l=a.firstChild,e.appendChild(l),g.addEvent(l,"load",function(){var e;try{e=l.contentWindow.document||l.contentDocument||window.frames[l.id].document,/^4(0[0-9]|1[0-7]|2[2346])\s/.test(e.title)?u=e.title.replace(/^(\d+).*$/,"$1"):(u=200,c=m.trim(e.body.innerHTML),s.trigger({type:"progress",loaded:c.length,total:c.length}),o&&s.trigger({type:"uploadprogress",loaded:o.size||1025,total:o.size||1025}))}catch(e){if(!f.hasSameOrigin(t.url))return void d.call(s,function(){s.trigger("error")});u=404}d.call(s,function(){s.trigger("load")})},s.uid),n.submit(),s.trigger("loadstart")},getStatus:function(){return u},getResponse:function(e){if("json"===e&&"string"===m.typeOf(c)&&window.JSON)try{return JSON.parse(c.replace(/^\s*<pre[^>]*>/,"").replace(/<\/pre>\s*$/,""))}catch(e){return null}return c},abort:function(){var e=this;l&&l.contentWindow&&(l.contentWindow.stop?l.contentWindow.stop():l.contentWindow.document.execCommand?l.contentWindow.document.execCommand("Stop"):l.src="about:blank"),d.call(this,function(){e.dispatchEvent("abort")})}})}}),e("moxie/runtime/html4/image/Image",["moxie/runtime/html4/Runtime","moxie/runtime/html5/image/Image"],function(e,t){return e.Image=t});for(var t=["moxie/core/utils/Basic","moxie/core/utils/Env","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/FileInput","moxie/core/utils/Encode","moxie/file/Blob","moxie/file/File","moxie/file/FileDrop","moxie/file/FileReader","moxie/core/utils/Url","moxie/runtime/RuntimeTarget","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/image/Image","moxie/core/utils/Events"],i=0;i<t.length;i++){for(var r=o,a=t[i],u=a.split(/[.\/]/),c=0;c<u.length-1;++c)r[u[c]]===x&&(r[u[c]]={}),r=r[u[c]];r[u[u.length-1]]=s[a]}}(this),function(e){"use strict";var r={},o=e.moxie.core.utils.Basic.inArray;!function e(t){var i,n;for(i in t)"object"!=(n=typeof t[i])||~o(i,["Exceptions","Env","Mime"])?"function"==n&&(r[i]=t[i]):e(t[i])}(e.moxie),r.Env=e.moxie.core.utils.Env,r.Mime=e.moxie.core.utils.Mime,r.Exceptions=e.moxie.core.Exceptions,e.mOxie=r,e.o||(e.o=r)}(this);
// source --> https://homelive.pt/wp-includes/js/plupload/plupload.min.js?ver=2.1.9 
!function(e,I,S){var T=e.setTimeout,D={};function w(e){var t=e.required_features,r={};function i(e,t,i){var n={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",urlstream_upload:"send_binary_string",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};n[e]?r[n[e]]=t:i||(r[e]=t)}return"string"==typeof t?F.each(t.split(/\s*,\s*/),function(e){i(e,!0)}):"object"==typeof t?F.each(t,function(e,t){i(t,e)}):!0===t&&(0<e.chunk_size&&(r.slice_blob=!0),!e.resize.enabled&&e.multipart||(r.send_binary_string=!0),F.each(e,function(e,t){i(t,!!e,!0)})),e.runtimes="html5,html4",r}var t,F={VERSION:"2.1.9",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:I.mimes,ua:I.ua,typeOf:I.typeOf,extend:I.extend,guid:I.guid,getAll:function(e){for(var t,i=[],n=(e="array"!==F.typeOf(e)?[e]:e).length;n--;)(t=F.get(e[n]))&&i.push(t);return i.length?i:null},get:I.get,each:I.each,getPos:I.getPos,getSize:I.getSize,xmlEncode:function(e){var t={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"};return e&&(""+e).replace(/[<>&\"\']/g,function(e){return t[e]?"&"+t[e]+";":e})},toArray:I.toArray,inArray:I.inArray,addI18n:I.addI18n,translate:I.translate,isEmptyObj:I.isEmptyObj,hasClass:I.hasClass,addClass:I.addClass,removeClass:I.removeClass,getStyle:I.getStyle,addEvent:I.addEvent,removeEvent:I.removeEvent,removeAllEvents:I.removeAllEvents,cleanName:function(e){for(var t=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"],i=0;i<t.length;i+=2)e=e.replace(t[i],t[i+1]);return e=(e=e.replace(/\s+/g,"_")).replace(/[^a-z0-9_\-\.]+/gi,"")},buildUrl:function(e,t){var i="";return F.each(t,function(e,t){i+=(i?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(e)}),i&&(e+=(0<e.indexOf("?")?"&":"?")+i),e},formatSize:function(e){var t;return e===S||/\D/.test(e)?F.translate("N/A"):(t=Math.pow(1024,4))<e?i(e/t,1)+" "+F.translate("tb"):e>(t/=1024)?i(e/t,1)+" "+F.translate("gb"):e>(t/=1024)?i(e/t,1)+" "+F.translate("mb"):1024<e?Math.round(e/1024)+" "+F.translate("kb"):e+" "+F.translate("b");function i(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}},parseSize:I.parseSizeStr,predictRuntime:function(e,t){var i=new F.Uploader(e),t=I.Runtime.thatCan(i.getOption().required_features,t||e.runtimes);return i.destroy(),t},addFileFilter:function(e,t){D[e]=t}};F.addFileFilter("mime_types",function(e,t,i){e.length&&!e.regexp.test(t.name)?(this.trigger("Error",{code:F.FILE_EXTENSION_ERROR,message:F.translate("File extension error."),file:t}),i(!1)):i(!0)}),F.addFileFilter("max_file_size",function(e,t,i){e=F.parseSize(e),void 0!==t.size&&e&&t.size>e?(this.trigger("Error",{code:F.FILE_SIZE_ERROR,message:F.translate("File size error."),file:t}),i(!1)):i(!0)}),F.addFileFilter("prevent_duplicates",function(e,t,i){if(e)for(var n=this.files.length;n--;)if(t.name===this.files[n].name&&t.size===this.files[n].size)return this.trigger("Error",{code:F.FILE_DUPLICATE_ERROR,message:F.translate("Duplicate file error."),file:t}),void i(!1);i(!0)}),F.Uploader=function(e){var u,i,n,p,t=F.guid(),l=[],h={},o=[],d=[],c=!1;function r(){var e,t,i=0;if(this.state==F.STARTED){for(t=0;t<l.length;t++)e||l[t].status!=F.QUEUED?i++:(e=l[t],this.trigger("BeforeUpload",e)&&(e.status=F.UPLOADING,this.trigger("UploadFile",e)));i==l.length&&(this.state!==F.STOPPED&&(this.state=F.STOPPED,this.trigger("StateChanged")),this.trigger("UploadComplete",l))}}function s(e){e.percent=0<e.size?Math.ceil(e.loaded/e.size*100):100,a()}function a(){var e,t;for(n.reset(),e=0;e<l.length;e++)(t=l[e]).size!==S?(n.size+=t.origSize,n.loaded+=t.loaded*t.origSize/t.size):n.size=S,t.status==F.DONE?n.uploaded++:t.status==F.FAILED?n.failed++:n.queued++;n.size===S?n.percent=0<l.length?Math.ceil(n.uploaded/l.length*100):0:(n.bytesPerSec=Math.ceil(n.loaded/((+new Date-i||1)/1e3)),n.percent=0<n.size?Math.ceil(n.loaded/n.size*100):0)}function f(){var e=o[0]||d[0];return!!e&&e.getRuntime().uid}function g(n,e){var r=this,s=0,t=[],a={runtime_order:n.runtimes,required_caps:n.required_features,preferred_caps:h};F.each(n.runtimes.split(/\s*,\s*/),function(e){n[e]&&(a[e]=n[e])}),n.browse_button&&F.each(n.browse_button,function(i){t.push(function(t){var e=new I.FileInput(F.extend({},a,{accept:n.filters.mime_types,name:n.file_data_name,multiple:n.multi_selection,container:n.container,browse_button:i}));e.onready=function(){var e=I.Runtime.getInfo(this.ruid);I.extend(r.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),multi_selection:e.can("select_multiple")}),s++,o.push(this),t()},e.onchange=function(){r.addFile(this.files)},e.bind("mouseenter mouseleave mousedown mouseup",function(e){c||(n.browse_button_hover&&("mouseenter"===e.type?I.addClass(i,n.browse_button_hover):"mouseleave"===e.type&&I.removeClass(i,n.browse_button_hover)),n.browse_button_active&&("mousedown"===e.type?I.addClass(i,n.browse_button_active):"mouseup"===e.type&&I.removeClass(i,n.browse_button_active)))}),e.bind("mousedown",function(){r.trigger("Browse")}),e.bind("error runtimeerror",function(){e=null,t()}),e.init()})}),n.drop_element&&F.each(n.drop_element,function(i){t.push(function(t){var e=new I.FileDrop(F.extend({},a,{drop_zone:i}));e.onready=function(){var e=I.Runtime.getInfo(this.ruid);I.extend(r.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),dragdrop:e.can("drag_and_drop")}),s++,d.push(this),t()},e.ondrop=function(){r.addFile(this.files)},e.bind("error runtimeerror",function(){e=null,t()}),e.init()})}),I.inSeries(t,function(){"function"==typeof e&&e(s)})}function _(e,t,i){var a=this,o=!1;function n(e,t,i){var n,r,s=u[e];switch(e){case"max_file_size":"max_file_size"===e&&(u.max_file_size=u.filters.max_file_size=t);break;case"chunk_size":(t=F.parseSize(t))&&(u[e]=t,u.send_file_name=!0);break;case"multipart":(u[e]=t)||(u.send_file_name=!0);break;case"unique_names":(u[e]=t)&&(u.send_file_name=!0);break;case"filters":"array"===F.typeOf(t)&&(t={mime_types:t}),i?F.extend(u.filters,t):u.filters=t,t.mime_types&&(u.filters.mime_types.regexp=(n=u.filters.mime_types,r=[],F.each(n,function(e){F.each(e.extensions.split(/,/),function(e){/^\s*\*\s*$/.test(e)?r.push("\\.*"):r.push("\\."+e.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\\$&")+"]","g"),"\\$&"))})}),new RegExp("("+r.join("|")+")$","i")));break;case"resize":i?F.extend(u.resize,t,{enabled:!0}):u.resize=t;break;case"prevent_duplicates":u.prevent_duplicates=u.filters.prevent_duplicates=!!t;break;case"container":case"browse_button":case"drop_element":t="container"===e?F.get(t):F.getAll(t);case"runtimes":case"multi_selection":u[e]=t,i||(o=!0);break;default:u[e]=t}i||a.trigger("OptionChanged",e,t,s)}"object"==typeof e?F.each(e,function(e,t){n(t,e,i)}):n(e,t,i),i?(u.required_features=w(F.extend({},u)),h=w(F.extend({},u,{required_features:!0}))):o&&(a.trigger("Destroy"),g.call(a,u,function(e){e?(a.runtime=I.Runtime.getInfo(f()).type,a.trigger("Init",{runtime:a.runtime}),a.trigger("PostInit")):a.trigger("Error",{code:F.INIT_ERROR,message:F.translate("Init error.")})}))}function m(e,t){var i;e.settings.unique_names&&(e="part",(i=t.name.match(/\.([^.]+)$/))&&(e=i[1]),t.target_name=t.id+"."+e)}function b(r,s){var a,o=r.settings.url,u=r.settings.chunk_size,l=r.settings.max_retries,d=r.features,c=0;function f(){0<l--?T(g,1e3):(s.loaded=c,r.trigger("Error",{code:F.HTTP_ERROR,message:F.translate("HTTP Error."),file:s,response:p.responseText,status:p.status,responseHeaders:p.getAllResponseHeaders()}))}function g(){var e,i,t,n={};s.status===F.UPLOADING&&r.state!==F.STOPPED&&(r.settings.send_file_name&&(n.name=s.target_name||s.name),e=u&&d.chunks&&a.size>u?(t=Math.min(u,a.size-c),a.slice(c,c+t)):(t=a.size,a),u&&d.chunks&&(r.settings.send_chunk_number?(n.chunk=Math.ceil(c/u),n.chunks=Math.ceil(a.size/u)):(n.offset=c,n.total=a.size)),(p=new I.XMLHttpRequest).upload&&(p.upload.onprogress=function(e){s.loaded=Math.min(s.size,c+e.loaded),r.trigger("UploadProgress",s)}),p.onload=function(){400<=p.status?f():(l=r.settings.max_retries,t<a.size?(e.destroy(),c+=t,s.loaded=Math.min(c,a.size),r.trigger("ChunkUploaded",s,{offset:s.loaded,total:a.size,response:p.responseText,status:p.status,responseHeaders:p.getAllResponseHeaders()}),"Android Browser"===I.Env.browser&&r.trigger("UploadProgress",s)):s.loaded=s.size,e=i=null,!c||c>=a.size?(s.size!=s.origSize&&(a.destroy(),a=null),r.trigger("UploadProgress",s),s.status=F.DONE,r.trigger("FileUploaded",s,{response:p.responseText,status:p.status,responseHeaders:p.getAllResponseHeaders()})):T(g,1))},p.onerror=function(){f()},p.onloadend=function(){this.destroy(),p=null},r.settings.multipart&&d.multipart?(p.open("post",o,!0),F.each(r.settings.headers,function(e,t){p.setRequestHeader(t,e)}),i=new I.FormData,F.each(F.extend(n,r.settings.multipart_params),function(e,t){i.append(t,e)}),i.append(r.settings.file_data_name,e),p.send(i,{runtime_order:r.settings.runtimes,required_caps:r.settings.required_features,preferred_caps:h})):(o=F.buildUrl(r.settings.url,F.extend(n,r.settings.multipart_params)),p.open("post",o,!0),p.setRequestHeader("Content-Type","application/octet-stream"),F.each(r.settings.headers,function(e,t){p.setRequestHeader(t,e)}),p.send(e,{runtime_order:r.settings.runtimes,required_caps:r.settings.required_features,preferred_caps:h})))}s.loaded&&(c=s.loaded=u?u*Math.floor(s.loaded/u):0),a=s.getSource(),r.settings.resize.enabled&&function(e,t){if(e.ruid){e=I.Runtime.getInfo(e.ruid);if(e)return e.can(t)}}(a,"send_binary_string")&&~I.inArray(a.type,["image/jpeg","image/png"])?function(t,e,i){var n=new I.Image;try{n.onload=function(){if(e.width>this.width&&e.height>this.height&&e.quality===S&&e.preserve_headers&&!e.crop)return this.destroy(),i(t);n.downsize(e.width,e.height,e.crop,e.preserve_headers)},n.onresize=function(){i(this.getAsBlob(t.type,e.quality)),this.destroy()},n.onerror=function(){i(t)},n.load(t)}catch(e){i(t)}}.call(this,a,r.settings.resize,function(e){a=e,s.size=e.size,g()}):g()}function R(e,t){s(t)}function E(e){if(e.state==F.STARTED)i=+new Date;else if(e.state==F.STOPPED)for(var t=e.files.length-1;0<=t;t--)e.files[t].status==F.UPLOADING&&(e.files[t].status=F.QUEUED,a())}function y(){p&&p.abort()}function v(e){a(),T(function(){r.call(e)},1)}function z(e,t){t.code===F.INIT_ERROR?e.destroy():t.code===F.HTTP_ERROR&&(t.file.status=F.FAILED,s(t.file),e.state==F.STARTED)&&(e.trigger("CancelUpload"),T(function(){r.call(e)},1))}function O(e){e.stop(),F.each(l,function(e){e.destroy()}),l=[],o.length&&(F.each(o,function(e){e.destroy()}),o=[]),d.length&&(F.each(d,function(e){e.destroy()}),d=[]),c=!(h={}),i=p=null,n.reset()}u={runtimes:I.Runtime.order,max_retries:0,chunk_size:0,multipart:!0,multi_selection:!0,file_data_name:"file",filters:{mime_types:[],prevent_duplicates:!1,max_file_size:0},resize:{enabled:!1,preserve_headers:!0,crop:!1},send_file_name:!0,send_chunk_number:!0},_.call(this,e,null,!0),n=new F.QueueProgress,F.extend(this,{id:t,uid:t,state:F.STOPPED,features:{},runtime:null,files:l,settings:u,total:n,init:function(){var t,i=this,e=i.getOption("preinit");return"function"==typeof e?e(i):F.each(e,function(e,t){i.bind(t,e)}),function(){this.bind("FilesAdded FilesRemoved",function(e){e.trigger("QueueChanged"),e.refresh()}),this.bind("CancelUpload",y),this.bind("BeforeUpload",m),this.bind("UploadFile",b),this.bind("UploadProgress",R),this.bind("StateChanged",E),this.bind("QueueChanged",a),this.bind("Error",z),this.bind("FileUploaded",v),this.bind("Destroy",O)}.call(i),F.each(["container","browse_button","drop_element"],function(e){if(null===i.getOption(e))return!(t={code:F.INIT_ERROR,message:F.translate("'%' specified, but cannot be found.")})}),t?i.trigger("Error",t):u.browse_button||u.drop_element?void g.call(i,u,function(e){var t=i.getOption("init");"function"==typeof t?t(i):F.each(t,function(e,t){i.bind(t,e)}),e?(i.runtime=I.Runtime.getInfo(f()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("PostInit")):i.trigger("Error",{code:F.INIT_ERROR,message:F.translate("Init error.")})}):i.trigger("Error",{code:F.INIT_ERROR,message:F.translate("You must specify either 'browse_button' or 'drop_element'.")})},setOption:function(e,t){_.call(this,e,t,!this.runtime)},getOption:function(e){return e?u[e]:u},refresh:function(){o.length&&F.each(o,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=F.STARTED&&(this.state=F.STARTED,this.trigger("StateChanged"),r.call(this))},stop:function(){this.state!=F.STOPPED&&(this.state=F.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){c=arguments[0]===S||arguments[0],o.length&&F.each(o,function(e){e.disable(c)}),this.trigger("DisableBrowse",c)},getFile:function(e){for(var t=l.length-1;0<=t;t--)if(l[t].id===e)return l[t]},addFile:function(e,n){var r,s=this,a=[],o=[];r=f(),function e(i){var t=I.typeOf(i);if(i instanceof I.File){if(!i.ruid&&!i.isDetached()){if(!r)return!1;i.ruid=r,i.connectRuntime(r)}e(new F.File(i))}else i instanceof I.Blob?(e(i.getSource()),i.destroy()):i instanceof F.File?(n&&(i.name=n),a.push(function(t){var n,e,r;n=i,e=function(e){e||(l.push(i),o.push(i),s.trigger("FileFiltered",i)),T(t,1)},r=[],I.each(s.settings.filters,function(e,i){D[i]&&r.push(function(t){D[i].call(s,e,n,function(e){t(!e)})})}),I.inSeries(r,e)})):-1!==I.inArray(t,["file","blob"])?e(new I.File(null,i)):"node"===t&&"filelist"===I.typeOf(i.files)?I.each(i.files,e):"array"===t&&(n=null,I.each(i,e))}(e),a.length&&I.inSeries(a,function(){o.length&&s.trigger("FilesAdded",o)})},removeFile:function(e){for(var t="string"==typeof e?e:e.id,i=l.length-1;0<=i;i--)if(l[i].id===t)return this.splice(i,1)[0]},splice:function(e,t){var e=l.splice(e===S?0:e,t===S?l.length:t),i=!1;return this.state==F.STARTED&&(F.each(e,function(e){if(e.status===F.UPLOADING)return!(i=!0)}),i)&&this.stop(),this.trigger("FilesRemoved",e),F.each(e,function(e){e.destroy()}),i&&this.start(),e},dispatchEvent:function(e){var t,i;if(e=e.toLowerCase(),t=this.hasEventListener(e)){t.sort(function(e,t){return t.priority-e.priority}),(i=[].slice.call(arguments)).shift(),i.unshift(this);for(var n=0;n<t.length;n++)if(!1===t[n].fn.apply(t[n].scope,i))return!1}return!0},bind:function(e,t,i,n){F.Uploader.prototype.bind.call(this,e,t,n,i)},destroy:function(){this.trigger("Destroy"),u=n=null,this.unbindAll()}})},F.Uploader.prototype=I.EventTarget.instance,F.File=(t={},function(e){F.extend(this,{id:F.guid(),name:e.name||e.fileName,type:e.type||"",size:e.size||e.fileSize,origSize:e.size||e.fileSize,loaded:0,percent:0,status:F.QUEUED,lastModifiedDate:e.lastModifiedDate||(new Date).toLocaleString(),getNative:function(){var e=this.getSource().getSource();return-1!==I.inArray(I.typeOf(e),["blob","file"])?e:null},getSource:function(){return t[this.id]||null},destroy:function(){var e=this.getSource();e&&(e.destroy(),delete t[this.id])}}),t[this.id]=e}),F.QueueProgress=function(){var e=this;e.size=0,e.loaded=0,e.uploaded=0,e.failed=0,e.queued=0,e.percent=0,e.bytesPerSec=0,e.reset=function(){e.size=e.loaded=e.uploaded=e.failed=e.queued=e.percent=e.bytesPerSec=0}},e.plupload=F}(window,mOxie);
// source --> https://homelive.pt/wp-includes/js/jquery/ui/core.min.js?ver=1.13.3 
/*! jQuery UI - v1.13.3 - 2024-04-26
* https://jqueryui.com
* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-patch.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js
* Copyright jQuery Foundation and other contributors; Licensed MIT */
!function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)}(function(x){"use strict";var t,e,i,n,W,C,o,s,r,l,a,h,u;function E(t,e,i){return[parseFloat(t[0])*(a.test(t[0])?e/100:1),parseFloat(t[1])*(a.test(t[1])?i/100:1)]}function L(t,e){return parseInt(x.css(t,e),10)||0}function N(t){return null!=t&&t===t.window}x.ui=x.ui||{},x.ui.version="1.13.3",
/*!
 * jQuery UI :data 1.13.3
 * https://jqueryui.com
 *
 * Copyright OpenJS Foundation and other contributors
 * Released under the MIT license.
 * https://jquery.org/license
 */
x.extend(x.expr.pseudos,{data:x.expr.createPseudo?x.expr.createPseudo(function(e){return function(t){return!!x.data(t,e)}}):function(t,e,i){return!!x.data(t,i[3])}}),
/*!
 * jQuery UI Disable Selection 1.13.3
 * https://jqueryui.com
 *
 * Copyright OpenJS Foundation and other contributors
 * Released under the MIT license.
 * https://jquery.org/license
 */
x.fn.extend({disableSelection:(t="onselectstart"in document.createElement("div")?"selectstart":"mousedown",function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}),enableSelection:function(){return this.off(".ui-disableSelection")}}),
/*!
 * jQuery UI Focusable 1.13.3
 * https://jqueryui.com
 *
 * Copyright OpenJS Foundation and other contributors
 * Released under the MIT license.
 * https://jquery.org/license
 */
x.ui.focusable=function(t,e){var i,n,o,s=t.nodeName.toLowerCase();return"area"===s?(o=(i=t.parentNode).name,!(!t.href||!o||"map"!==i.nodeName.toLowerCase())&&0<(i=x("img[usemap='#"+o+"']")).length&&i.is(":visible")):(/^(input|select|textarea|button|object)$/.test(s)?(n=!t.disabled)&&(o=x(t).closest("fieldset")[0])&&(n=!o.disabled):n="a"===s&&t.href||e,n&&x(t).is(":visible")&&function(t){var e=t.css("visibility");for(;"inherit"===e;)t=t.parent(),e=t.css("visibility");return"visible"===e}(x(t)))},x.extend(x.expr.pseudos,{focusable:function(t){return x.ui.focusable(t,null!=x.attr(t,"tabindex"))}}),x.fn._form=function(){return"string"==typeof this[0].form?this.closest("form"):x(this[0].form)},
/*!
 * jQuery UI Form Reset Mixin 1.13.3
 * https://jqueryui.com
 *
 * Copyright OpenJS Foundation and other contributors
 * Released under the MIT license.
 * https://jquery.org/license
 */
x.ui.formResetMixin={_formResetHandler:function(){var e=x(this);setTimeout(function(){var t=e.data("ui-form-reset-instances");x.each(t,function(){this.refresh()})})},_bindFormResetHandler:function(){var t;this.form=this.element._form(),this.form.length&&((t=this.form.data("ui-form-reset-instances")||[]).length||this.form.on("reset.ui-form-reset",this._formResetHandler),t.push(this),this.form.data("ui-form-reset-instances",t))},_unbindFormResetHandler:function(){var t;this.form.length&&((t=this.form.data("ui-form-reset-instances")).splice(x.inArray(this,t),1),t.length?this.form.data("ui-form-reset-instances",t):this.form.removeData("ui-form-reset-instances").off("reset.ui-form-reset"))}},x.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),
/*!
 * jQuery UI Support for jQuery core 1.8.x and newer 1.13.3
 * https://jqueryui.com
 *
 * Copyright OpenJS Foundation and other contributors
 * Released under the MIT license.
 * https://jquery.org/license
 *
 */
x.expr.pseudos||(x.expr.pseudos=x.expr[":"]),x.uniqueSort||(x.uniqueSort=x.unique),x.escapeSelector||(e=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,i=function(t,e){return e?"\0"===t?"�":t.slice(0,-1)+"\\"+t.charCodeAt(t.length-1).toString(16)+" ":"\\"+t},x.escapeSelector=function(t){return(t+"").replace(e,i)}),x.fn.even&&x.fn.odd||x.fn.extend({even:function(){return this.filter(function(t){return t%2==0})},odd:function(){return this.filter(function(t){return t%2==1})}}),
/*!
 * jQuery UI Keycode 1.13.3
 * https://jqueryui.com
 *
 * Copyright OpenJS Foundation and other contributors
 * Released under the MIT license.
 * https://jquery.org/license
 */
x.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},
/*!
 * jQuery UI Labels 1.13.3
 * https://jqueryui.com
 *
 * Copyright OpenJS Foundation and other contributors
 * Released under the MIT license.
 * https://jquery.org/license
 */
x.fn.labels=function(){var t,e,i;return this.length?this[0].labels&&this[0].labels.length?this.pushStack(this[0].labels):(e=this.eq(0).parents("label"),(t=this.attr("id"))&&(i=(i=this.eq(0).parents().last()).add((i.length?i:this).siblings()),t="label[for='"+x.escapeSelector(t)+"']",e=e.add(i.find(t).addBack(t))),this.pushStack(e)):this.pushStack([])},x.ui.plugin={add:function(t,e,i){var n,o=x.ui[t].prototype;for(n in i)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([e,i[n]])},call:function(t,e,i,n){var o,s=t.plugins[e];if(s&&(n||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(o=0;o<s.length;o++)t.options[s[o][0]]&&s[o][1].apply(t.element,i)}},
/*!
 * jQuery UI Position 1.13.3
 * https://jqueryui.com
 *
 * Copyright OpenJS Foundation and other contributors
 * Released under the MIT license.
 * https://jquery.org/license
 *
 * https://api.jqueryui.com/position/
 */
W=Math.max,C=Math.abs,o=/left|center|right/,s=/top|center|bottom/,r=/[\+\-]\d+(\.[\d]+)?%?/,l=/^\w+/,a=/%$/,h=x.fn.position,x.position={scrollbarWidth:function(){var t,e,i;return void 0!==n?n:(i=(e=x("<div style='display:block;position:absolute;width:200px;height:200px;overflow:hidden;'><div style='height:300px;width:auto;'></div></div>")).children()[0],x("body").append(e),t=i.offsetWidth,e.css("overflow","scroll"),t===(i=i.offsetWidth)&&(i=e[0].clientWidth),e.remove(),n=t-i)},getScrollInfo:function(t){var e=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),i=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),e="scroll"===e||"auto"===e&&t.width<t.element[0].scrollWidth;return{width:"scroll"===i||"auto"===i&&t.height<t.element[0].scrollHeight?x.position.scrollbarWidth():0,height:e?x.position.scrollbarWidth():0}},getWithinInfo:function(t){var e=x(t||window),i=N(e[0]),n=!!e[0]&&9===e[0].nodeType;return{element:e,isWindow:i,isDocument:n,offset:!i&&!n?x(t).offset():{left:0,top:0},scrollLeft:e.scrollLeft(),scrollTop:e.scrollTop(),width:e.outerWidth(),height:e.outerHeight()}}},x.fn.position=function(f){var c,d,p,g,m,v,y,w,b,_,t,e;return f&&f.of?(v="string"==typeof(f=x.extend({},f)).of?x(document).find(f.of):x(f.of),y=x.position.getWithinInfo(f.within),w=x.position.getScrollInfo(y),b=(f.collision||"flip").split(" "),_={},e=9===(e=(t=v)[0]).nodeType?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:N(e)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:e.preventDefault?{width:0,height:0,offset:{top:e.pageY,left:e.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()},v[0].preventDefault&&(f.at="left top"),d=e.width,p=e.height,m=x.extend({},g=e.offset),x.each(["my","at"],function(){var t,e,i=(f[this]||"").split(" ");(i=1===i.length?o.test(i[0])?i.concat(["center"]):s.test(i[0])?["center"].concat(i):["center","center"]:i)[0]=o.test(i[0])?i[0]:"center",i[1]=s.test(i[1])?i[1]:"center",t=r.exec(i[0]),e=r.exec(i[1]),_[this]=[t?t[0]:0,e?e[0]:0],f[this]=[l.exec(i[0])[0],l.exec(i[1])[0]]}),1===b.length&&(b[1]=b[0]),"right"===f.at[0]?m.left+=d:"center"===f.at[0]&&(m.left+=d/2),"bottom"===f.at[1]?m.top+=p:"center"===f.at[1]&&(m.top+=p/2),c=E(_.at,d,p),m.left+=c[0],m.top+=c[1],this.each(function(){var i,t,r=x(this),l=r.outerWidth(),a=r.outerHeight(),e=L(this,"marginLeft"),n=L(this,"marginTop"),o=l+e+L(this,"marginRight")+w.width,s=a+n+L(this,"marginBottom")+w.height,h=x.extend({},m),u=E(_.my,r.outerWidth(),r.outerHeight());"right"===f.my[0]?h.left-=l:"center"===f.my[0]&&(h.left-=l/2),"bottom"===f.my[1]?h.top-=a:"center"===f.my[1]&&(h.top-=a/2),h.left+=u[0],h.top+=u[1],i={marginLeft:e,marginTop:n},x.each(["left","top"],function(t,e){x.ui.position[b[t]]&&x.ui.position[b[t]][e](h,{targetWidth:d,targetHeight:p,elemWidth:l,elemHeight:a,collisionPosition:i,collisionWidth:o,collisionHeight:s,offset:[c[0]+u[0],c[1]+u[1]],my:f.my,at:f.at,within:y,elem:r})}),f.using&&(t=function(t){var e=g.left-h.left,i=e+d-l,n=g.top-h.top,o=n+p-a,s={target:{element:v,left:g.left,top:g.top,width:d,height:p},element:{element:r,left:h.left,top:h.top,width:l,height:a},horizontal:i<0?"left":0<e?"right":"center",vertical:o<0?"top":0<n?"bottom":"middle"};d<l&&C(e+i)<d&&(s.horizontal="center"),p<a&&C(n+o)<p&&(s.vertical="middle"),W(C(e),C(i))>W(C(n),C(o))?s.important="horizontal":s.important="vertical",f.using.call(this,t,s)}),r.offset(x.extend(h,{using:t}))})):h.apply(this,arguments)},x.ui.position={fit:{left:function(t,e){var i,n=e.within,o=n.isWindow?n.scrollLeft:n.offset.left,n=n.width,s=t.left-e.collisionPosition.marginLeft,r=o-s,l=s+e.collisionWidth-n-o;n<e.collisionWidth?0<r&&l<=0?(i=t.left+r+e.collisionWidth-n-o,t.left+=r-i):t.left=!(0<l&&r<=0)&&l<r?o+n-e.collisionWidth:o:0<r?t.left+=r:0<l?t.left-=l:t.left=W(t.left-s,t.left)},top:function(t,e){var i,n=e.within,n=n.isWindow?n.scrollTop:n.offset.top,o=e.within.height,s=t.top-e.collisionPosition.marginTop,r=n-s,l=s+e.collisionHeight-o-n;o<e.collisionHeight?0<r&&l<=0?(i=t.top+r+e.collisionHeight-o-n,t.top+=r-i):t.top=!(0<l&&r<=0)&&l<r?n+o-e.collisionHeight:n:0<r?t.top+=r:0<l?t.top-=l:t.top=W(t.top-s,t.top)}},flip:{left:function(t,e){var i=e.within,n=i.offset.left+i.scrollLeft,o=i.width,i=i.isWindow?i.scrollLeft:i.offset.left,s=t.left-e.collisionPosition.marginLeft,r=s-i,s=s+e.collisionWidth-o-i,l="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,a="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,h=-2*e.offset[0];r<0?((o=t.left+l+a+h+e.collisionWidth-o-n)<0||o<C(r))&&(t.left+=l+a+h):0<s&&(0<(n=t.left-e.collisionPosition.marginLeft+l+a+h-i)||C(n)<s)&&(t.left+=l+a+h)},top:function(t,e){var i=e.within,n=i.offset.top+i.scrollTop,o=i.height,i=i.isWindow?i.scrollTop:i.offset.top,s=t.top-e.collisionPosition.marginTop,r=s-i,s=s+e.collisionHeight-o-i,l="top"===e.my[1]?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,a="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,h=-2*e.offset[1];r<0?((o=t.top+l+a+h+e.collisionHeight-o-n)<0||o<C(r))&&(t.top+=l+a+h):0<s&&(0<(n=t.top-e.collisionPosition.marginTop+l+a+h-i)||C(n)<s)&&(t.top+=l+a+h)}},flipfit:{left:function(){x.ui.position.flip.left.apply(this,arguments),x.ui.position.fit.left.apply(this,arguments)},top:function(){x.ui.position.flip.top.apply(this,arguments),x.ui.position.fit.top.apply(this,arguments)}}},x.ui.safeActiveElement=function(e){var i;try{i=e.activeElement}catch(t){i=e.body}return i=(i=i||e.body).nodeName?i:e.body},x.ui.safeBlur=function(t){t&&"body"!==t.nodeName.toLowerCase()&&x(t).trigger("blur")},
/*!
 * jQuery UI Scroll Parent 1.13.3
 * https://jqueryui.com
 *
 * Copyright OpenJS Foundation and other contributors
 * Released under the MIT license.
 * https://jquery.org/license
 */
x.fn.scrollParent=function(t){var e=this.css("position"),i="absolute"===e,n=t?/(auto|scroll|hidden)/:/(auto|scroll)/,t=this.parents().filter(function(){var t=x(this);return(!i||"static"!==t.css("position"))&&n.test(t.css("overflow")+t.css("overflow-y")+t.css("overflow-x"))}).eq(0);return"fixed"!==e&&t.length?t:x(this[0].ownerDocument||document)},
/*!
 * jQuery UI Tabbable 1.13.3
 * https://jqueryui.com
 *
 * Copyright OpenJS Foundation and other contributors
 * Released under the MIT license.
 * https://jquery.org/license
 */
x.extend(x.expr.pseudos,{tabbable:function(t){var e=x.attr(t,"tabindex"),i=null!=e;return(!i||0<=e)&&x.ui.focusable(t,i)}}),
/*!
 * jQuery UI Unique ID 1.13.3
 * https://jqueryui.com
 *
 * Copyright OpenJS Foundation and other contributors
 * Released under the MIT license.
 * https://jquery.org/license
 */
x.fn.extend({uniqueId:(u=0,function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++u)})}),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&x(this).removeAttr("id")})}});
/*!
 * jQuery UI Widget 1.13.3
 * https://jqueryui.com
 *
 * Copyright OpenJS Foundation and other contributors
 * Released under the MIT license.
 * https://jquery.org/license
 */
var f,c=0,d=Array.prototype.hasOwnProperty,p=Array.prototype.slice;x.cleanData=(f=x.cleanData,function(t){for(var e,i,n=0;null!=(i=t[n]);n++)(e=x._data(i,"events"))&&e.remove&&x(i).triggerHandler("remove");f(t)}),x.widget=function(t,i,e){var n,o,s,r={},l=t.split(".")[0],a=l+"-"+(t=t.split(".")[1]);return e||(e=i,i=x.Widget),Array.isArray(e)&&(e=x.extend.apply(null,[{}].concat(e))),x.expr.pseudos[a.toLowerCase()]=function(t){return!!x.data(t,a)},x[l]=x[l]||{},n=x[l][t],o=x[l][t]=function(t,e){if(!this||!this._createWidget)return new o(t,e);arguments.length&&this._createWidget(t,e)},x.extend(o,n,{version:e.version,_proto:x.extend({},e),_childConstructors:[]}),(s=new i).options=x.widget.extend({},s.options),x.each(e,function(e,n){function o(){return i.prototype[e].apply(this,arguments)}function s(t){return i.prototype[e].apply(this,t)}r[e]="function"!=typeof n?n:function(){var t,e=this._super,i=this._superApply;return this._super=o,this._superApply=s,t=n.apply(this,arguments),this._super=e,this._superApply=i,t}}),o.prototype=x.widget.extend(s,{widgetEventPrefix:n&&s.widgetEventPrefix||t},r,{constructor:o,namespace:l,widgetName:t,widgetFullName:a}),n?(x.each(n._childConstructors,function(t,e){var i=e.prototype;x.widget(i.namespace+"."+i.widgetName,o,e._proto)}),delete n._childConstructors):i._childConstructors.push(o),x.widget.bridge(t,o),o},x.widget.extend=function(t){for(var e,i,n=p.call(arguments,1),o=0,s=n.length;o<s;o++)for(e in n[o])i=n[o][e],d.call(n[o],e)&&void 0!==i&&(x.isPlainObject(i)?t[e]=x.isPlainObject(t[e])?x.widget.extend({},t[e],i):x.widget.extend({},i):t[e]=i);return t},x.widget.bridge=function(s,e){var r=e.prototype.widgetFullName||s;x.fn[s]=function(i){var t="string"==typeof i,n=p.call(arguments,1),o=this;return t?this.length||"instance"!==i?this.each(function(){var t,e=x.data(this,r);return"instance"===i?(o=e,!1):e?"function"!=typeof e[i]||"_"===i.charAt(0)?x.error("no such method '"+i+"' for "+s+" widget instance"):(t=e[i].apply(e,n))!==e&&void 0!==t?(o=t&&t.jquery?o.pushStack(t.get()):t,!1):void 0:x.error("cannot call methods on "+s+" prior to initialization; attempted to call method '"+i+"'")}):o=void 0:(n.length&&(i=x.widget.extend.apply(null,[i].concat(n))),this.each(function(){var t=x.data(this,r);t?(t.option(i||{}),t._init&&t._init()):x.data(this,r,new e(i,this))})),o}},x.Widget=function(){},x.Widget._childConstructors=[],x.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{classes:{},disabled:!1,create:null},_createWidget:function(t,e){e=x(e||this.defaultElement||this)[0],this.element=x(e),this.uuid=c++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=x(),this.hoverable=x(),this.focusable=x(),this.classesElementLookup={},e!==this&&(x.data(e,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===e&&this.destroy()}}),this.document=x(e.style?e.ownerDocument:e.document||e),this.window=x(this.document[0].defaultView||this.document[0].parentWindow)),this.options=x.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:x.noop,_create:x.noop,_init:x.noop,destroy:function(){var i=this;this._destroy(),x.each(this.classesElementLookup,function(t,e){i._removeClass(e,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:x.noop,widget:function(){return this.element},option:function(t,e){var i,n,o,s=t;if(0===arguments.length)return x.widget.extend({},this.options);if("string"==typeof t)if(s={},t=(i=t.split(".")).shift(),i.length){for(n=s[t]=x.widget.extend({},this.options[t]),o=0;o<i.length-1;o++)n[i[o]]=n[i[o]]||{},n=n[i[o]];if(t=i.pop(),1===arguments.length)return void 0===n[t]?null:n[t];n[t]=e}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];s[t]=e}return this._setOptions(s),this},_setOptions:function(t){for(var e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(t){var e,i,n;for(e in t)n=this.classesElementLookup[e],t[e]!==this.options.classes[e]&&n&&n.length&&(i=x(n.get()),this._removeClass(n,e),i.addClass(this._classes({element:i,keys:e,classes:t,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(o){var s=[],r=this;function t(t,e){for(var i,n=0;n<t.length;n++)i=r.classesElementLookup[t[n]]||x(),i=o.add?(function(){var i=[];o.element.each(function(t,e){x.map(r.classesElementLookup,function(t){return t}).some(function(t){return t.is(e)})||i.push(e)}),r._on(x(i),{remove:"_untrackClassesElement"})}(),x(x.uniqueSort(i.get().concat(o.element.get())))):x(i.not(o.element).get()),r.classesElementLookup[t[n]]=i,s.push(t[n]),e&&o.classes[t[n]]&&s.push(o.classes[t[n]])}return(o=x.extend({element:this.element,classes:this.options.classes||{}},o)).keys&&t(o.keys.match(/\S+/g)||[],!0),o.extra&&t(o.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(i){var n=this;x.each(n.classesElementLookup,function(t,e){-1!==x.inArray(i.target,e)&&(n.classesElementLookup[t]=x(e.not(i.target).get()))}),this._off(x(i.target))},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,n){var o="string"==typeof t||null===t,e={extra:o?e:i,keys:o?t:e,element:o?this.element:t,add:n="boolean"==typeof n?n:i};return e.element.toggleClass(this._classes(e),n),this},_on:function(o,s,t){var r,l=this;"boolean"!=typeof o&&(t=s,s=o,o=!1),t?(s=r=x(s),this.bindings=this.bindings.add(s)):(t=s,s=this.element,r=this.widget()),x.each(t,function(t,e){function i(){if(o||!0!==l.options.disabled&&!x(this).hasClass("ui-state-disabled"))return("string"==typeof e?l[e]:e).apply(l,arguments)}"string"!=typeof e&&(i.guid=e.guid=e.guid||i.guid||x.guid++);var t=t.match(/^([\w:-]*)\s*(.*)$/),n=t[1]+l.eventNamespace,t=t[2];t?r.on(n,t,i):s.on(n,i)})},_off:function(t,e){e=(e||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.off(e),this.bindings=x(this.bindings.not(t).get()),this.focusable=x(this.focusable.not(t).get()),this.hoverable=x(this.hoverable.not(t).get())},_delay:function(t,e){var i=this;return setTimeout(function(){return("string"==typeof t?i[t]:t).apply(i,arguments)},e||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){this._addClass(x(t.currentTarget),null,"ui-state-hover")},mouseleave:function(t){this._removeClass(x(t.currentTarget),null,"ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){this._addClass(x(t.currentTarget),null,"ui-state-focus")},focusout:function(t){this._removeClass(x(t.currentTarget),null,"ui-state-focus")}})},_trigger:function(t,e,i){var n,o,s=this.options[t];if(i=i||{},(e=x.Event(e)).type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),e.target=this.element[0],o=e.originalEvent)for(n in o)n in e||(e[n]=o[n]);return this.element.trigger(e,i),!("function"==typeof s&&!1===s.apply(this.element[0],[e].concat(i))||e.isDefaultPrevented())}},x.each({show:"fadeIn",hide:"fadeOut"},function(s,r){x.Widget.prototype["_"+s]=function(e,t,i){var n,o=(t="string"==typeof t?{effect:t}:t)?!0!==t&&"number"!=typeof t&&t.effect||r:s;"number"==typeof(t=t||{})?t={duration:t}:!0===t&&(t={}),n=!x.isEmptyObject(t),t.complete=i,t.delay&&e.delay(t.delay),n&&x.effects&&x.effects.effect[o]?e[s](t):o!==s&&e[o]?e[o](t.duration,t.easing,i):e.queue(function(t){x(this)[s](),i&&i.call(e[0]),t()})}})});
// source --> https://homelive.pt/wp-includes/js/jquery/ui/mouse.min.js?ver=1.13.3 
/*!
 * jQuery UI Mouse 1.13.3
 * https://jqueryui.com
 *
 * Copyright OpenJS Foundation and other contributors
 * Released under the MIT license.
 * https://jquery.org/license
 */
!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery","../ie","../version","../widget"],e):e(jQuery)}(function(o){"use strict";var n=!1;return o(document).on("mouseup",function(){n=!1}),o.widget("ui.mouse",{version:"1.13.3",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.on("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).on("click."+this.widgetName,function(e){if(!0===o.data(e.target,t.widgetName+".preventClickEvent"))return o.removeData(e.target,t.widgetName+".preventClickEvent"),e.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){var t,i,s;if(!n)return this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),i=1===(this._mouseDownEvent=e).which,s=!("string"!=typeof(t=this).options.cancel||!e.target.nodeName)&&o(e.target).closest(this.options.cancel).length,i&&!s&&this._mouseCapture(e)&&(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){t.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=!1!==this._mouseStart(e),!this._mouseStarted)?e.preventDefault():(!0===o.data(e.target,this.widgetName+".preventClickEvent")&&o.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return t._mouseMove(e)},this._mouseUpDelegate=function(e){return t._mouseUp(e)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),n=!0)),!0},_mouseMove:function(e){if(this._mouseMoved){if(o.ui.ie&&(!document.documentMode||document.documentMode<9)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=!1!==this._mouseStart(this._mouseDownEvent,e),this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&o.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,n=!1,e.preventDefault()},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})});
// source --> https://homelive.pt/wp-content/plugins/super-forms/assets/js/frontend/masked-currency.js?ver=6.3.312 
(function ($) {
    "use strict";
    if (!$.browser) {
        $.browser = {};
        $.browser.mozilla = /mozilla/.test(navigator.userAgent.toLowerCase()) && !/webkit/.test(navigator.userAgent.toLowerCase());
        $.browser.webkit = /webkit/.test(navigator.userAgent.toLowerCase());
        $.browser.opera = /opera/.test(navigator.userAgent.toLowerCase());
        $.browser.msie = /msie/.test(navigator.userAgent.toLowerCase());
        $.browser.device = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase());
    }

    var defaultOptions = {
            prefix: "",
            suffix: "",
            affixesStay: true,
            thousands: ",",
            decimal: ".",
            precision: 2,
            allowZero: false,
            allowNegative: false,
            doubleClickSelection: true,
            allowEmpty: false,
            bringCaretAtEndOnFocus: true
        },
        methods = {
            destroy: function () {
                $(this).unbind(".maskMoney");

                if ($.browser.msie) {
                    this.onpaste = null;
                }
                return this;
            },

            applyMask: function (value) {
                var $input = $(this);
                // data-* api
                var settings = $input.data("settings");
                return maskValue(value, settings);
            },

            mask: function (value) {
                return this.each(function () {
                    var $this = $(this);
                    if (typeof value === "number") {
                        $this.val(value);
                    }
                    return $this.trigger("mask");
                });
            },

            unmasked: function () {
                return this.map(function () {
                    var value = ($(this).val() || "0"),
                        isNegative = value.indexOf("-") !== -1,
                        decimalPart,
                        settings = $(this).data("settings") || defaultOptions;

                    // if precision is > 0, we apply the adjusts for precision, 
                    if (settings.precision > 0) {
                        // get the last position of the array that is a number(coercion makes "" to be evaluated as false)
                        $(value.split(/\D/).reverse()).each(function (index, element) {
                            if (element) {
                                decimalPart = element;
                                return false;
                            }
                        });
                        value = value.replace(/\D/g, "");
                        value = value.replace(new RegExp(decimalPart + "$"), "." + decimalPart);
                        if (isNegative) {
                            value = "-" + value;
                        }
                    } else {
                        // if <= 0, replace the . of the float value
                        value = value.replace(/\D/g, "");
                    }
                    return parseFloat(value);
                });
            },

            unmaskedWithOptions: function () {
                return this.map(function () {
                    var value = ($(this).val() || "0"),
                        settings = $(this).data("settings") || defaultOptions,
                        regExp = new RegExp((settings.thousandsForUnmasked || settings.thousands), "g");
                    value = value.replace(regExp, "");
                    return parseFloat(value);
                });
            },

            init: function (parameters) {
                // the default options should not be shared with others
                parameters = $.extend($.extend({}, defaultOptions), parameters);

                return this.each(function () {
                    var $input = $(this),
                        settings,
                        onFocusValue;

                    // data-* api
                    settings = $.extend({}, parameters);
                    settings = $.extend(settings, $input.data());

                    // Store settings for use with the applyMask method.
                    $input.data("settings", settings);


                    function getInputSelection() {
                        var el = $input.get(0),
                            start = 0,
                            end = 0,
                            normalizedValue,
                            range,
                            textInputRange,
                            len,
                            endRange;

                        if (typeof el.selectionStart === "number" && typeof el.selectionEnd === "number") {
                            start = el.selectionStart;
                            end = el.selectionEnd;
                        } else {
                            range = document.selection.createRange();

                            if (range && range.parentElement() === el) {
                                len = el.value.length;
                                normalizedValue = el.value.replace(/\r\n/g, "\n");

                                // Create a working TextRange that lives only in the input
                                textInputRange = el.createTextRange();
                                textInputRange.moveToBookmark(range.getBookmark());

                                // Check if the start and end of the selection are at the very end
                                // of the input, since moveStart/moveEnd doesn't return what we want
                                // in those cases
                                endRange = el.createTextRange();
                                endRange.collapse(false);

                                if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
                                    start = end = len;
                                } else {
                                    start = -textInputRange.moveStart("character", -len);
                                    start += normalizedValue.slice(0, start).split("\n").length - 1;

                                    if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
                                        end = len;
                                    } else {
                                        end = -textInputRange.moveEnd("character", -len);
                                        end += normalizedValue.slice(0, end).split("\n").length - 1;
                                    }
                                }
                            }
                        }

                        return {
                            start: start,
                            end: end
                        };
                    } // getInputSelection

                    function canInputMoreNumbers() {
                        var haventReachedMaxLength = !($input.val().length >= $input.attr("maxlength") && $input.attr("maxlength") >= 0),
                            selection = getInputSelection(),
                            start = selection.start,
                            end = selection.end,
                            haveNumberSelected = (selection.start !== selection.end && $input.val().substring(start, end).match(/\d/)) ? true : false,
                            startWithZero = ($input.val().substring(0, 1) === "0");
                        return haventReachedMaxLength || haveNumberSelected || startWithZero;
                    }

                    function setCursorPosition(pos) {
                        // Do not set the position if
                        // the we're formatting on blur.
                        // This is because we do not want
                        // to refocus on the control after
                        // the blur.
                        if (settings.formatOnBlur) {
                            return;
                        }

                        $input.each(function (index, elem) {
                            if (elem.setSelectionRange) {
                                elem.focus();
                                elem.setSelectionRange(pos, pos);
                            } else if (elem.createTextRange) {
                                var range = elem.createTextRange();
                                range.collapse(true);
                                range.moveEnd("character", pos);
                                range.moveStart("character", pos);
                                range.select();
                            }
                        });
                    }

                    function maskAndPosition(startPos) {
                        var originalLen = $input.val().length,
                            newLen;
                        $input.val(maskValue($input.val(), settings));
                        newLen = $input.val().length;
                        // If the we're using the reverse option,
                        // do not put the cursor at the end of
                        // the input. The reverse option allows
                        // the user to input text from left to right.
                        if (!settings.reverse) {
                            startPos = startPos - (originalLen - newLen);
                        }
                        setCursorPosition(startPos);
                    }

                    function mask() {
                        var value = $input.val();
                        if (settings.allowEmpty && value === "") {
                            return;
                        }
                        var decimalPointIndex = value.indexOf(settings.decimal);
                        if (settings.precision > 0) {
                            if (decimalPointIndex < 0) {
                                value += settings.decimal + new Array(settings.precision + 1).join(0);
                            } else {
                                // If the following decimal part dosen't have enough length against the precision, it needs to be filled with zeros.
                                var integerPart = value.slice(0, decimalPointIndex),
                                    decimalPart = value.slice(decimalPointIndex + 1);
                                value = integerPart + settings.decimal + decimalPart +
                                    new Array((settings.precision + 1) - (decimalPart.length - settings.format.length)).join(0);
                            }
                        } else if (decimalPointIndex > 0) {
                            // if the precision is 0, discard the decimal part
                            value = value.slice(0, decimalPointIndex);
                        }
                        $input.val(maskValue(value, settings));
                    }

                    function changeSign() {
                        var inputValue = $input.val();
                        if (settings.allowNegative) {
                            if (inputValue !== "" && inputValue.charAt(0) === "-") {
                                return inputValue.replace("-", "");
                            } else {
                                return "-" + inputValue;
                            }
                        } else {
                            return inputValue;
                        }
                    }

                    function preventDefault(e) {
                        if (e.preventDefault) { //standard browsers
                            e.preventDefault();
                        } else { // old internet explorer
                            e.returnValue = false;
                        }
                    }

                    function fixMobile() {
                        if ($.browser.device) {
                            $input.attr("type", "tel");
                        }
                    }

                    function keypressEvent(e) {
                        e = e || window.event;
                        var key = e.which || e.charCode || e.keyCode,
                            decimalKeyCode = settings.decimal.charCodeAt(0);
                        //added to handle an IE "special" event
                        if (key === undefined) {
                            return false;
                        }

                        // any key except the numbers 0-9. if we're using settings.reverse,
                        // allow the user to input the decimal key
                        if ((key < 48 || key > 57) && (key !== decimalKeyCode || !settings.reverse)) {
                            return handleAllKeysExceptNumericalDigits(key, e);
                        } else if (!canInputMoreNumbers()) {
                            return false;
                        } else {
                            if (key === decimalKeyCode && shouldPreventDecimalKey()) {
                                return false;
                            }
                            if (settings.formatOnBlur) {
                                return true;
                            }
                            preventDefault(e);
                            applyMask(e);
                            return false;
                        }
                    }

                    function shouldPreventDecimalKey() {
                        // If all text is selected, we can accept the decimal
                        // key because it will replace everything.
                        if (isAllTextSelected()) {
                            return false;
                        }

                        return alreadyContainsDecimal();
                    }

                    function isAllTextSelected() {
                        var length = $input.val().length;
                        var selection = getInputSelection();
                        // This should if all text is selected or if the
                        // input is empty.
                        return selection.start === 0 && selection.end === length;
                    }

                    function alreadyContainsDecimal() {
                        return $input.val().indexOf(settings.decimal) > -1;
                    }

                    function applyMask(e) {
                        e = e || window.event;
                        var key = e.which || e.charCode || e.keyCode,
                            keyPressedChar = "",
                            selection,
                            startPos,
                            endPos,
                            value;
                        if (key >= 48 && key <= 57) {
                            keyPressedChar = String.fromCharCode(key);
                        }
                        selection = getInputSelection();
                        startPos = selection.start;
                        endPos = selection.end;
                        value = $input.val();
                        $input.val(value.substring(0, startPos) + keyPressedChar + value.substring(endPos, value.length));
                        maskAndPosition(startPos + 1);
                    }

                    function handleAllKeysExceptNumericalDigits(key, e) {
                        // -(minus) key
                        if (key === 45) {
                            $input.val(changeSign());
                            return false;
                            // +(plus) key
                        } else if (key === 43) {
                            $input.val($input.val().replace("-", ""));
                            return false;
                            // enter key or tab key
                        } else if (key === 13 || key === 9) {
                            return true;
                        } else if ($.browser.mozilla && (key === 37 || key === 39) && e.charCode === 0) {
                            // needed for left arrow key or right arrow key with firefox
                            // the charCode part is to avoid allowing "%"(e.charCode 0, e.keyCode 37)
                            return true;
                        } else { // any other key with keycode less than 48 and greater than 57
                            preventDefault(e);
                            return true;
                        }
                    }

                    function keydownEvent(e) {
                        e = e || window.event;
                        var key = e.which || e.charCode || e.keyCode,
                            selection,
                            startPos,
                            endPos,
                            value,
                            lastNumber;
                        //needed to handle an IE "special" event
                        if (key === undefined) {
                            return false;
                        }

                        selection = getInputSelection();
                        startPos = selection.start;
                        endPos = selection.end;

                        if (key === 8 || key === 46 || key === 63272) { // backspace or delete key (with special case for safari)
                            preventDefault(e);

                            value = $input.val();

                            // not a selection
                            if (startPos === endPos) {
                                // backspace
                                if (key === 8) {
                                    if (settings.suffix === "") {
                                        startPos -= 1;
                                    } else {
                                        // needed to find the position of the last number to be erased
                                        lastNumber = value.split("").reverse().join("").search(/\d/);
                                        startPos = value.length - lastNumber - 1;
                                        endPos = startPos + 1;
                                    }
                                    //delete
                                } else {
                                    endPos += 1;
                                }
                            }

                            $input.val(value.substring(0, startPos) + value.substring(endPos, value.length));

                            maskAndPosition(startPos);
                            return false;
                        } else if (key === 9) { // tab key
                            return true;
                        } else { // any other key
                            return true;
                        }
                    }

                    function focusEvent() {
                        onFocusValue = $input.val();
                        mask();
                        var input = $input.get(0),
                            textRange;

                        if (settings.selectAllOnFocus) {
                            input.select();
                        } else if (input.createTextRange && settings.bringCaretAtEndOnFocus) {
                            textRange = input.createTextRange();
                            textRange.collapse(false); // set the cursor at the end of the input
                            textRange.select();
                        }
                    }

                    function cutPasteEvent() {
                        setTimeout(function () {
                            mask();
                        }, 0);
                    }

                    function getDefaultMask() {
                        var n = parseFloat("0") / Math.pow(10, settings.precision);
                        return (n.toFixed(settings.precision)).replace(new RegExp("\\.", "g"), settings.decimal);
                    }

                    function blurEvent(e) {
                        if ($.browser.msie) {
                            keypressEvent(e);
                        }

                        if (!!settings.formatOnBlur && $input.val() !== onFocusValue) {
                            applyMask(e);
                        }

                        if ($input.val() === "" && settings.allowEmpty) {
                            $input.val("").trigger('change'); // trigger change so super forms removes super-filled class
                        } else if ($input.val() === "" || $input.val() === setSymbol(getDefaultMask(), settings)) {
                            if (!settings.allowZero) {
                                $input.val("").trigger('change'); // trigger change so super forms removes super-filled class
                            } else if (!settings.affixesStay) {
                                $input.val(getDefaultMask());
                            } else {
                                $input.val(setSymbol(getDefaultMask(), settings));
                            }
                        } else {
                            if (!settings.affixesStay) {
                                var newValue = $input.val().replace(settings.prefix, "").replace(settings.suffix, "");
                                $input.val(newValue);
                            }
                        }
                        if ($input.val() !== onFocusValue) {
                            $input.change();
                        }
                    }

                    function clickEvent() {
                        var input = $input.get(0),
                            length;
                        if (settings.selectAllOnFocus) {
                            // selectAllOnFocus will be handled by
                            // the focus event. The focus event is
                            // also fired when the input is clicked.
                            return;
                        } else if (input.setSelectionRange && settings.bringCaretAtEndOnFocus) {
                            length = $input.val().length;
                            input.setSelectionRange(length, length);
                        } else {
                            $input.val($input.val());
                        }
                    }

                    function doubleClickEvent() {
                        var input = $input.get(0),
                            start,
                            length;
                        if (input.setSelectionRange && settings.bringCaretAtEndOnFocus) {
                            length = $input.val().length;
                            start = settings.doubleClickSelection ? 0 : length;
                            input.setSelectionRange(start, length);
                        } else {
                            $input.val($input.val());
                        }
                    }

                    fixMobile();
                    $input.unbind(".maskMoney");
                    $input.bind("keypress.maskMoney", keypressEvent);
                    $input.bind("keydown.maskMoney", keydownEvent);
                    $input.bind("blur.maskMoney", blurEvent);
                    $input.bind("focus.maskMoney", focusEvent);
                    $input.bind("click.maskMoney", clickEvent);
                    $input.bind("dblclick.maskMoney", doubleClickEvent);
                    $input.bind("cut.maskMoney", cutPasteEvent);
                    $input.bind("paste.maskMoney", cutPasteEvent);
                    $input.bind("mask.maskMoney", mask);
                });
            }
        };

    function setSymbol(value, settings) {
        var operator = "";
        if (value.indexOf("-") > -1) {
            value = value.replace("-", "");
            operator = "-";
        }
        if (value.indexOf(settings.prefix) > -1) {
            value = value.replace(settings.prefix, "");
        }
        if (value.indexOf(settings.suffix) > -1) {
            value = value.replace(settings.suffix, "");
        }
        return operator + settings.prefix + value + settings.suffix;
    }

    function maskValue(value, settings) {
        if (settings.allowEmpty && value === "") {
            return "";
        }
        if (settings.reverse) {
            return maskValueReverse(value, settings);
        }
        return maskValueStandard(value, settings);
    }

    function maskValueStandard(value, settings) {
        var negative = (value.indexOf("-") > -1 && settings.allowNegative) ? "-" : "",
            onlyNumbers = value.replace(/[^0-9]/g, ""),
            integerPart = onlyNumbers.slice(0, onlyNumbers.length - settings.precision),
            newValue,
            decimalPart,
            leadingZeros;

        newValue = buildIntegerPart(integerPart, negative, settings);

        if (settings.precision > 0) {
            decimalPart = onlyNumbers.slice(onlyNumbers.length - settings.precision);
            leadingZeros = new Array((settings.precision + 1) - decimalPart.length).join(0);
            newValue += settings.decimal + leadingZeros + decimalPart;
        }
        return setSymbol(newValue, settings);
    }

    function maskValueReverse(value, settings) {
        var negative = (value.indexOf("-") > -1 && settings.allowNegative) ? "-" : "",
            valueWithoutSymbol = value.replace(settings.prefix, "").replace(settings.suffix, ""),
            integerPart = valueWithoutSymbol.split(settings.decimal)[0],
            newValue,
            decimalPart = "";

        if (integerPart === "") {
            integerPart = "0";
        }
        newValue = buildIntegerPart(integerPart, negative, settings);

        if (settings.precision > 0) {
            var arr = valueWithoutSymbol.split(settings.decimal);
            if (arr.length > 1) {
                decimalPart = arr[1];
            }
            newValue += settings.decimal + decimalPart;
            var rounded = Number.parseFloat((integerPart + "." + decimalPart)).toFixed(settings.precision);
            var roundedDecimalPart = rounded.toString().split(settings.decimal)[1];
            newValue = newValue.split(settings.decimal)[0] + "." + roundedDecimalPart;
        }

        return setSymbol(newValue, settings);
    }

    function buildIntegerPart(integerPart, negative, settings) {
        // remove initial zeros
        integerPart = integerPart.replace(/^0*/g, "");

        // put settings.thousands every 3 chars
        integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, settings.thousands);
        if (integerPart === "") {
            integerPart = "0";
        }
        return negative + integerPart;
    }

    $.fn.maskMoney = function (method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === "object" || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error("Method " + method + " does not exist on jQuery.maskMoney");
        }
    };
})(window.jQuery || window.Zepto);
// source --> https://homelive.pt/wp-content/plugins/super-forms/assets/js/frontend/spectrum.js?ver=6.3.312 
// jshint ignore: start
// Spectrum Colorpicker v1.8.0
// https://github.com/bgrins/spectrum
// Author: Brian Grinstead
// License: MIT

(function (factory) {
    "use strict";

    if (typeof define === 'function' && define.amd) { // AMD
        define(['jquery'], factory);
    }
    else if (typeof exports == "object" && typeof module == "object") { // CommonJS
        module.exports = factory(require('jquery'));
    }
    else { // Browser
        factory(jQuery);
    }
})(function($, undefined) {
    "use strict";

    var defaultOpts = {

        // Callbacks
        beforeShow: noop,
        move: noop,
        change: noop,
        show: noop,
        hide: noop,

        // Options
        color: false,
        flat: false,
        showInput: false,
        allowEmpty: false,
        showButtons: true,
        clickoutFiresChange: true,
        showInitial: false,
        showPalette: false,
        showPaletteOnly: false,
        hideAfterPaletteSelect: false,
        togglePaletteOnly: false,
        showSelectionPalette: true,
        localStorageKey: false,
        appendTo: "body",
        maxSelectionSize: 7,
        cancelText: "cancel",
        chooseText: "choose",
        togglePaletteMoreText: "more",
        togglePaletteLessText: "less",
        clearText: "Clear Color Selection",
        noColorSelectedText: "No Color Selected",
        preferredFormat: false,
        className: "", // Deprecated - use containerClassName and replacerClassName instead.
        containerClassName: "",
        replacerClassName: "",
        showAlpha: false,
        theme: "sp-light",
        palette: [["#ffffff", "#000000", "#ff0000", "#ff8000", "#ffff00", "#008000", "#0000ff", "#4b0082", "#9400d3"]],
        selectionPalette: [],
        disabled: false,
        offset: null
    },
    spectrums = [],
    IE = !!/msie/i.exec( window.navigator.userAgent ),
    rgbaSupport = (function() {
        function contains( str, substr ) {
            return !!~('' + str).indexOf(substr);
        }

        var elem = document.createElement('div');
        var style = elem.style;
        style.cssText = 'background-color:rgba(0,0,0,.5)';
        return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla');
    })(),
    replaceInput = [
        "<div class='sp-replacer'>",
            "<div class='sp-preview'><div class='sp-preview-inner'></div></div>",
            "<div class='sp-dd'>&#9660;</div>",
        "</div>"
    ].join(''),
    markup = (function () {

        // IE does not support gradients with multiple stops, so we need to simulate
        //  that for the rainbow slider with 8 divs that each have a single gradient
        var gradientFix = "";
        if (IE) {
            for (var i = 1; i <= 6; i++) {
                gradientFix += "<div class='sp-" + i + "'></div>";
            }
        }

        return [
            "<div class='sp-container sp-hidden'>",
                "<div class='sp-palette-container'>",
                    "<div class='sp-palette sp-thumb sp-cf'></div>",
                    "<div class='sp-palette-button-container sp-cf'>",
                        "<button type='button' class='sp-palette-toggle'></button>",
                    "</div>",
                "</div>",
                "<div class='sp-picker-container'>",
                    "<div class='sp-top sp-cf'>",
                        "<div class='sp-fill'></div>",
                        "<div class='sp-top-inner'>",
                            "<div class='sp-color'>",
                                "<div class='sp-sat'>",
                                    "<div class='sp-val'>",
                                        "<div class='sp-dragger'></div>",
                                    "</div>",
                                "</div>",
                            "</div>",
                            "<div class='sp-clear sp-clear-display'>",
                            "</div>",
                            "<div class='sp-hue'>",
                                "<div class='sp-slider'></div>",
                                gradientFix,
                            "</div>",
                        "</div>",
                        "<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>",
                    "</div>",
                    "<div class='sp-input-container sp-cf'>",
                        "<input class='sp-input' type='text' spellcheck='false'  />",
                    "</div>",
                    "<div class='sp-initial sp-thumb sp-cf'></div>",
                    "<div class='sp-button-container sp-cf'>",
                        "<a class='sp-cancel' href='#'></a>",
                        "<button type='button' class='sp-choose'></button>",
                    "</div>",
                "</div>",
            "</div>"
        ].join("");
    })();

    function paletteTemplate (p, color, className, opts) {
        var html = [];
        for (var i = 0; i < p.length; i++) {
            var current = p[i];
            if(current) {
                var tiny = tinycolor(current);
                var c = tiny.toHsl().l < 0.5 ? "sp-thumb-el sp-thumb-dark" : "sp-thumb-el sp-thumb-light";
                c += (tinycolor.equals(color, current)) ? " sp-thumb-active" : "";
                var formattedString = tiny.toString(opts.preferredFormat || "rgb");
                var swatchStyle = rgbaSupport ? ("background-color:" + tiny.toRgbString()) : "filter:" + tiny.toFilter();
                html.push('<span title="' + formattedString + '" data-color="' + tiny.toRgbString() + '" class="' + c + '"><span class="sp-thumb-inner" style="' + swatchStyle + ';" /></span>');
            } else {
                var cls = 'sp-clear-display';
                html.push($('<div />')
                    .append($('<span data-color="" style="background-color:transparent;" class="' + cls + '"></span>')
                        .attr('title', opts.noColorSelectedText)
                    )
                    .html()
                );
            }
        }
        return "<div class='sp-cf " + className + "'>" + html.join('') + "</div>";
    }

    function hideAll() {
        for (var i = 0; i < spectrums.length; i++) {
            if (spectrums[i]) {
                spectrums[i].hide();
            }
        }
    }

    function instanceOptions(o, callbackContext) {
        var opts = $.extend({}, defaultOpts, o);
        opts.callbacks = {
            'move': bind(opts.move, callbackContext),
            'change': bind(opts.change, callbackContext),
            'show': bind(opts.show, callbackContext),
            'hide': bind(opts.hide, callbackContext),
            'beforeShow': bind(opts.beforeShow, callbackContext)
        };

        return opts;
    }

    function spectrum(element, o) {

        var opts = instanceOptions(o, element),
            flat = opts.flat,
            showSelectionPalette = opts.showSelectionPalette,
            localStorageKey = opts.localStorageKey,
            theme = opts.theme,
            callbacks = opts.callbacks,
            resize = throttle(reflow, 10),
            visible = false,
            isDragging = false,
            dragWidth = 0,
            dragHeight = 0,
            dragHelperHeight = 0,
            slideHeight = 0,
            slideWidth = 0,
            alphaWidth = 0,
            alphaSlideHelperWidth = 0,
            slideHelperHeight = 0,
            currentHue = 0,
            currentSaturation = 0,
            currentValue = 0,
            currentAlpha = 1,
            palette = [],
            paletteArray = [],
            paletteLookup = {},
            selectionPalette = opts.selectionPalette.slice(0),
            maxSelectionSize = opts.maxSelectionSize,
            draggingClass = "sp-dragging",
            shiftMovementDirection = null;

        var doc = element.ownerDocument,
            boundElement = $(element),
            disabled = false,
            container = $(markup, doc).addClass(theme),
            pickerContainer = container.find(".sp-picker-container"),
            dragger = container.find(".sp-color"),
            dragHelper = container.find(".sp-dragger"),
            slider = container.find(".sp-hue"),
            slideHelper = container.find(".sp-slider"),
            alphaSliderInner = container.find(".sp-alpha-inner"),
            alphaSlider = container.find(".sp-alpha"),
            alphaSlideHelper = container.find(".sp-alpha-handle"),
            textInput = container.find(".sp-input"),
            paletteContainer = container.find(".sp-palette"),
            initialColorContainer = container.find(".sp-initial"),
            cancelButton = container.find(".sp-cancel"),
            clearButton = container.find(".sp-clear"),
            chooseButton = container.find(".sp-choose"),
            toggleButton = container.find(".sp-palette-toggle"),
            isInput = boundElement.is("input"),
            isInputTypeColor = isInput && boundElement.attr("type") === "color" && inputTypeColorSupport(),
            shouldReplace = isInput && !flat,
            replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]),
            offsetElement = (shouldReplace) ? replacer : boundElement,
            previewElement = replacer.find(".sp-preview-inner"),
            initialColor = opts.color || (isInput && boundElement.val()),
            colorOnShow = false,
            currentPreferredFormat = opts.preferredFormat,
            clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange,
            isEmpty = !initialColor,
            allowEmpty = opts.allowEmpty && !isInputTypeColor;

        function applyOptions() {

            if (opts.showPaletteOnly) {
                opts.showPalette = true;
            }

            toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);

            if (opts.palette) {
                palette = opts.palette.slice(0);
                paletteArray = $.isArray(palette[0]) ? palette : [palette];
                paletteLookup = {};
                for (var i = 0; i < paletteArray.length; i++) {
                    for (var j = 0; j < paletteArray[i].length; j++) {
                        var rgb = tinycolor(paletteArray[i][j]).toRgbString();
                        paletteLookup[rgb] = true;
                    }
                }
            }

            container.toggleClass("sp-flat", flat);
            container.toggleClass("sp-input-disabled", !opts.showInput);
            container.toggleClass("sp-alpha-enabled", opts.showAlpha);
            container.toggleClass("sp-clear-enabled", allowEmpty);
            container.toggleClass("sp-buttons-disabled", !opts.showButtons);
            container.toggleClass("sp-palette-buttons-disabled", !opts.togglePaletteOnly);
            container.toggleClass("sp-palette-disabled", !opts.showPalette);
            container.toggleClass("sp-palette-only", opts.showPaletteOnly);
            container.toggleClass("sp-initial-disabled", !opts.showInitial);
            container.addClass(opts.className).addClass(opts.containerClassName);

            reflow();
        }

        function initialize() {

            if (IE) {
                container.find("*:not(input)").attr("unselectable", "on");
            }

            applyOptions();

            if (shouldReplace) {
                boundElement.after(replacer).hide();
            }

            if (!allowEmpty) {
                clearButton.hide();
            }

            if (flat) {
                boundElement.after(container).hide();
            }
            else {

                var appendTo = opts.appendTo === "parent" ? boundElement.parent() : $(opts.appendTo);
                if (appendTo.length !== 1) {
                    appendTo = $("body");
                }

                appendTo.append(container);
            }

            updateSelectionPaletteFromStorage();

            offsetElement.on("click.spectrum touchstart.spectrum", function (e) {
                if (!disabled) {
                    toggle();
                }

                e.stopPropagation();

                if (!$(e.target).is("input")) {
                    e.preventDefault();
                }
            });

            if(boundElement.is(":disabled") || (opts.disabled === true)) {
                disable();
            }

            // Prevent clicks from bubbling up to document.  This would cause it to be hidden.
            container.click(stopPropagation);

            // Handle user typed input
            textInput.change(setFromTextInput);
            textInput.on("paste", function () {
                setTimeout(setFromTextInput, 1);
            });
            textInput.keydown(function (e) { if (e.keyCode == 13) { setFromTextInput(); } });

            cancelButton.text(opts.cancelText);
            cancelButton.on("click.spectrum", function (e) {
                e.stopPropagation();
                e.preventDefault();
                revert();
                hide();
            });

            clearButton.attr("title", opts.clearText);
            clearButton.on("click.spectrum", function (e) {
                e.stopPropagation();
                e.preventDefault();
                isEmpty = true;
                move();

                if(flat) {
                    //for the flat style, this is a change event
                    updateOriginalInput(true);
                }
            });

            chooseButton.text(opts.chooseText);
            chooseButton.on("click.spectrum", function (e) {
                e.stopPropagation();
                e.preventDefault();

                if (IE && textInput.is(":focus")) {
                    textInput.trigger('change');
                }

                if (isValid()) {
                    updateOriginalInput(true);
                    hide();
                }
            });

            toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);
            toggleButton.on("click.spectrum", function (e) {
                e.stopPropagation();
                e.preventDefault();

                opts.showPaletteOnly = !opts.showPaletteOnly;

                // To make sure the Picker area is drawn on the right, next to the
                // Palette area (and not below the palette), first move the Palette
                // to the left to make space for the picker, plus 5px extra.
                // The 'applyOptions' function puts the whole container back into place
                // and takes care of the button-text and the sp-palette-only CSS class.
                if (!opts.showPaletteOnly && !flat) {
                    container.css('left', '-=' + (pickerContainer.outerWidth(true) + 5));
                }
                applyOptions();
            });

            draggable(alphaSlider, function (dragX, dragY, e) {
                currentAlpha = (dragX / alphaWidth);
                isEmpty = false;
                if (e.shiftKey) {
                    currentAlpha = Math.round(currentAlpha * 10) / 10;
                }

                move();
            }, dragStart, dragStop);

            draggable(slider, function (dragX, dragY) {
                currentHue = parseFloat(dragY / slideHeight);
                isEmpty = false;
                if (!opts.showAlpha) {
                    currentAlpha = 1;
                }
                move();
            }, dragStart, dragStop);

            draggable(dragger, function (dragX, dragY, e) {

                // shift+drag should snap the movement to either the x or y axis.
                if (!e.shiftKey) {
                    shiftMovementDirection = null;
                }
                else if (!shiftMovementDirection) {
                    var oldDragX = currentSaturation * dragWidth;
                    var oldDragY = dragHeight - (currentValue * dragHeight);
                    var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY);

                    shiftMovementDirection = furtherFromX ? "x" : "y";
                }

                var setSaturation = !shiftMovementDirection || shiftMovementDirection === "x";
                var setValue = !shiftMovementDirection || shiftMovementDirection === "y";

                if (setSaturation) {
                    currentSaturation = parseFloat(dragX / dragWidth);
                }
                if (setValue) {
                    currentValue = parseFloat((dragHeight - dragY) / dragHeight);
                }

                isEmpty = false;
                if (!opts.showAlpha) {
                    currentAlpha = 1;
                }

                move();

            }, dragStart, dragStop);

            if (initialColor) {
                set(initialColor);

                // In case color was black - update the preview UI and set the format
                // since the set function will not run (default color is black).
                updateUI();
                currentPreferredFormat = opts.preferredFormat || tinycolor(initialColor).format;

                addColorToSelectionPalette(initialColor);
            }
            else {
                updateUI();
            }

            if (flat) {
                show();
            }

            function paletteElementClick(e) {
                if (e.data && e.data.ignore) {
                    set($(e.target).closest(".sp-thumb-el").data("color"));
                    move();
                }
                else {
                    set($(e.target).closest(".sp-thumb-el").data("color"));
                    move();

                    // If the picker is going to close immediately, a palette selection
                    // is a change.  Otherwise, it's a move only.
                    if (opts.hideAfterPaletteSelect) {
                        updateOriginalInput(true);
                        hide();
                    } else {
                        updateOriginalInput();
                    }
                }

                return false;
            }

            var paletteEvent = IE ? "mousedown.spectrum" : "click.spectrum touchstart.spectrum";
            paletteContainer.on(paletteEvent, ".sp-thumb-el", paletteElementClick);
            initialColorContainer.on(paletteEvent, ".sp-thumb-el:nth-child(1)", { ignore: true }, paletteElementClick);
        }

        function updateSelectionPaletteFromStorage() {

            if (localStorageKey && window.localStorage) {

                // Migrate old palettes over to new format.  May want to remove this eventually.
                try {
                    var oldPalette = window.localStorage[localStorageKey].split(",#");
                    if (oldPalette.length > 1) {
                        delete window.localStorage[localStorageKey];
                        $.each(oldPalette, function(i, c) {
                             addColorToSelectionPalette(c);
                        });
                    }
                }
                catch(e) { }

                try {
                    selectionPalette = window.localStorage[localStorageKey].split(";");
                }
                catch (e) { }
            }
        }

        function addColorToSelectionPalette(color) {
            if (showSelectionPalette) {
                var rgb = tinycolor(color).toRgbString();
                if (!paletteLookup[rgb] && $.inArray(rgb, selectionPalette) === -1) {
                    selectionPalette.push(rgb);
                    while(selectionPalette.length > maxSelectionSize) {
                        selectionPalette.shift();
                    }
                }

                if (localStorageKey && window.localStorage) {
                    try {
                        window.localStorage[localStorageKey] = selectionPalette.join(";");
                    }
                    catch(e) { }
                }
            }
        }

        function getUniqueSelectionPalette() {
            var unique = [];
            if (opts.showPalette) {
                for (var i = 0; i < selectionPalette.length; i++) {
                    var rgb = tinycolor(selectionPalette[i]).toRgbString();

                    if (!paletteLookup[rgb]) {
                        unique.push(selectionPalette[i]);
                    }
                }
            }

            return unique.reverse().slice(0, opts.maxSelectionSize);
        }

        function drawPalette() {

            var currentColor = get();

            var html = $.map(paletteArray, function (palette, i) {
                return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i, opts);
            });

            updateSelectionPaletteFromStorage();

            if (selectionPalette) {
                html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "sp-palette-row sp-palette-row-selection", opts));
            }

            paletteContainer.html(html.join(""));
        }

        function drawInitial() {
            if (opts.showInitial) {
                var initial = colorOnShow;
                var current = get();
                initialColorContainer.html(paletteTemplate([initial, current], current, "sp-palette-row-initial", opts));
            }
        }

        function dragStart() {
            if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) {
                reflow();
            }
            isDragging = true;
            container.addClass(draggingClass);
            shiftMovementDirection = null;
            boundElement.trigger('dragstart.spectrum', [ get() ]);
        }

        function dragStop() {
            isDragging = false;
            container.removeClass(draggingClass);
            boundElement.trigger('dragstop.spectrum', [ get() ]);
        }

        function setFromTextInput() {

            var value = textInput.val();

            if ((value === null || value === "") && allowEmpty) {
                set(null);
                move();
                updateOriginalInput();
            }
            else {
                var tiny = tinycolor(value);
                if (tiny.isValid()) {
                    set(tiny);
                    move();
                    updateOriginalInput();
                }
                else {
                    textInput.addClass("sp-validation-error");
                }
            }
        }

        function toggle() {
            if (visible) {
                hide();
            }
            else {
                show();
            }
        }

        function show() {
            var event = $.Event('beforeShow.spectrum');

            if (visible) {
                reflow();
                return;
            }

            boundElement.trigger(event, [ get() ]);

            if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) {
                return;
            }

            hideAll();
            visible = true;

            $(doc).on("keydown.spectrum", onkeydown);
            $(doc).on("click.spectrum", clickout);
            $(window).on("resize.spectrum", resize);
            replacer.addClass("sp-active");
            container.removeClass("sp-hidden");

            reflow();
            updateUI();

            colorOnShow = get();

            drawInitial();
            callbacks.show(colorOnShow);
            boundElement.trigger('show.spectrum', [ colorOnShow ]);
        }

        function onkeydown(e) {
            // Close on ESC
            if (e.keyCode === 27) {
                hide();
            }
        }

        function clickout(e) {
            // Return on right click.
            if (e.button == 2) { return; }

            // If a drag event was happening during the mouseup, don't hide
            // on click.
            if (isDragging) { return; }

            if (clickoutFiresChange) {
                updateOriginalInput(true);
            }
            else {
                revert();
            }
            hide();
        }

        function hide() {
            // Return if hiding is unnecessary
            if (!visible || flat) { return; }
            visible = false;

            $(doc).off("keydown.spectrum", onkeydown);
            $(doc).off("click.spectrum", clickout);
            $(window).off("resize.spectrum", resize);

            replacer.removeClass("sp-active");
            container.addClass("sp-hidden");

            callbacks.hide(get());
            boundElement.trigger('hide.spectrum', [ get() ]);
        }

        function revert() {
            set(colorOnShow, true);
            updateOriginalInput(true);
        }

        function set(color, ignoreFormatChange) {
            if (tinycolor.equals(color, get())) {
                // Update UI just in case a validation error needs
                // to be cleared.
                updateUI();
                return;
            }

            var newColor, newHsv;
            if (!color && allowEmpty) {
                isEmpty = true;
            } else {
                isEmpty = false;
                newColor = tinycolor(color);
                newHsv = newColor.toHsv();

                currentHue = (newHsv.h % 360) / 360;
                currentSaturation = newHsv.s;
                currentValue = newHsv.v;
                currentAlpha = newHsv.a;
            }
            updateUI();

            if (newColor && newColor.isValid() && !ignoreFormatChange) {
                currentPreferredFormat = opts.preferredFormat || newColor.getFormat();
            }
        }

        function get(opts) {
            opts = opts || { };

            if (allowEmpty && isEmpty) {
                return null;
            }

            return tinycolor.fromRatio({
                h: currentHue,
                s: currentSaturation,
                v: currentValue,
                a: Math.round(currentAlpha * 1000) / 1000
            }, { format: opts.format || currentPreferredFormat });
        }

        function isValid() {
            return !textInput.hasClass("sp-validation-error");
        }

        function move() {
            updateUI();

            callbacks.move(get());
            boundElement.trigger('move.spectrum', [ get() ]);
        }

        function updateUI() {

            textInput.removeClass("sp-validation-error");

            updateHelperLocations();

            // Update dragger background color (gradients take care of saturation and value).
            var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 });
            dragger.css("background-color", flatColor.toHexString());

            // Get a format that alpha will be included in (hex and names ignore alpha)
            var format = currentPreferredFormat;
            if (currentAlpha < 1 && !(currentAlpha === 0 && format === "name")) {
                if (format === "hex" || format === "hex3" || format === "hex6" || format === "name") {
                    format = "rgb";
                }
            }

            var realColor = get({ format: format }),
                displayColor = '';

             //reset background info for preview element
            previewElement.removeClass("sp-clear-display");
            previewElement.css('background-color', 'transparent');

            if (!realColor && allowEmpty) {
                // Update the replaced elements background with icon indicating no color selection
                previewElement.addClass("sp-clear-display");
            }
            else {
                var realHex = realColor.toHexString(),
                    realRgb = realColor.toRgbString();

                // Update the replaced elements background color (with actual selected color)
                if (rgbaSupport || realColor.alpha === 1) {
                    previewElement.css("background-color", realRgb);
                }
                else {
                    previewElement.css("background-color", "transparent");
                    previewElement.css("filter", realColor.toFilter());
                }

                if (opts.showAlpha) {
                    var rgb = realColor.toRgb();
                    rgb.a = 0;
                    var realAlpha = tinycolor(rgb).toRgbString();
                    var gradient = "linear-gradient(left, " + realAlpha + ", " + realHex + ")";

                    if (IE) {
                        alphaSliderInner.css("filter", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex));
                    }
                    else {
                        alphaSliderInner.css("background", "-webkit-" + gradient);
                        alphaSliderInner.css("background", "-moz-" + gradient);
                        alphaSliderInner.css("background", "-ms-" + gradient);
                        // Use current syntax gradient on unprefixed property.
                        alphaSliderInner.css("background",
                            "linear-gradient(to right, " + realAlpha + ", " + realHex + ")");
                    }
                }

                displayColor = realColor.toString(format);
            }

            // Update the text entry input as it changes happen
            if (opts.showInput) {
                textInput.val(displayColor);
            }

            if (opts.showPalette) {
                drawPalette();
            }

            drawInitial();
        }

        function updateHelperLocations() {
            var s = currentSaturation;
            var v = currentValue;

            if(allowEmpty && isEmpty) {
                //if selected color is empty, hide the helpers
                alphaSlideHelper.hide();
                slideHelper.hide();
                dragHelper.hide();
            }
            else {
                //make sure helpers are visible
                alphaSlideHelper.show();
                slideHelper.show();
                dragHelper.show();

                // Where to show the little circle in that displays your current selected color
                var dragX = s * dragWidth;
                var dragY = dragHeight - (v * dragHeight);
                dragX = Math.max(
                    -dragHelperHeight,
                    Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)
                );
                dragY = Math.max(
                    -dragHelperHeight,
                    Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight)
                );
                dragHelper.css({
                    "top": dragY + "px",
                    "left": dragX + "px"
                });

                var alphaX = currentAlpha * alphaWidth;
                alphaSlideHelper.css({
                    "left": (alphaX - (alphaSlideHelperWidth / 2)) + "px"
                });

                // Where to show the bar that displays your current selected hue
                var slideY = (currentHue) * slideHeight;
                slideHelper.css({
                    "top": (slideY - slideHelperHeight) + "px"
                });
            }
        }

        function updateOriginalInput(fireCallback) {
            var color = get(),
                displayColor = '',
                hasChanged = !tinycolor.equals(color, colorOnShow);

            if (color) {
                displayColor = color.toString(currentPreferredFormat);
                // Update the selection palette with the current color
                addColorToSelectionPalette(color);
            }

            if (isInput) {
                boundElement.val(displayColor);
            }

            if (fireCallback && hasChanged) {
                callbacks.change(color);
                boundElement.trigger('change', [ color ]);
            }
        }

        function reflow() {
            if (!visible) {
                return; // Calculations would be useless and wouldn't be reliable anyways
            }
            dragWidth = dragger.width();
            dragHeight = dragger.height();
            dragHelperHeight = dragHelper.height();
            slideWidth = slider.width();
            slideHeight = slider.height();
            slideHelperHeight = slideHelper.height();
            alphaWidth = alphaSlider.width();
            alphaSlideHelperWidth = alphaSlideHelper.width();

            if (!flat) {
                container.css("position", "absolute");
                if (opts.offset) {
                    container.offset(opts.offset);
                } else {
                    container.offset(getOffset(container, offsetElement));
                }
            }

            updateHelperLocations();

            if (opts.showPalette) {
                drawPalette();
            }

            boundElement.trigger('reflow.spectrum');
        }

        function destroy() {
            boundElement.show();
            offsetElement.off("click.spectrum touchstart.spectrum");
            container.remove();
            replacer.remove();
            spectrums[spect.id] = null;
        }

        function option(optionName, optionValue) {
            if (optionName === undefined) {
                return $.extend({}, opts);
            }
            if (optionValue === undefined) {
                return opts[optionName];
            }

            opts[optionName] = optionValue;

            if (optionName === "preferredFormat") {
                currentPreferredFormat = opts.preferredFormat;
            }
            applyOptions();
        }

        function enable() {
            disabled = false;
            boundElement.attr("disabled", false);
            offsetElement.removeClass("sp-disabled");
        }

        function disable() {
            hide();
            disabled = true;
            boundElement.attr("disabled", true);
            offsetElement.addClass("sp-disabled");
        }

        function setOffset(coord) {
            opts.offset = coord;
            reflow();
        }

        initialize();

        var spect = {
            show: show,
            hide: hide,
            toggle: toggle,
            reflow: reflow,
            option: option,
            enable: enable,
            disable: disable,
            offset: setOffset,
            set: function (c) {
                set(c);
                updateOriginalInput();
            },
            get: get,
            destroy: destroy,
            container: container
        };

        spect.id = spectrums.push(spect) - 1;

        return spect;
    }

    /**
    * checkOffset - get the offset below/above and left/right element depending on screen position
    * Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js
    */
    function getOffset(picker, input) {
        var extraY = 0;
        var dpWidth = picker.outerWidth();
        var dpHeight = picker.outerHeight();
        var inputHeight = input.outerHeight();
        var doc = picker[0].ownerDocument;
        var docElem = doc.documentElement;
        var viewWidth = docElem.clientWidth + $(doc).scrollLeft();
        var viewHeight = docElem.clientHeight + $(doc).scrollTop();
        var offset = input.offset();
        var offsetLeft = offset.left;
        var offsetTop = offset.top;

        offsetTop += inputHeight;

        offsetLeft -=
            Math.min(offsetLeft, (offsetLeft + dpWidth > viewWidth && viewWidth > dpWidth) ?
            Math.abs(offsetLeft + dpWidth - viewWidth) : 0);

        offsetTop -=
            Math.min(offsetTop, ((offsetTop + dpHeight > viewHeight && viewHeight > dpHeight) ?
            Math.abs(dpHeight + inputHeight - extraY) : extraY));

        return {
            top: offsetTop,
            bottom: offset.bottom,
            left: offsetLeft,
            right: offset.right,
            width: offset.width,
            height: offset.height
        };
    }

    /**
    * noop - do nothing
    */
    function noop() {

    }

    /**
    * stopPropagation - makes the code only doing this a little easier to read in line
    */
    function stopPropagation(e) {
        e.stopPropagation();
    }

    /**
    * Create a function bound to a given object
    * Thanks to underscore.js
    */
    function bind(func, obj) {
        var slice = Array.prototype.slice;
        var args = slice.call(arguments, 2);
        return function () {
            return func.apply(obj, args.concat(slice.call(arguments)));
        };
    }

    /**
    * Lightweight drag helper.  Handles containment within the element, so that
    * when dragging, the x is within [0,element.width] and y is within [0,element.height]
    */
    function draggable(element, onmove, onstart, onstop) {
        onmove = onmove || function () { };
        onstart = onstart || function () { };
        onstop = onstop || function () { };
        var doc = document;
        var dragging = false;
        var offset = {};
        var maxHeight = 0;
        var maxWidth = 0;
        var hasTouch = ('ontouchstart' in window);

        var duringDragEvents = {};
        duringDragEvents.selectstart = prevent;
        duringDragEvents.dragstart = prevent;
        duringDragEvents["touchmove mousemove"] = move;
        duringDragEvents["touchend mouseup"] = stop;

        function prevent(e) {
            if (e.stopPropagation) {
                e.stopPropagation();
            }
            if (e.preventDefault) {
                e.preventDefault();
            }
            e.returnValue = false;
        }

        function move(e) {
            if (dragging) {
                // Mouseup happened outside of window
                if (IE && doc.documentMode < 9 && !e.button) {
                    return stop();
                }

                var t0 = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0];
                var pageX = t0 && t0.pageX || e.pageX;
                var pageY = t0 && t0.pageY || e.pageY;

                var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth));
                var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));

                if (hasTouch) {
                    // Stop scrolling in iOS
                    prevent(e);
                }

                onmove.apply(element, [dragX, dragY, e]);
            }
        }

        function start(e) {
            var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);

            if (!rightclick && !dragging) {
                if (onstart.apply(element, arguments) !== false) {
                    dragging = true;
                    maxHeight = $(element).height();
                    maxWidth = $(element).width();
                    offset = $(element).offset();

                    $(doc).on(duringDragEvents);
                    $(doc.body).addClass("sp-dragging");

                    move(e);

                    prevent(e);
                }
            }
        }

        function stop() {
            if (dragging) {
                $(doc).off(duringDragEvents);
                $(doc.body).removeClass("sp-dragging");

                // Wait a tick before notifying observers to allow the click event
                // to fire in Chrome.
                setTimeout(function() {
                    onstop.apply(element, arguments);
                }, 0);
            }
            dragging = false;
        }

        $(element).on("touchstart mousedown", start);
    }

    function throttle(func, wait, debounce) {
        var timeout;
        return function () {
            var context = this, args = arguments;
            var throttler = function () {
                timeout = null;
                func.apply(context, args);
            };
            if (debounce) clearTimeout(timeout);
            if (debounce || !timeout) timeout = setTimeout(throttler, wait);
        };
    }

    function inputTypeColorSupport() {
        return $.fn.spectrum.inputTypeColorSupport();
    }

    /**
    * Define a jQuery plugin
    */
    var dataID = "spectrum.id";
    $.fn.spectrum = function (opts) {

        if (typeof opts == "string") {

            var returnValue = this;
            var args = Array.prototype.slice.call( arguments, 1 );

            this.each(function () {
                var spect = spectrums[$(this).data(dataID)];
                if (spect) {
                    var method = spect[opts];
                    if (!method) {
                        throw new Error( "Spectrum: no such method: '" + opts + "'" );
                    }

                    if (opts == "get") {
                        returnValue = spect.get();
                    }
                    else if (opts == "container") {
                        returnValue = spect.container;
                    }
                    else if (opts == "option") {
                        returnValue = spect.option.apply(spect, args);
                    }
                    else if (opts == "destroy") {
                        spect.destroy();
                        $(this).removeData(dataID);
                    }
                    else {
                        method.apply(spect, args);
                    }
                }
            });

            return returnValue;
        }

        // Initializing a new instance of spectrum
        return this.spectrum("destroy").each(function () {
            var options = $.extend({}, $(this).data(), opts);
            var spect = spectrum(this, options);
            $(this).data(dataID, spect.id);
        });
    };

    $.fn.spectrum.load = true;
    $.fn.spectrum.loadOpts = {};
    $.fn.spectrum.draggable = draggable;
    $.fn.spectrum.defaults = defaultOpts;
    $.fn.spectrum.inputTypeColorSupport = function inputTypeColorSupport() {
        if (typeof inputTypeColorSupport._cachedResult === "undefined") {
            var colorInput = $("<input type='color'/>")[0]; // if color element is supported, value will default to not null
            inputTypeColorSupport._cachedResult = colorInput.type === "color" && colorInput.value !== "";
        }
        return inputTypeColorSupport._cachedResult;
    };

    $.spectrum = { };
    $.spectrum.localization = { };
    $.spectrum.palettes = { };

    $.fn.spectrum.processNativeColorInputs = function () {
        var colorInputs = $("input[type=color]");
        if (colorInputs.length && !inputTypeColorSupport()) {
            colorInputs.spectrum({
                preferredFormat: "hex6"
            });
        }
    };

    // TinyColor v1.1.2
    // https://github.com/bgrins/TinyColor
    // Brian Grinstead, MIT License

    (function() {

    var trimLeft = /^[\s,#]+/,
        trimRight = /\s+$/,
        tinyCounter = 0,
        math = Math,
        mathRound = math.round,
        mathMin = math.min,
        mathMax = math.max,
        mathRandom = math.random;

    var tinycolor = function(color, opts) {

        color = (color) ? color : '';
        opts = opts || { };

        // If input is already a tinycolor, return itself
        if (color instanceof tinycolor) {
           return color;
        }
        // If we are called as a function, call using new instead
        if (!(this instanceof tinycolor)) {
            return new tinycolor(color, opts);
        }

        var rgb = inputToRGB(color);
        this._originalInput = color;
        this._r = rgb.r;
        this._g = rgb.g;
        this._b = rgb.b;
        this._a = rgb.a;
        this._roundA = mathRound(1000 * this._a) / 1000;
        this._format = opts.format || rgb.format;
        this._gradientType = opts.gradientType;

        // Don't let the range of [0,255] come back in [0,1].
        // Potentially lose a little bit of precision here, but will fix issues where
        // .5 gets interpreted as half of the total, instead of half of 1
        // If it was supposed to be 128, this was already taken care of by `inputToRgb`
        if (this._r < 1) { this._r = mathRound(this._r); }
        if (this._g < 1) { this._g = mathRound(this._g); }
        if (this._b < 1) { this._b = mathRound(this._b); }

        this._ok = rgb.ok;
        this._tc_id = tinyCounter++;
    };

    tinycolor.prototype = {
        isDark: function() {
            return this.getBrightness() < 128;
        },
        isLight: function() {
            return !this.isDark();
        },
        isValid: function() {
            return this._ok;
        },
        getOriginalInput: function() {
          return this._originalInput;
        },
        getFormat: function() {
            return this._format;
        },
        getAlpha: function() {
            return this._a;
        },
        getBrightness: function() {
            var rgb = this.toRgb();
            return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
        },
        setAlpha: function(value) {
            this._a = boundAlpha(value);
            this._roundA = mathRound(1000 * this._a) / 1000;
            return this;
        },
        toHsv: function() {
            var hsv = rgbToHsv(this._r, this._g, this._b);
            return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
        },
        toHsvString: function() {
            var hsv = rgbToHsv(this._r, this._g, this._b);
            var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
            return (this._a == 1) ?
              "hsv("  + h + ", " + s + "%, " + v + "%)" :
              "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")";
        },
        toHsl: function() {
            var hsl = rgbToHsl(this._r, this._g, this._b);
            return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
        },
        toHslString: function() {
            var hsl = rgbToHsl(this._r, this._g, this._b);
            var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
            return (this._a == 1) ?
              "hsl("  + h + ", " + s + "%, " + l + "%)" :
              "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")";
        },
        toHex: function(allow3Char) {
            return rgbToHex(this._r, this._g, this._b, allow3Char);
        },
        toHexString: function(allow3Char) {
            return '#' + this.toHex(allow3Char);
        },
        toHex8: function() {
            return rgbaToHex(this._r, this._g, this._b, this._a);
        },
        toHex8String: function() {
            return '#' + this.toHex8();
        },
        toRgb: function() {
            return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };
        },
        toRgbString: function() {
            return (this._a == 1) ?
              "rgb("  + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" :
              "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")";
        },
        toPercentageRgb: function() {
            return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a };
        },
        toPercentageRgbString: function() {
            return (this._a == 1) ?
              "rgb("  + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" :
              "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")";
        },
        toName: function() {
            if (this._a === 0) {
                return "transparent";
            }

            if (this._a < 1) {
                return false;
            }

            return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
        },
        toFilter: function(secondColor) {
            var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a);
            var secondHex8String = hex8String;
            var gradientType = this._gradientType ? "GradientType = 1, " : "";

            if (secondColor) {
                var s = tinycolor(secondColor);
                secondHex8String = s.toHex8String();
            }

            return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")";
        },
        toString: function(format) {
            var formatSet = !!format;
            format = format || this._format;

            var formattedString = false;
            var hasAlpha = this._a < 1 && this._a >= 0;
            var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "name");

            if (needsAlphaFormat) {
                // Special case for "transparent", all other non-alpha formats
                // will return rgba when there is transparency.
                if (format === "name" && this._a === 0) {
                    return this.toName();
                }
                return this.toRgbString();
            }
            if (format === "rgb") {
                formattedString = this.toRgbString();
            }
            if (format === "prgb") {
                formattedString = this.toPercentageRgbString();
            }
            if (format === "hex" || format === "hex6") {
                formattedString = this.toHexString();
            }
            if (format === "hex3") {
                formattedString = this.toHexString(true);
            }
            if (format === "hex8") {
                formattedString = this.toHex8String();
            }
            if (format === "name") {
                formattedString = this.toName();
            }
            if (format === "hsl") {
                formattedString = this.toHslString();
            }
            if (format === "hsv") {
                formattedString = this.toHsvString();
            }

            return formattedString || this.toHexString();
        },

        _applyModification: function(fn, args) {
            var color = fn.apply(null, [this].concat([].slice.call(args)));
            this._r = color._r;
            this._g = color._g;
            this._b = color._b;
            this.setAlpha(color._a);
            return this;
        },
        lighten: function() {
            return this._applyModification(lighten, arguments);
        },
        brighten: function() {
            return this._applyModification(brighten, arguments);
        },
        darken: function() {
            return this._applyModification(darken, arguments);
        },
        desaturate: function() {
            return this._applyModification(desaturate, arguments);
        },
        saturate: function() {
            return this._applyModification(saturate, arguments);
        },
        greyscale: function() {
            return this._applyModification(greyscale, arguments);
        },
        spin: function() {
            return this._applyModification(spin, arguments);
        },

        _applyCombination: function(fn, args) {
            return fn.apply(null, [this].concat([].slice.call(args)));
        },
        analogous: function() {
            return this._applyCombination(analogous, arguments);
        },
        complement: function() {
            return this._applyCombination(complement, arguments);
        },
        monochromatic: function() {
            return this._applyCombination(monochromatic, arguments);
        },
        splitcomplement: function() {
            return this._applyCombination(splitcomplement, arguments);
        },
        triad: function() {
            return this._applyCombination(triad, arguments);
        },
        tetrad: function() {
            return this._applyCombination(tetrad, arguments);
        }
    };

    // If input is an object, force 1 into "1.0" to handle ratios properly
    // String input requires "1.0" as input, so 1 will be treated as 1
    tinycolor.fromRatio = function(color, opts) {
        if (typeof color == "object") {
            var newColor = {};
            for (var i in color) {
                if (color.hasOwnProperty(i)) {
                    if (i === "a") {
                        newColor[i] = color[i];
                    }
                    else {
                        newColor[i] = convertToPercentage(color[i]);
                    }
                }
            }
            color = newColor;
        }

        return tinycolor(color, opts);
    };

    // Given a string or object, convert that input to RGB
    // Possible string inputs:
    //
    //     "red"
    //     "#f00" or "f00"
    //     "#ff0000" or "ff0000"
    //     "#ff000000" or "ff000000"
    //     "rgb 255 0 0" or "rgb (255, 0, 0)"
    //     "rgb 1.0 0 0" or "rgb (1, 0, 0)"
    //     "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
    //     "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
    //     "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
    //     "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
    //     "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
    //
    function inputToRGB(color) {

        var rgb = { r: 0, g: 0, b: 0 };
        var a = 1;
        var ok = false;
        var format = false;

        if (typeof color == "string") {
            color = stringInputToObject(color);
        }

        if (typeof color == "object") {
            if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
                rgb = rgbToRgb(color.r, color.g, color.b);
                ok = true;
                format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
            }
            else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
                color.s = convertToPercentage(color.s);
                color.v = convertToPercentage(color.v);
                rgb = hsvToRgb(color.h, color.s, color.v);
                ok = true;
                format = "hsv";
            }
            else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
                color.s = convertToPercentage(color.s);
                color.l = convertToPercentage(color.l);
                rgb = hslToRgb(color.h, color.s, color.l);
                ok = true;
                format = "hsl";
            }

            if (color.hasOwnProperty("a")) {
                a = color.a;
            }
        }

        a = boundAlpha(a);

        return {
            ok: ok,
            format: color.format || format,
            r: mathMin(255, mathMax(rgb.r, 0)),
            g: mathMin(255, mathMax(rgb.g, 0)),
            b: mathMin(255, mathMax(rgb.b, 0)),
            a: a
        };
    }


    // Conversion Functions
    // --------------------

    // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
    // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>

    // `rgbToRgb`
    // Handle bounds / percentage checking to conform to CSS color spec
    // <http://www.w3.org/TR/css3-color/>
    // *Assumes:* r, g, b in [0, 255] or [0, 1]
    // *Returns:* { r, g, b } in [0, 255]
    function rgbToRgb(r, g, b){
        return {
            r: bound01(r, 255) * 255,
            g: bound01(g, 255) * 255,
            b: bound01(b, 255) * 255
        };
    }

    // `rgbToHsl`
    // Converts an RGB color value to HSL.
    // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
    // *Returns:* { h, s, l } in [0,1]
    function rgbToHsl(r, g, b) {

        r = bound01(r, 255);
        g = bound01(g, 255);
        b = bound01(b, 255);

        var max = mathMax(r, g, b), min = mathMin(r, g, b);
        var h, s, l = (max + min) / 2;

        if(max == min) {
            h = s = 0; // achromatic
        }
        else {
            var d = max - min;
            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
            switch(max) {
                case r: h = (g - b) / d + (g < b ? 6 : 0); break;
                case g: h = (b - r) / d + 2; break;
                case b: h = (r - g) / d + 4; break;
            }

            h /= 6;
        }

        return { h: h, s: s, l: l };
    }

    // `hslToRgb`
    // Converts an HSL color value to RGB.
    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
    // *Returns:* { r, g, b } in the set [0, 255]
    function hslToRgb(h, s, l) {
        var r, g, b;

        h = bound01(h, 360);
        s = bound01(s, 100);
        l = bound01(l, 100);

        function hue2rgb(p, q, t) {
            if(t < 0) t += 1;
            if(t > 1) t -= 1;
            if(t < 1/6) return p + (q - p) * 6 * t;
            if(t < 1/2) return q;
            if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
            return p;
        }

        if(s === 0) {
            r = g = b = l; // achromatic
        }
        else {
            var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
            var p = 2 * l - q;
            r = hue2rgb(p, q, h + 1/3);
            g = hue2rgb(p, q, h);
            b = hue2rgb(p, q, h - 1/3);
        }

        return { r: r * 255, g: g * 255, b: b * 255 };
    }

    // `rgbToHsv`
    // Converts an RGB color value to HSV
    // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
    // *Returns:* { h, s, v } in [0,1]
    function rgbToHsv(r, g, b) {

        r = bound01(r, 255);
        g = bound01(g, 255);
        b = bound01(b, 255);

        var max = mathMax(r, g, b), min = mathMin(r, g, b);
        var h, s, v = max;

        var d = max - min;
        s = max === 0 ? 0 : d / max;

        if(max == min) {
            h = 0; // achromatic
        }
        else {
            switch(max) {
                case r: h = (g - b) / d + (g < b ? 6 : 0); break;
                case g: h = (b - r) / d + 2; break;
                case b: h = (r - g) / d + 4; break;
            }
            h /= 6;
        }
        return { h: h, s: s, v: v };
    }

    // `hsvToRgb`
    // Converts an HSV color value to RGB.
    // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
    // *Returns:* { r, g, b } in the set [0, 255]
     function hsvToRgb(h, s, v) {

        h = bound01(h, 360) * 6;
        s = bound01(s, 100);
        v = bound01(v, 100);

        var i = math.floor(h),
            f = h - i,
            p = v * (1 - s),
            q = v * (1 - f * s),
            t = v * (1 - (1 - f) * s),
            mod = i % 6,
            r = [v, q, p, p, t, v][mod],
            g = [t, v, v, q, p, p][mod],
            b = [p, p, t, v, v, q][mod];

        return { r: r * 255, g: g * 255, b: b * 255 };
    }

    // `rgbToHex`
    // Converts an RGB color to hex
    // Assumes r, g, and b are contained in the set [0, 255]
    // Returns a 3 or 6 character hex
    function rgbToHex(r, g, b, allow3Char) {

        var hex = [
            pad2(mathRound(r).toString(16)),
            pad2(mathRound(g).toString(16)),
            pad2(mathRound(b).toString(16))
        ];

        // Return a 3 character hex if possible
        if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
            return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
        }

        return hex.join("");
    }
        // `rgbaToHex`
        // Converts an RGBA color plus alpha transparency to hex
        // Assumes r, g, b and a are contained in the set [0, 255]
        // Returns an 8 character hex
        function rgbaToHex(r, g, b, a) {

            var hex = [
                pad2(convertDecimalToHex(a)),
                pad2(mathRound(r).toString(16)),
                pad2(mathRound(g).toString(16)),
                pad2(mathRound(b).toString(16))
            ];

            return hex.join("");
        }

    // `equals`
    // Can be called with any tinycolor input
    tinycolor.equals = function (color1, color2) {
        if (!color1 || !color2) { return false; }
        return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
    };
    tinycolor.random = function() {
        return tinycolor.fromRatio({
            r: mathRandom(),
            g: mathRandom(),
            b: mathRandom()
        });
    };


    // Modification Functions
    // ----------------------
    // Thanks to less.js for some of the basics here
    // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>

    function desaturate(color, amount) {
        amount = (amount === 0) ? 0 : (amount || 10);
        var hsl = tinycolor(color).toHsl();
        hsl.s -= amount / 100;
        hsl.s = clamp01(hsl.s);
        return tinycolor(hsl);
    }

    function saturate(color, amount) {
        amount = (amount === 0) ? 0 : (amount || 10);
        var hsl = tinycolor(color).toHsl();
        hsl.s += amount / 100;
        hsl.s = clamp01(hsl.s);
        return tinycolor(hsl);
    }

    function greyscale(color) {
        return tinycolor(color).desaturate(100);
    }

    function lighten (color, amount) {
        amount = (amount === 0) ? 0 : (amount || 10);
        var hsl = tinycolor(color).toHsl();
        hsl.l += amount / 100;
        hsl.l = clamp01(hsl.l);
        return tinycolor(hsl);
    }

    function brighten(color, amount) {
        amount = (amount === 0) ? 0 : (amount || 10);
        var rgb = tinycolor(color).toRgb();
        rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100))));
        rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100))));
        rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100))));
        return tinycolor(rgb);
    }

    function darken (color, amount) {
        amount = (amount === 0) ? 0 : (amount || 10);
        var hsl = tinycolor(color).toHsl();
        hsl.l -= amount / 100;
        hsl.l = clamp01(hsl.l);
        return tinycolor(hsl);
    }

    // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
    // Values outside of this range will be wrapped into this range.
    function spin(color, amount) {
        var hsl = tinycolor(color).toHsl();
        var hue = (mathRound(hsl.h) + amount) % 360;
        hsl.h = hue < 0 ? 360 + hue : hue;
        return tinycolor(hsl);
    }

    // Combination Functions
    // ---------------------
    // Thanks to jQuery xColor for some of the ideas behind these
    // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>

    function complement(color) {
        var hsl = tinycolor(color).toHsl();
        hsl.h = (hsl.h + 180) % 360;
        return tinycolor(hsl);
    }

    function triad(color) {
        var hsl = tinycolor(color).toHsl();
        var h = hsl.h;
        return [
            tinycolor(color),
            tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
            tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
        ];
    }

    function tetrad(color) {
        var hsl = tinycolor(color).toHsl();
        var h = hsl.h;
        return [
            tinycolor(color),
            tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
            tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
            tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
        ];
    }

    function splitcomplement(color) {
        var hsl = tinycolor(color).toHsl();
        var h = hsl.h;
        return [
            tinycolor(color),
            tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
            tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
        ];
    }

    function analogous(color, results, slices) {
        results = results || 6;
        slices = slices || 30;

        var hsl = tinycolor(color).toHsl();
        var part = 360 / slices;
        var ret = [tinycolor(color)];

        for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
            hsl.h = (hsl.h + part) % 360;
            ret.push(tinycolor(hsl));
        }
        return ret;
    }

    function monochromatic(color, results) {
        results = results || 6;
        var hsv = tinycolor(color).toHsv();
        var h = hsv.h, s = hsv.s, v = hsv.v;
        var ret = [];
        var modification = 1 / results;

        while (results--) {
            ret.push(tinycolor({ h: h, s: s, v: v}));
            v = (v + modification) % 1;
        }

        return ret;
    }

    // Utility Functions
    // ---------------------

    tinycolor.mix = function(color1, color2, amount) {
        amount = (amount === 0) ? 0 : (amount || 50);

        var rgb1 = tinycolor(color1).toRgb();
        var rgb2 = tinycolor(color2).toRgb();

        var p = amount / 100;
        var w = p * 2 - 1;
        var a = rgb2.a - rgb1.a;

        var w1;

        if (w * a == -1) {
            w1 = w;
        } else {
            w1 = (w + a) / (1 + w * a);
        }

        w1 = (w1 + 1) / 2;

        var w2 = 1 - w1;

        var rgba = {
            r: rgb2.r * w1 + rgb1.r * w2,
            g: rgb2.g * w1 + rgb1.g * w2,
            b: rgb2.b * w1 + rgb1.b * w2,
            a: rgb2.a * p  + rgb1.a * (1 - p)
        };

        return tinycolor(rgba);
    };


    // Readability Functions
    // ---------------------
    // <http://www.w3.org/TR/AERT#color-contrast>

    // `readability`
    // Analyze the 2 colors and returns an object with the following properties:
    //    `brightness`: difference in brightness between the two colors
    //    `color`: difference in color/hue between the two colors
    tinycolor.readability = function(color1, color2) {
        var c1 = tinycolor(color1);
        var c2 = tinycolor(color2);
        var rgb1 = c1.toRgb();
        var rgb2 = c2.toRgb();
        var brightnessA = c1.getBrightness();
        var brightnessB = c2.getBrightness();
        var colorDiff = (
            Math.max(rgb1.r, rgb2.r) - Math.min(rgb1.r, rgb2.r) +
            Math.max(rgb1.g, rgb2.g) - Math.min(rgb1.g, rgb2.g) +
            Math.max(rgb1.b, rgb2.b) - Math.min(rgb1.b, rgb2.b)
        );

        return {
            brightness: Math.abs(brightnessA - brightnessB),
            color: colorDiff
        };
    };

    // `readable`
    // http://www.w3.org/TR/AERT#color-contrast
    // Ensure that foreground and background color combinations provide sufficient contrast.
    // *Example*
    //    tinycolor.isReadable("#000", "#111") => false
    tinycolor.isReadable = function(color1, color2) {
        var readability = tinycolor.readability(color1, color2);
        return readability.brightness > 125 && readability.color > 500;
    };

    // `mostReadable`
    // Given a base color and a list of possible foreground or background
    // colors for that base, returns the most readable color.
    // *Example*
    //    tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
    tinycolor.mostReadable = function(baseColor, colorList) {
        var bestColor = null;
        var bestScore = 0;
        var bestIsReadable = false;
        for (var i=0; i < colorList.length; i++) {

            // We normalize both around the "acceptable" breaking point,
            // but rank brightness constrast higher than hue.

            var readability = tinycolor.readability(baseColor, colorList[i]);
            var readable = readability.brightness > 125 && readability.color > 500;
            var score = 3 * (readability.brightness / 125) + (readability.color / 500);

            if ((readable && ! bestIsReadable) ||
                (readable && bestIsReadable && score > bestScore) ||
                ((! readable) && (! bestIsReadable) && score > bestScore)) {
                bestIsReadable = readable;
                bestScore = score;
                bestColor = tinycolor(colorList[i]);
            }
        }
        return bestColor;
    };


    // Big List of Colors
    // ------------------
    // <http://www.w3.org/TR/css3-color/#svg-color>
    var names = tinycolor.names = {
        aliceblue: "f0f8ff",
        antiquewhite: "faebd7",
        aqua: "0ff",
        aquamarine: "7fffd4",
        azure: "f0ffff",
        beige: "f5f5dc",
        bisque: "ffe4c4",
        black: "000",
        blanchedalmond: "ffebcd",
        blue: "00f",
        blueviolet: "8a2be2",
        brown: "a52a2a",
        burlywood: "deb887",
        burntsienna: "ea7e5d",
        cadetblue: "5f9ea0",
        chartreuse: "7fff00",
        chocolate: "d2691e",
        coral: "ff7f50",
        cornflowerblue: "6495ed",
        cornsilk: "fff8dc",
        crimson: "dc143c",
        cyan: "0ff",
        darkblue: "00008b",
        darkcyan: "008b8b",
        darkgoldenrod: "b8860b",
        darkgray: "a9a9a9",
        darkgreen: "006400",
        darkgrey: "a9a9a9",
        darkkhaki: "bdb76b",
        darkmagenta: "8b008b",
        darkolivegreen: "556b2f",
        darkorange: "ff8c00",
        darkorchid: "9932cc",
        darkred: "8b0000",
        darksalmon: "e9967a",
        darkseagreen: "8fbc8f",
        darkslateblue: "483d8b",
        darkslategray: "2f4f4f",
        darkslategrey: "2f4f4f",
        darkturquoise: "00ced1",
        darkviolet: "9400d3",
        deeppink: "ff1493",
        deepskyblue: "00bfff",
        dimgray: "696969",
        dimgrey: "696969",
        dodgerblue: "1e90ff",
        firebrick: "b22222",
        floralwhite: "fffaf0",
        forestgreen: "228b22",
        fuchsia: "f0f",
        gainsboro: "dcdcdc",
        ghostwhite: "f8f8ff",
        gold: "ffd700",
        goldenrod: "daa520",
        gray: "808080",
        green: "008000",
        greenyellow: "adff2f",
        grey: "808080",
        honeydew: "f0fff0",
        hotpink: "ff69b4",
        indianred: "cd5c5c",
        indigo: "4b0082",
        ivory: "fffff0",
        khaki: "f0e68c",
        lavender: "e6e6fa",
        lavenderblush: "fff0f5",
        lawngreen: "7cfc00",
        lemonchiffon: "fffacd",
        lightblue: "add8e6",
        lightcoral: "f08080",
        lightcyan: "e0ffff",
        lightgoldenrodyellow: "fafad2",
        lightgray: "d3d3d3",
        lightgreen: "90ee90",
        lightgrey: "d3d3d3",
        lightpink: "ffb6c1",
        lightsalmon: "ffa07a",
        lightseagreen: "20b2aa",
        lightskyblue: "87cefa",
        lightslategray: "789",
        lightslategrey: "789",
        lightsteelblue: "b0c4de",
        lightyellow: "ffffe0",
        lime: "0f0",
        limegreen: "32cd32",
        linen: "faf0e6",
        magenta: "f0f",
        maroon: "800000",
        mediumaquamarine: "66cdaa",
        mediumblue: "0000cd",
        mediumorchid: "ba55d3",
        mediumpurple: "9370db",
        mediumseagreen: "3cb371",
        mediumslateblue: "7b68ee",
        mediumspringgreen: "00fa9a",
        mediumturquoise: "48d1cc",
        mediumvioletred: "c71585",
        midnightblue: "191970",
        mintcream: "f5fffa",
        mistyrose: "ffe4e1",
        moccasin: "ffe4b5",
        navajowhite: "ffdead",
        navy: "000080",
        oldlace: "fdf5e6",
        olive: "808000",
        olivedrab: "6b8e23",
        orange: "ffa500",
        orangered: "ff4500",
        orchid: "da70d6",
        palegoldenrod: "eee8aa",
        palegreen: "98fb98",
        paleturquoise: "afeeee",
        palevioletred: "db7093",
        papayawhip: "ffefd5",
        peachpuff: "ffdab9",
        peru: "cd853f",
        pink: "ffc0cb",
        plum: "dda0dd",
        powderblue: "b0e0e6",
        purple: "800080",
        rebeccapurple: "663399",
        red: "f00",
        rosybrown: "bc8f8f",
        royalblue: "4169e1",
        saddlebrown: "8b4513",
        salmon: "fa8072",
        sandybrown: "f4a460",
        seagreen: "2e8b57",
        seashell: "fff5ee",
        sienna: "a0522d",
        silver: "c0c0c0",
        skyblue: "87ceeb",
        slateblue: "6a5acd",
        slategray: "708090",
        slategrey: "708090",
        snow: "fffafa",
        springgreen: "00ff7f",
        steelblue: "4682b4",
        tan: "d2b48c",
        teal: "008080",
        thistle: "d8bfd8",
        tomato: "ff6347",
        turquoise: "40e0d0",
        violet: "ee82ee",
        wheat: "f5deb3",
        white: "fff",
        whitesmoke: "f5f5f5",
        yellow: "ff0",
        yellowgreen: "9acd32"
    };

    // Make it easy to access colors via `hexNames[hex]`
    var hexNames = tinycolor.hexNames = flip(names);


    // Utilities
    // ---------

    // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
    function flip(o) {
        var flipped = { };
        for (var i in o) {
            if (o.hasOwnProperty(i)) {
                flipped[o[i]] = i;
            }
        }
        return flipped;
    }

    // Return a valid alpha value [0,1] with all invalid values being set to 1
    function boundAlpha(a) {
        a = parseFloat(a);

        if (isNaN(a) || a < 0 || a > 1) {
            a = 1;
        }

        return a;
    }

    // Take input from [0, n] and return it as [0, 1]
    function bound01(n, max) {
        if (isOnePointZero(n)) { n = "100%"; }

        var processPercent = isPercentage(n);
        n = mathMin(max, mathMax(0, parseFloat(n)));

        // Automatically convert percentage into number
        if (processPercent) {
            n = parseInt(n * max, 10) / 100;
        }

        // Handle floating point rounding errors
        if ((math.abs(n - max) < 0.000001)) {
            return 1;
        }

        // Convert into [0, 1] range if it isn't already
        return (n % max) / parseFloat(max);
    }

    // Force a number between 0 and 1
    function clamp01(val) {
        return mathMin(1, mathMax(0, val));
    }

    // Parse a base-16 hex value into a base-10 integer
    function parseIntFromHex(val) {
        return parseInt(val, 16);
    }

    // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
    // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
    function isOnePointZero(n) {
        return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
    }

    // Check to see if string passed in is a percentage
    function isPercentage(n) {
        return typeof n === "string" && n.indexOf('%') != -1;
    }

    // Force a hex value to have 2 characters
    function pad2(c) {
        return c.length == 1 ? '0' + c : '' + c;
    }

    // Replace a decimal with it's percentage value
    function convertToPercentage(n) {
        if (n <= 1) {
            n = (n * 100) + "%";
        }

        return n;
    }

    // Converts a decimal to a hex value
    function convertDecimalToHex(d) {
        return Math.round(parseFloat(d) * 255).toString(16);
    }
    // Converts a hex value to a decimal
    function convertHexToDecimal(h) {
        return (parseIntFromHex(h) / 255);
    }

    var matchers = (function() {

        // <http://www.w3.org/TR/css3-values/#integers>
        var CSS_INTEGER = "[-\\+]?\\d+%?";

        // <http://www.w3.org/TR/css3-values/#number-value>
        var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";

        // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.
        var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";

        // Actual matching.
        // Parentheses and commas are optional, but not required.
        // Whitespace can take the place of commas or opening paren
        var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
        var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";

        return {
            rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
            rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
            hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
            hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
            hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
            hsva: new RegExp("hsva" + PERMISSIVE_MATCH4),
            hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
            hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
            hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
        };
    })();

    // `stringInputToObject`
    // Permissive string parsing.  Take in a number of formats, and output an object
    // based on detected format.  Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
    function stringInputToObject(color) {

        color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
        var named = false;
        if (names[color]) {
            color = names[color];
            named = true;
        }
        else if (color == 'transparent') {
            return { r: 0, g: 0, b: 0, a: 0, format: "name" };
        }

        // Try to match string input using regular expressions.
        // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
        // Just return an object and let the conversion functions handle that.
        // This way the result will be the same whether the tinycolor is initialized with string or object.
        var match;
        if ((match = matchers.rgb.exec(color))) {
            return { r: match[1], g: match[2], b: match[3] };
        }
        if ((match = matchers.rgba.exec(color))) {
            return { r: match[1], g: match[2], b: match[3], a: match[4] };
        }
        if ((match = matchers.hsl.exec(color))) {
            return { h: match[1], s: match[2], l: match[3] };
        }
        if ((match = matchers.hsla.exec(color))) {
            return { h: match[1], s: match[2], l: match[3], a: match[4] };
        }
        if ((match = matchers.hsv.exec(color))) {
            return { h: match[1], s: match[2], v: match[3] };
        }
        if ((match = matchers.hsva.exec(color))) {
            return { h: match[1], s: match[2], v: match[3], a: match[4] };
        }
        if ((match = matchers.hex8.exec(color))) {
            return {
                a: convertHexToDecimal(match[1]),
                r: parseIntFromHex(match[2]),
                g: parseIntFromHex(match[3]),
                b: parseIntFromHex(match[4]),
                format: named ? "name" : "hex8"
            };
        }
        if ((match = matchers.hex6.exec(color))) {
            return {
                r: parseIntFromHex(match[1]),
                g: parseIntFromHex(match[2]),
                b: parseIntFromHex(match[3]),
                format: named ? "name" : "hex"
            };
        }
        if ((match = matchers.hex3.exec(color))) {
            return {
                r: parseIntFromHex(match[1] + '' + match[1]),
                g: parseIntFromHex(match[2] + '' + match[2]),
                b: parseIntFromHex(match[3] + '' + match[3]),
                format: named ? "name" : "hex"
            };
        }

        return false;
    }

    window.tinycolor = tinycolor;
    })();

    $(function () {
        if ($.fn.spectrum.load) {
            $.fn.spectrum.processNativeColorInputs();
        }
    });

});
// source --> https://homelive.pt/wp-content/plugins/super-forms/assets/js/backend/tooltips.js?ver=6.3.312 
// jshint ignore: start
/**
 * tooltipster http://iamceege.github.io/tooltipster/
 * A rockin' custom tooltip jQuery plugin
 * Developed by Caleb Jacob and Louis Ameline
 * MIT license
 */
(function(root, factory) {
    "use strict";
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module unless amdModuleId is set
        define(["jquery"], function(a0) {
            return (factory(a0));
        });
    } else if (typeof exports === 'object') {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like environments that support module.exports,
        // like Node.
        module.exports = factory(require("jquery"));
    } else {
        factory(jQuery);
    }
}(this, function($) {
    "use strict";
    // This file will be UMDified by a build task.

    var defaults = {
            animation: 'fade',
            animationDuration: 350,
            content: null,
            contentAsHTML: false,
            contentCloning: false,
            debug: true,
            delay: 300,
            delayTouch: [300, 500],
            functionInit: null,
            functionBefore: null,
            functionReady: null,
            functionAfter: null,
            functionFormat: null,
            IEmin: 6,
            interactive: false,
            multiple: false,
            // will default to document.body, or must be an element positioned at (0, 0)
            // in the document, typically like the very top views of an app.
            parent: null,
            plugins: ['sideTip'],
            repositionOnScroll: false,
            restoration: 'none',
            selfDestruction: true,
            theme: [],
            timer: 0,
            trackerInterval: 500,
            trackOrigin: false,
            trackTooltip: false,
            trigger: 'hover',
            triggerClose: {
                click: false,
                mouseleave: false,
                originClick: false,
                scroll: false,
                tap: false,
                touchleave: false
            },
            triggerOpen: {
                click: false,
                mouseenter: false,
                tap: false,
                touchstart: false
            },
            updateAnimation: 'rotate',
            zIndex: 9999999
        },
        // we'll avoid using the 'window' global as a good practice but npm's
        // jquery@<2.1.0 package actually requires a 'window' global, so not sure
        // it's useful at all
        win = (typeof window != 'undefined') ? window : null,
        // env will be proxied by the core for plugins to have access its properties
        env = {
            // detect if this device can trigger touch events. Better have a false
            // positive (unused listeners, that's ok) than a false negative.
            // https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js
            // http://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript
            hasTouchCapability: !!(win && ('ontouchstart' in win || (win.DocumentTouch && win.document instanceof win.DocumentTouch) || win.navigator.maxTouchPoints)),
            hasTransitions: transitionSupport(),
            IE: false,
            // don't set manually, it will be updated by a build task after the manifest
            semVer: '4.2.6',
            window: win
        },
        core = function() {

            // core variables

            // the core emitters
            this.__$emitterPrivate = $({});
            this.__$emitterPublic = $({});
            this.__instancesLatestArr = [];
            // collects plugin constructors
            this.__plugins = {};
            // proxy env variables for plugins who might use them
            this._env = env;
        };

    // core methods
    core.prototype = {

        /**
         * A function to proxy the public methods of an object onto another
         *
         * @param {object} constructor The constructor to bridge
         * @param {object} obj The object that will get new methods (an instance or the core)
         * @param {string} pluginName A plugin name for the console log message
         * @return {core}
         * @private
         */
        __bridge: function(constructor, obj, pluginName) {

            // if it's not already bridged
            if (!obj[pluginName]) {

                var fn = function() {};
                fn.prototype = constructor;

                var pluginInstance = new fn();

                // the _init method has to exist in instance constructors but might be missing
                // in core constructors
                if (pluginInstance.__init) {
                    pluginInstance.__init(obj);
                }

                $.each(constructor, function(methodName) {

                    // don't proxy "private" methods, only "protected" and public ones
                    if (methodName.indexOf('__') != 0) {

                        // if the method does not exist yet
                        if (!obj[methodName]) {

                            obj[methodName] = function() {
                                return pluginInstance[methodName].apply(pluginInstance, Array.prototype.slice.apply(arguments));
                            };

                            // remember to which plugin this method corresponds (several plugins may
                            // have methods of the same name, we need to be sure)
                            obj[methodName].bridged = pluginInstance;
                        } else if (defaults.debug) {

                            console.log('The ' + methodName + ' method of the ' + pluginName + ' plugin conflicts with another plugin or native methods');
                        }
                    }
                });

                obj[pluginName] = pluginInstance;
            }

            return this;
        },

        /**
         * For mockup in Node env if need be, for testing purposes
         *
         * @return {core}
         * @private
         */
        __setWindow: function(window) {
            env.window = window;
            return this;
        },

        /**
         * Returns a ruler, a tool to help measure the size of a tooltip under
         * various settings. Meant for plugins
         * 
         * @see Ruler
         * @return {object} A Ruler instance
         * @protected
         */
        _getRuler: function($tooltip) {
            return new Ruler($tooltip);
        },

        /**
         * For internal use by plugins, if needed
         *
         * @return {core}
         * @protected
         */
        _off: function() {
            this.__$emitterPrivate.off.apply(this.__$emitterPrivate, Array.prototype.slice.apply(arguments));
            return this;
        },

        /**
         * For internal use by plugins, if needed
         *
         * @return {core}
         * @protected
         */
        _on: function() {
            this.__$emitterPrivate.on.apply(this.__$emitterPrivate, Array.prototype.slice.apply(arguments));
            return this;
        },

        /**
         * For internal use by plugins, if needed
         *
         * @return {core}
         * @protected
         */
        _one: function() {
            this.__$emitterPrivate.one.apply(this.__$emitterPrivate, Array.prototype.slice.apply(arguments));
            return this;
        },

        /**
         * Returns (getter) or adds (setter) a plugin
         *
         * @param {string|object} plugin Provide a string (in the full form
         * "namespace.name") to use as as getter, an object to use as a setter
         * @return {object|core}
         * @protected
         */
        _plugin: function(plugin) {

            var self = this;

            // getter
            if (typeof plugin == 'string') {

                var pluginName = plugin,
                    p = null;

                // if the namespace is provided, it's easy to search
                if (pluginName.indexOf('.') > 0) {
                    p = self.__plugins[pluginName];
                }
                // otherwise, return the first name that matches
                else {
                    $.each(self.__plugins, function(i, plugin) {

                        if (plugin.name.substring(plugin.name.length - pluginName.length - 1) == '.' + pluginName) {
                            p = plugin;
                            return false;
                        }
                    });
                }

                return p;
            }
            // setter
            else {

                // force namespaces
                if (plugin.name.indexOf('.') < 0) {
                    throw new Error('Plugins must be namespaced');
                }

                self.__plugins[plugin.name] = plugin;

                // if the plugin has core features
                if (plugin.core) {

                    // bridge non-private methods onto the core to allow new core methods
                    self.__bridge(plugin.core, self, plugin.name);
                }

                return this;
            }
        },

        /**
         * Trigger events on the core emitters
         * 
         * @returns {core}
         * @protected
         */
        _trigger: function() {

            var args = Array.prototype.slice.apply(arguments);

            if (typeof args[0] == 'string') {
                args[0] = {
                    type: args[0]
                };
            }

            // note: the order of emitters matters
            this.__$emitterPrivate.trigger.apply(this.__$emitterPrivate, args);
            this.__$emitterPublic.trigger.apply(this.__$emitterPublic, args);

            return this;
        },

        /**
         * Returns instances of all tooltips in the page or an a given element
         *
         * @param {string|HTML object collection} selector optional Use this
         * parameter to restrict the set of objects that will be inspected
         * for the retrieval of instances. By default, all instances in the
         * page are returned.
         * @return {array} An array of instance objects
         * @public
         */
        instances: function(selector) {

            var instances = [],
                sel = selector || '.tooltipstered';

            $(sel).each(function() {

                var $this = $(this),
                    ns = $this.data('tooltipster-ns');

                if (ns) {

                    $.each(ns, function(i, namespace) {
                        instances.push($this.data(namespace));
                    });
                }
            });

            return instances;
        },

        /**
         * Returns the Tooltipster objects generated by the last initializing call
         *
         * @return {array} An array of instance objects
         * @public
         */
        instancesLatest: function() {
            return this.__instancesLatestArr;
        },

        /**
         * For public use only, not to be used by plugins (use ::_off() instead)
         *
         * @return {core}
         * @public
         */
        off: function() {
            this.__$emitterPublic.off.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments));
            return this;
        },

        /**
         * For public use only, not to be used by plugins (use ::_on() instead)
         *
         * @return {core}
         * @public
         */
        on: function() {
            this.__$emitterPublic.on.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments));
            return this;
        },

        /**
         * For public use only, not to be used by plugins (use ::_one() instead)
         * 
         * @return {core}
         * @public
         */
        one: function() {
            this.__$emitterPublic.one.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments));
            return this;
        },

        /**
         * Returns all HTML elements which have one or more tooltips
         *
         * @param {string} selector optional Use this to restrict the results
         * to the descendants of an element
         * @return {array} An array of HTML elements
         * @public
         */
        origins: function(selector) {

            var sel = selector ?
                selector + ' ' :
                '';

            return $(sel + '.tooltipstered').toArray();
        },

        /**
         * Change default options for all future instances
         *
         * @param {object} d The options that should be made defaults
         * @return {core}
         * @public
         */
        setDefaults: function(d) {
            $.extend(defaults, d);
            return this;
        },

        /**
         * For users to trigger their handlers on the public emitter
         * 
         * @returns {core}
         * @public
         */
        triggerHandler: function() {
            this.__$emitterPublic.triggerHandler.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments));
            return this;
        }
    };

    // $.tooltipster will be used to call core methods
    $.tooltipster = new core();

    // the Tooltipster instance class (mind the capital T)
    $.Tooltipster = function(element, options) {

        // list of instance variables

        // stack of custom callbacks provided as parameters to API methods
        this.__callbacks = {
            close: [],
            open: []
        };
        // the schedule time of DOM removal
        //this.__closingTime;
        // this will be the user content shown in the tooltip. A capital "C" is used
        // because there is also a method called content()
        //this.__Content;
        // for the size tracker
        //this.__contentBcr;
        // to disable the tooltip after destruction
        this.__destroyed = false;
        // we can't emit directly on the instance because if a method with the same
        // name as the event exists, it will be called by jQuery. Se we use a plain
        // object as emitter. This emitter is for internal use by plugins,
        // if needed.
        this.__$emitterPrivate = $({});
        // this emitter is for the user to listen to events without risking to mess
        // with our internal listeners
        this.__$emitterPublic = $({});
        this.__enabled = true;
        // the reference to the gc interval
        //this.__garbageCollector;
        // various position and size data recomputed before each repositioning
        //this.__Geometry;
        // the tooltip position, saved after each repositioning by a plugin
        //this.__lastPosition;
        // a unique namespace per instance
        this.__namespace = 'tooltipster-' + Math.round(Math.random() * 1000000);
        //this.__options;
        // will be used to support origins in scrollable areas
        //this.__$originParents;
        this.__pointerIsOverOrigin = false;
        // to remove themes if needed
        this.__previousThemes = [];
        // the state can be either: appearing, stable, disappearing, closed
        this.__state = 'closed';
        // timeout references
        this.__timeouts = {
            close: [],
            open: null
        };
        // store touch events to be able to detect emulated mouse events
        this.__touchEvents = [];
        // the reference to the tracker interval
        this.__tracker = null;
        // the element to which this tooltip is associated
        //this._$origin;
        // this will be the tooltip element (jQuery wrapped HTML element).
        // It's the job of a plugin to create it and append it to the DOM
        //this._$tooltip;

        // launch
        this.__init(element, options);
    };

    $.Tooltipster.prototype = {

        /**
         * @param origin
         * @param options
         * @private
         */
        __init: function(origin, options) {

            var self = this;

            self._$origin = $(origin);
            self.__options = $.extend(true, {}, defaults, options);

            // some options may need to be reformatted
            self.__optionsFormat();

            // don't run on old IE if asked no to
            if (!env.IE || env.IE >= self.__options.IEmin) {

                // note: the content is null (empty) by default and can stay that
                // way if the plugin remains initialized but not fed any content. The
                // tooltip will just not appear.

                // let's save the initial value of the title attribute for later
                // restoration if need be.
                var initialTitle = null;

                // it will already have been saved in case of multiple tooltips
                if (self._$origin.data('tooltipster-initialTitle') === undefined) {

                    initialTitle = self._$origin.attr('title');

                    // we do not want initialTitle to be "undefined" because
                    // of how jQuery's .data() method works
                    if (initialTitle === undefined) initialTitle = null;

                    self._$origin.data('tooltipster-initialTitle', initialTitle);
                }

                // If content is provided in the options, it has precedence over the
                // title attribute.
                // Note: an empty string is considered content, only 'null' represents
                // the absence of content.
                // Also, an existing title="" attribute will result in an empty string
                // content
                if (self.__options.content !== null) {
                    self.__contentSet(self.__options.content);
                } else {

                    var selector = self._$origin.attr('data-tooltip-content'),
                        $el;

                    if (selector) {
                        $el = $(selector);
                    }

                    if ($el && $el[0]) {
                        self.__contentSet($el.first());
                    } else {
                        self.__contentSet(initialTitle);
                    }
                }

                self._$origin
                    // strip the title off of the element to prevent the default tooltips
                    // from popping up
                    .removeAttr('title')
                    // to be able to find all instances on the page later (upon window
                    // events in particular)
                    .addClass('tooltipstered');

                // set listeners on the origin
                self.__prepareOrigin();

                // set the garbage collector
                self.__prepareGC();

                // init plugins
                $.each(self.__options.plugins, function(i, pluginName) {
                    self._plug(pluginName);
                });

                // to detect swiping
                if (env.hasTouchCapability) {
                    $(env.window.document.body).on('touchmove.' + self.__namespace + '-triggerOpen', function(event) {
                        self._touchRecordEvent(event);
                    });
                }

                self
                    // prepare the tooltip when it gets created. This event must
                    // be fired by a plugin
                    ._on('created', function() {
                        self.__prepareTooltip();
                    })
                    // save position information when it's sent by a plugin
                    ._on('repositioned', function(e) {
                        self.__lastPosition = e.position;
                    });
            } else {
                self.__options.disabled = true;
            }
        },

        /**
         * Insert the content into the appropriate HTML element of the tooltip
         * 
         * @returns {self}
         * @private
         */
        __contentInsert: function() {

            var self = this,
                $el = self._$tooltip.find('.tooltipster-content'),
                formattedContent = self.__Content,
                format = function(content) {
                    formattedContent = content;
                };

            self._trigger({
                type: 'format',
                content: self.__Content,
                format: format
            });

            if (self.__options.functionFormat) {

                formattedContent = self.__options.functionFormat.call(
                    self,
                    self, {
                        origin: self._$origin[0]
                    },
                    self.__Content
                );
            }

            if (typeof formattedContent === 'string' && !self.__options.contentAsHTML) {
                $el.text(formattedContent);
            } else {
                $el
                    .empty()
                    .append(formattedContent);
            }

            return self;
        },

        /**
         * Save the content, cloning it beforehand if need be
         * 
         * @param content
         * @returns {self}
         * @private
         */
        __contentSet: function(content) {

            // clone if asked. Cloning the object makes sure that each instance has its
            // own version of the content (in case a same object were provided for several
            // instances)
            // reminder: typeof null === object
            if (content instanceof $ && this.__options.contentCloning) {
                content = content.clone(true);
            }

            this.__Content = content;

            this._trigger({
                type: 'updated',
                content: content
            });

            return this;
        },

        /**
         * Error message about a method call made after destruction
         * 
         * @private
         */
        __destroyError: function() {
            throw new Error('This tooltip has been destroyed and cannot execute your method call.');
        },

        /**
         * Gather all information about dimensions and available space,
         * called before every repositioning
         * 
         * @private
         * @returns {object}
         */
        __geometry: function() {

            var self = this,
                $target = self._$origin,
                originIsArea = self._$origin.is('area');

            // if this._$origin is a map area, the target we'll need
            // the dimensions of is actually the image using the map,
            // not the area itself
            if (originIsArea) {

                var mapName = self._$origin.parent().attr('name');

                $target = $('img[usemap="#' + mapName + '"]');
            }

            var bcr = $target[0].getBoundingClientRect(),
                $document = $(env.window.document),
                $window = $(env.window),
                $parent = $target,
                // some useful properties of important elements
                geo = {
                    // available space for the tooltip, see down below
                    available: {
                        document: null,
                        window: null
                    },
                    document: {
                        size: {
                            height: $document.height(),
                            width: $document.width()
                        }
                    },
                    window: {
                        scroll: {
                            // the second ones are for IE compatibility
                            left: env.window.scrollX || env.window.document.documentElement.scrollLeft,
                            top: env.window.scrollY || env.window.document.documentElement.scrollTop
                        },
                        size: {
                            height: $window.height(),
                            width: $window.width()
                        }
                    },
                    origin: {
                        // the origin has a fixed lineage if itself or one of its
                        // ancestors has a fixed position
                        fixedLineage: false,
                        // relative to the document
                        offset: {},
                        size: {
                            height: bcr.bottom - bcr.top,
                            width: bcr.right - bcr.left
                        },
                        usemapImage: originIsArea ? $target[0] : null,
                        // relative to the window
                        windowOffset: {
                            bottom: bcr.bottom,
                            left: bcr.left,
                            right: bcr.right,
                            top: bcr.top
                        }
                    }
                };

            // if the element is a map area, some properties may need
            // to be recalculated
            if (originIsArea) {

                var shape = self._$origin.attr('shape'),
                    coords = self._$origin.attr('coords');

                if (coords) {

                    coords = coords.split(',');

                    $.map(coords, function(val, i) {
                        coords[i] = parseInt(val, 10);
                    });
                }

                // if the image itself is the area, nothing more to do
                if (shape != 'default') {

                    switch (shape) {

                        case 'circle':

                            var circleCenterLeft = coords[0],
                                circleCenterTop = coords[1],
                                circleRadius = coords[2],
                                areaTopOffset = circleCenterTop - circleRadius,
                                areaLeftOffset = circleCenterLeft - circleRadius;

                            geo.origin.size.height = circleRadius * 2;
                            geo.origin.size.width = geo.origin.size.height;

                            geo.origin.windowOffset.left += areaLeftOffset;
                            geo.origin.windowOffset.top += areaTopOffset;

                            break;

                        case 'rect':

                            var areaLeft = coords[0],
                                areaTop = coords[1],
                                areaRight = coords[2],
                                areaBottom = coords[3];

                            geo.origin.size.height = areaBottom - areaTop;
                            geo.origin.size.width = areaRight - areaLeft;

                            geo.origin.windowOffset.left += areaLeft;
                            geo.origin.windowOffset.top += areaTop;

                            break;

                        case 'poly':

                            var areaSmallestX = 0,
                                areaSmallestY = 0,
                                areaGreatestX = 0,
                                areaGreatestY = 0,
                                arrayAlternate = 'even';

                            for (var i = 0; i < coords.length; i++) {

                                var areaNumber = coords[i];

                                if (arrayAlternate == 'even') {

                                    if (areaNumber > areaGreatestX) {

                                        areaGreatestX = areaNumber;

                                        if (i === 0) {
                                            areaSmallestX = areaGreatestX;
                                        }
                                    }

                                    if (areaNumber < areaSmallestX) {
                                        areaSmallestX = areaNumber;
                                    }

                                    arrayAlternate = 'odd';
                                } else {
                                    if (areaNumber > areaGreatestY) {

                                        areaGreatestY = areaNumber;

                                        if (i == 1) {
                                            areaSmallestY = areaGreatestY;
                                        }
                                    }

                                    if (areaNumber < areaSmallestY) {
                                        areaSmallestY = areaNumber;
                                    }

                                    arrayAlternate = 'even';
                                }
                            }

                            geo.origin.size.height = areaGreatestY - areaSmallestY;
                            geo.origin.size.width = areaGreatestX - areaSmallestX;

                            geo.origin.windowOffset.left += areaSmallestX;
                            geo.origin.windowOffset.top += areaSmallestY;

                            break;
                    }
                }
            }

            // user callback through an event
            var edit = function(r) {
                geo.origin.size.height = r.height;
                geo.origin.windowOffset.left = r.left;
                geo.origin.windowOffset.top = r.top;
                geo.origin.size.width = r.width;
            };

            self._trigger({
                type: 'geometry',
                edit: edit,
                geometry: {
                    height: geo.origin.size.height,
                    left: geo.origin.windowOffset.left,
                    top: geo.origin.windowOffset.top,
                    width: geo.origin.size.width
                }
            });

            // calculate the remaining properties with what we got

            geo.origin.windowOffset.right = geo.origin.windowOffset.left + geo.origin.size.width;
            geo.origin.windowOffset.bottom = geo.origin.windowOffset.top + geo.origin.size.height;

            geo.origin.offset.left = geo.origin.windowOffset.left + geo.window.scroll.left;
            geo.origin.offset.top = geo.origin.windowOffset.top + geo.window.scroll.top;
            geo.origin.offset.bottom = geo.origin.offset.top + geo.origin.size.height;
            geo.origin.offset.right = geo.origin.offset.left + geo.origin.size.width;

            // the space that is available to display the tooltip relatively to the document
            geo.available.document = {
                bottom: {
                    height: geo.document.size.height - geo.origin.offset.bottom,
                    width: geo.document.size.width
                },
                left: {
                    height: geo.document.size.height,
                    width: geo.origin.offset.left
                },
                right: {
                    height: geo.document.size.height,
                    width: geo.document.size.width - geo.origin.offset.right
                },
                top: {
                    height: geo.origin.offset.top,
                    width: geo.document.size.width
                }
            };

            // the space that is available to display the tooltip relatively to the viewport
            // (the resulting values may be negative if the origin overflows the viewport)
            geo.available.window = {
                bottom: {
                    // the inner max is here to make sure the available height is no bigger
                    // than the viewport height (when the origin is off screen at the top).
                    // The outer max just makes sure that the height is not negative (when
                    // the origin overflows at the bottom).
                    height: Math.max(geo.window.size.height - Math.max(geo.origin.windowOffset.bottom, 0), 0),
                    width: geo.window.size.width
                },
                left: {
                    height: geo.window.size.height,
                    width: Math.max(geo.origin.windowOffset.left, 0)
                },
                right: {
                    height: geo.window.size.height,
                    width: Math.max(geo.window.size.width - Math.max(geo.origin.windowOffset.right, 0), 0)
                },
                top: {
                    height: Math.max(geo.origin.windowOffset.top, 0),
                    width: geo.window.size.width
                }
            };

            while ($parent[0].tagName.toLowerCase() != 'html') {

                if ($parent.css('position') == 'fixed') {
                    geo.origin.fixedLineage = true;
                    break;
                }

                $parent = $parent.parent();
            }

            return geo;
        },

        /**
         * Some options may need to be formated before being used
         * 
         * @returns {self}
         * @private
         */
        __optionsFormat: function() {

            if (typeof this.__options.animationDuration == 'number') {
                this.__options.animationDuration = [this.__options.animationDuration, this.__options.animationDuration];
            }

            if (typeof this.__options.delay == 'number') {
                this.__options.delay = [this.__options.delay, this.__options.delay];
            }

            if (typeof this.__options.delayTouch == 'number') {
                this.__options.delayTouch = [this.__options.delayTouch, this.__options.delayTouch];
            }

            if (typeof this.__options.theme == 'string') {
                this.__options.theme = [this.__options.theme];
            }

            // determine the future parent
            if (this.__options.parent === null) {
                this.__options.parent = $(env.window.document.body);
            } else if (typeof this.__options.parent == 'string') {
                this.__options.parent = $(this.__options.parent);
            }

            if (this.__options.trigger == 'hover') {

                this.__options.triggerOpen = {
                    mouseenter: true,
                    touchstart: true
                };

                this.__options.triggerClose = {
                    mouseleave: true,
                    originClick: true,
                    touchleave: true
                };
            } else if (this.__options.trigger == 'click') {

                this.__options.triggerOpen = {
                    click: true,
                    tap: true
                };

                this.__options.triggerClose = {
                    click: true,
                    tap: true
                };
            }

            // for the plugins
            this._trigger('options');

            return this;
        },

        /**
         * Schedules or cancels the garbage collector task
         *
         * @returns {self}
         * @private
         */
        __prepareGC: function() {

            var self = this;

            // in case the selfDestruction option has been changed by a method call
            if (self.__options.selfDestruction) {

                // the GC task
                self.__garbageCollector = setInterval(function() {

                    var now = new Date().getTime();

                    // forget the old events
                    self.__touchEvents = $.grep(self.__touchEvents, function(event) {
                        // 1 minute
                        return now - event.time > 60000;
                    });

                    // auto-destruct if the origin is gone
                    if (!bodyContains(self._$origin)) {

                        self.close(function() {
                            self.destroy();
                        });
                    }
                }, 20000);
            } else {
                clearInterval(self.__garbageCollector);
            }

            return self;
        },

        /**
         * Sets listeners on the origin if the open triggers require them.
         * Unlike the listeners set at opening time, these ones
         * remain even when the tooltip is closed. It has been made a
         * separate method so it can be called when the triggers are
         * changed in the options. Closing is handled in _open()
         * because of the bindings that may be needed on the tooltip
         * itself
         *
         * @returns {self}
         * @private
         */
        __prepareOrigin: function() {

            var self = this;

            // in case we're resetting the triggers
            self._$origin.off('.' + self.__namespace + '-triggerOpen');

            // if the device is touch capable, even if only mouse triggers
            // are asked, we need to listen to touch events to know if the mouse
            // events are actually emulated (so we can ignore them)
            if (env.hasTouchCapability) {

                self._$origin.on(
                    'touchstart.' + self.__namespace + '-triggerOpen ' +
                    'touchend.' + self.__namespace + '-triggerOpen ' +
                    'touchcancel.' + self.__namespace + '-triggerOpen',
                    function(event) {
                        self._touchRecordEvent(event);
                    }
                );
            }
            var eventNames;

            // mouse click and touch tap work the same way
            if (self.__options.triggerOpen.click || (self.__options.triggerOpen.tap && env.hasTouchCapability)) {

                eventNames = '';
                if (self.__options.triggerOpen.click) {
                    eventNames += 'click.' + self.__namespace + '-triggerOpen ';
                }
                if (self.__options.triggerOpen.tap && env.hasTouchCapability) {
                    eventNames += 'touchend.' + self.__namespace + '-triggerOpen';
                }

                self._$origin.on(eventNames, function(event) {
                    if (self._touchIsMeaningfulEvent(event)) {
                        self._open(event);
                    }
                });
            }

            // mouseenter and touch start work the same way
            if (self.__options.triggerOpen.mouseenter || (self.__options.triggerOpen.touchstart && env.hasTouchCapability)) {

                eventNames = '';
                if (self.__options.triggerOpen.mouseenter) {
                    eventNames += 'mouseenter.' + self.__namespace + '-triggerOpen ';
                }
                if (self.__options.triggerOpen.touchstart && env.hasTouchCapability) {
                    eventNames += 'touchstart.' + self.__namespace + '-triggerOpen';
                }

                self._$origin.on(eventNames, function(event) {
                    if (self._touchIsTouchEvent(event) || !self._touchIsEmulatedEvent(event)) {
                        self.__pointerIsOverOrigin = true;
                        self._openShortly(event);
                    }
                });
            }

            // info for the mouseleave/touchleave close triggers when they use a delay
            if (self.__options.triggerClose.mouseleave || (self.__options.triggerClose.touchleave && env.hasTouchCapability)) {

                eventNames = '';
                if (self.__options.triggerClose.mouseleave) {
                    eventNames += 'mouseleave.' + self.__namespace + '-triggerOpen ';
                }
                if (self.__options.triggerClose.touchleave && env.hasTouchCapability) {
                    eventNames += 'touchend.' + self.__namespace + '-triggerOpen touchcancel.' + self.__namespace + '-triggerOpen';
                }

                self._$origin.on(eventNames, function(event) {

                    if (self._touchIsMeaningfulEvent(event)) {
                        self.__pointerIsOverOrigin = false;
                    }
                });
            }

            return self;
        },

        /**
         * Do the things that need to be done only once after the tooltip
         * HTML element it has been created. It has been made a separate
         * method so it can be called when options are changed. Remember
         * that the tooltip may actually exist in the DOM before it is
         * opened, and present after it has been closed: it's the display
         * plugin that takes care of handling it.
         * 
         * @returns {self}
         * @private
         */
        __prepareTooltip: function() {

            var self = this,
                p = self.__options.interactive ? 'auto' : '';

            // this will be useful to know quickly if the tooltip is in
            // the DOM or not 
            self._$tooltip
                .attr('id', self.__namespace)
                .css({
                    // pointer events
                    'pointer-events': p,
                    zIndex: self.__options.zIndex
                });

            // themes
            // remove the old ones and add the new ones
            $.each(self.__previousThemes, function(i, theme) {
                self._$tooltip.removeClass(theme);
            });
            $.each(self.__options.theme, function(i, theme) {
                self._$tooltip.addClass(theme);
            });

            self.__previousThemes = $.merge([], self.__options.theme);

            return self;
        },

        /**
         * Handles the scroll on any of the parents of the origin (when the
         * tooltip is open)
         *
         * @param {object} event
         * @returns {self}
         * @private
         */
        __scrollHandler: function(event) {

            var self = this;

            if (self.__options.triggerClose.scroll) {
                self._close(event);
            } else {

                // if the origin or tooltip have been removed: do nothing, the tracker will
                // take care of it later
                if (bodyContains(self._$origin) && bodyContains(self._$tooltip)) {

                    var geo = null;

                    // if the scroll happened on the window
                    if (event.target === env.window.document) {

                        // if the origin has a fixed lineage, window scroll will have no
                        // effect on its position nor on the position of the tooltip
                        if (!self.__Geometry.origin.fixedLineage) {

                            // we don't need to do anything unless repositionOnScroll is true
                            // because the tooltip will already have moved with the window
                            // (and of course with the origin)
                            if (self.__options.repositionOnScroll) {
                                self.reposition(event);
                            }
                        }
                    }
                    // if the scroll happened on another parent of the tooltip, it means
                    // that it's in a scrollable area and now needs to have its position
                    // adjusted or recomputed, depending ont the repositionOnScroll
                    // option. Also, if the origin is partly hidden due to a parent that
                    // hides its overflow, we'll just hide (not close) the tooltip.
                    else {

                        geo = self.__geometry();

                        var overflows = false;

                        // a fixed position origin is not affected by the overflow hiding
                        // of a parent
                        if (self._$origin.css('position') != 'fixed') {

                            self.__$originParents.each(function(i, el) {

                                var $el = $(el),
                                    overflowX = $el.css('overflow-x'),
                                    overflowY = $el.css('overflow-y');

                                if (overflowX != 'visible' || overflowY != 'visible') {

                                    var bcr = el.getBoundingClientRect();

                                    if (overflowX != 'visible') {

                                        if (geo.origin.windowOffset.left < bcr.left || geo.origin.windowOffset.right > bcr.right) {
                                            overflows = true;
                                            return false;
                                        }
                                    }

                                    if (overflowY != 'visible') {

                                        if (geo.origin.windowOffset.top < bcr.top || geo.origin.windowOffset.bottom > bcr.bottom) {
                                            overflows = true;
                                            return false;
                                        }
                                    }
                                }

                                // no need to go further if fixed, for the same reason as above
                                if ($el.css('position') == 'fixed') {
                                    return false;
                                }
                            });
                        }

                        if (overflows) {
                            self._$tooltip.css('visibility', 'hidden');
                        } else {

                            self._$tooltip.css('visibility', 'visible');

                            // reposition
                            if (self.__options.repositionOnScroll) {
                                self.reposition(event);
                            }
                            // or just adjust offset
                            else {

                                // we have to use offset and not windowOffset because this way,
                                // only the scroll distance of the scrollable areas are taken into
                                // account (the scrolltop value of the main window must be
                                // ignored since the tooltip already moves with it)
                                var offsetLeft = geo.origin.offset.left - self.__Geometry.origin.offset.left,
                                    offsetTop = geo.origin.offset.top - self.__Geometry.origin.offset.top;

                                // add the offset to the position initially computed by the display plugin
                                self._$tooltip.css({
                                    left: self.__lastPosition.coord.left + offsetLeft,
                                    top: self.__lastPosition.coord.top + offsetTop
                                });
                            }
                        }
                    }

                    self._trigger({
                        type: 'scroll',
                        event: event,
                        geo: geo
                    });
                }
            }

            return self;
        },

        /**
         * Changes the state of the tooltip
         *
         * @param {string} state
         * @returns {self}
         * @private
         */
        __stateSet: function(state) {

            this.__state = state;

            this._trigger({
                type: 'state',
                state: state
            });

            return this;
        },

        /**
         * Clear appearance timeouts
         *
         * @returns {self}
         * @private
         */
        __timeoutsClear: function() {

            // there is only one possible open timeout: the delayed opening
            // when the mouseenter/touchstart open triggers are used
            clearTimeout(this.__timeouts.open);
            this.__timeouts.open = null;

            // ... but several close timeouts: the delayed closing when the
            // mouseleave close trigger is used and the timer option
            $.each(this.__timeouts.close, function(i, timeout) {
                clearTimeout(timeout);
            });
            this.__timeouts.close = [];

            return this;
        },

        /**
         * Start the tracker that will make checks at regular intervals
         * 
         * @returns {self}
         * @private
         */
        __trackerStart: function() {

            var self = this,
                $content = self._$tooltip.find('.tooltipster-content');

            // get the initial content size
            if (self.__options.trackTooltip) {
                self.__contentBcr = $content[0].getBoundingClientRect();
            }

            self.__tracker = setInterval(function() {

                // if the origin or tooltip elements have been removed.
                // Note: we could destroy the instance now if the origin has
                // been removed but we'll leave that task to our garbage collector
                if (!bodyContains(self._$origin) || !bodyContains(self._$tooltip)) {
                    self._close();
                }
                // if everything is alright
                else {

                    // compare the former and current positions of the origin to reposition
                    // the tooltip if need be
                    if (self.__options.trackOrigin) {

                        var g = self.__geometry(),
                            identical = false;

                        // compare size first (a change requires repositioning too)
                        if (areEqual(g.origin.size, self.__Geometry.origin.size)) {

                            // for elements that have a fixed lineage (see __geometry()), we track the
                            // top and left properties (relative to window)
                            if (self.__Geometry.origin.fixedLineage) {
                                if (areEqual(g.origin.windowOffset, self.__Geometry.origin.windowOffset)) {
                                    identical = true;
                                }
                            }
                            // otherwise, track total offset (relative to document)
                            else {
                                if (areEqual(g.origin.offset, self.__Geometry.origin.offset)) {
                                    identical = true;
                                }
                            }
                        }

                        if (!identical) {

                            // close the tooltip when using the mouseleave close trigger
                            // (see https://github.com/iamceege/tooltipster/pull/253)
                            if (self.__options.triggerClose.mouseleave) {
                                self._close();
                            } else {
                                self.reposition();
                            }
                        }
                    }

                    if (self.__options.trackTooltip) {

                        var currentBcr = $content[0].getBoundingClientRect();

                        if (currentBcr.height !== self.__contentBcr.height || currentBcr.width !== self.__contentBcr.width) {
                            self.reposition();
                            self.__contentBcr = currentBcr;
                        }
                    }
                }
            }, self.__options.trackerInterval);

            return self;
        },

        /**
         * Closes the tooltip (after the closing delay)
         * 
         * @param event
         * @param callback
         * @param force Set to true to override a potential refusal of the user's function
         * @returns {self}
         * @protected
         */
        _close: function(event, callback, force) {

            var self = this,
                ok = true;

            self._trigger({
                type: 'close',
                event: event,
                stop: function() {
                    ok = false;
                }
            });

            // a destroying tooltip (force == true) may not refuse to close
            if (ok || force) {

                // save the method custom callback and cancel any open method custom callbacks
                if (callback) self.__callbacks.close.push(callback);
                self.__callbacks.open = [];

                // clear open/close timeouts
                self.__timeoutsClear();

                var finishCallbacks = function() {

                    // trigger any close method custom callbacks and reset them
                    $.each(self.__callbacks.close, function(i, c) {
                        c.call(self, self, {
                            event: event,
                            origin: self._$origin[0]
                        });
                    });

                    self.__callbacks.close = [];
                };

                if (self.__state != 'closed') {

                    var necessary = true,
                        d = new Date(),
                        now = d.getTime(),
                        newClosingTime = now + self.__options.animationDuration[1];

                    // the tooltip may already already be disappearing, but if a new
                    // call to close() is made after the animationDuration was changed
                    // to 0 (for example), we ought to actually close it sooner than
                    // previously scheduled. In that case it should be noted that the
                    // browser will not adapt the animation duration to the new
                    // animationDuration that was set after the start of the closing
                    // animation.
                    // Note: the same thing could be considered at opening, but is not
                    // really useful since the tooltip is actually opened immediately
                    // upon a call to _open(). Since it would not make the opening
                    // animation finish sooner, its sole impact would be to trigger the
                    // state event and the open callbacks sooner than the actual end of
                    // the opening animation, which is not great.
                    if (self.__state == 'disappearing') {

                        if (newClosingTime > self.__closingTime && self.__options.animationDuration[1] > 0) { // in case closing is actually overdue because the script execution was suspended. See #679
                            necessary = false;
                        }
                    }

                    if (necessary) {

                        self.__closingTime = newClosingTime;

                        if (self.__state != 'disappearing') {
                            self.__stateSet('disappearing');
                        }

                        var finish = function() {

                            // stop the tracker
                            clearInterval(self.__tracker);

                            // a "beforeClose" option has been asked several times but would
                            // probably useless since the content element is still accessible
                            // via ::content(), and because people can always use listeners
                            // inside their content to track what's going on. For the sake of
                            // simplicity, this has been denied. Bur for the rare people who
                            // really need the option (for old browsers or for the case where
                            // detaching the content is actually destructive, for file or
                            // password inputs for example), this event will do the work.
                            self._trigger({
                                type: 'closing',
                                event: event
                            });

                            // unbind listeners which are no longer needed

                            self._$tooltip
                                .off('.' + self.__namespace + '-triggerClose')
                                .removeClass('tooltipster-dying');

                            // orientationchange, scroll and resize listeners
                            $(env.window).off('.' + self.__namespace + '-triggerClose');

                            // scroll listeners
                            self.__$originParents.each(function(i, el) {
                                $(el).off('scroll.' + self.__namespace + '-triggerClose');
                            });
                            // clear the array to prevent memory leaks
                            self.__$originParents = null;

                            $(env.window.document.body).off('.' + self.__namespace + '-triggerClose');

                            self._$origin.off('.' + self.__namespace + '-triggerClose');

                            self._off('dismissable');

                            // a plugin that would like to remove the tooltip from the
                            // DOM when closed should bind on this
                            self.__stateSet('closed');

                            // trigger event
                            self._trigger({
                                type: 'after',
                                event: event
                            });

                            // call our constructor custom callback function
                            if (self.__options.functionAfter) {
                                self.__options.functionAfter.call(self, self, {
                                    event: event,
                                    origin: self._$origin[0]
                                });
                            }

                            // call our method custom callbacks functions
                            finishCallbacks();
                        };

                        if (env.hasTransitions) {

                            self._$tooltip.css({
                                '-moz-animation-duration': self.__options.animationDuration[1] + 'ms',
                                '-ms-animation-duration': self.__options.animationDuration[1] + 'ms',
                                '-o-animation-duration': self.__options.animationDuration[1] + 'ms',
                                '-webkit-animation-duration': self.__options.animationDuration[1] + 'ms',
                                'animation-duration': self.__options.animationDuration[1] + 'ms',
                                'transition-duration': self.__options.animationDuration[1] + 'ms'
                            });

                            self._$tooltip
                                // clear both potential open and close tasks
                                .clearQueue()
                                .removeClass('tooltipster-show')
                                // for transitions only
                                .addClass('tooltipster-dying');

                            if (self.__options.animationDuration[1] > 0) {
                                self._$tooltip.delay(self.__options.animationDuration[1]);
                            }

                            self._$tooltip.queue(finish);
                        } else {

                            self._$tooltip
                                .stop()
                                .fadeOut(self.__options.animationDuration[1], finish);
                        }
                    }
                }
                // if the tooltip is already closed, we still need to trigger
                // the method custom callbacks
                else {
                    finishCallbacks();
                }
            }

            return self;
        },

        /**
         * For internal use by plugins, if needed
         * 
         * @returns {self}
         * @protected
         */
        _off: function() {
            this.__$emitterPrivate.off.apply(this.__$emitterPrivate, Array.prototype.slice.apply(arguments));
            return this;
        },

        /**
         * For internal use by plugins, if needed
         *
         * @returns {self}
         * @protected
         */
        _on: function() {
            this.__$emitterPrivate.on.apply(this.__$emitterPrivate, Array.prototype.slice.apply(arguments));
            return this;
        },

        /**
         * For internal use by plugins, if needed
         *
         * @returns {self}
         * @protected
         */
        _one: function() {
            this.__$emitterPrivate.one.apply(this.__$emitterPrivate, Array.prototype.slice.apply(arguments));
            return this;
        },

        /**
         * Opens the tooltip right away.
         *
         * @param event
         * @param callback Will be called when the opening animation is over
         * @returns {self}
         * @protected
         */
        _open: function(event, callback) {

            var self = this;

            // if the destruction process has not begun and if this was not
            // triggered by an unwanted emulated click event
            if (!self.__destroying) {

                // check that the origin is still in the DOM
                if (bodyContains(self._$origin) && self.__enabled ) {
                    // if the tooltip is enabled

                    var ok = true;

                    // if the tooltip is not open yet, we need to call functionBefore.
                    // otherwise we can jst go on
                    if (self.__state == 'closed') {

                        // trigger an event. The event.stop function allows the callback
                        // to prevent the opening of the tooltip
                        self._trigger({
                            type: 'before',
                            event: event,
                            stop: function() {
                                ok = false;
                            }
                        });

                        if (ok && self.__options.functionBefore) {

                            // call our custom function before continuing
                            ok = self.__options.functionBefore.call(self, self, {
                                event: event,
                                origin: self._$origin[0]
                            });
                        }
                    }

                    if (ok !== false) {

                        // if there is some content
                        if (self.__Content !== null) {

                        	var timeout;

                            // save the method callback and cancel close method callbacks
                            if (callback) {
                                self.__callbacks.open.push(callback);
                            }
                            self.__callbacks.close = [];

                            // get rid of any appearance timeouts
                            self.__timeoutsClear();

                            var extraTime,
                                finish = function() {

                                    if (self.__state != 'stable') {
                                        self.__stateSet('stable');
                                    }

                                    // trigger any open method custom callbacks and reset them
                                    $.each(self.__callbacks.open, function(i, c) {
                                        c.call(self, self, {
                                            origin: self._$origin[0],
                                            tooltip: self._$tooltip[0]
                                        });
                                    });

                                    self.__callbacks.open = [];
                                };

                            // if the tooltip is already open
                            if (self.__state !== 'closed') {

                                // the timer (if any) will start (or restart) right now
                                extraTime = 0;

                                // if it was disappearing, cancel that
                                if (self.__state === 'disappearing') {

                                    self.__stateSet('appearing');

                                    if (env.hasTransitions) {

                                        self._$tooltip
                                            .clearQueue()
                                            .removeClass('tooltipster-dying')
                                            .addClass('tooltipster-show');

                                        if (self.__options.animationDuration[0] > 0) {
                                            self._$tooltip.delay(self.__options.animationDuration[0]);
                                        }

                                        self._$tooltip.queue(finish);
                                    } else {
                                        // in case the tooltip was currently fading out, bring it back
                                        // to life
                                        self._$tooltip
                                            .stop()
                                            .fadeIn(finish);
                                    }
                                }
                                // if the tooltip is already open, we still need to trigger the method
                                // custom callback
                                else if (self.__state == 'stable') {
                                    finish();
                                }
                            }
                            // if the tooltip isn't already open, open it
                            else {

                                // a plugin must bind on this and store the tooltip in this._$tooltip
                                self.__stateSet('appearing');

                                // the timer (if any) will start when the tooltip has fully appeared
                                // after its transition
                                extraTime = self.__options.animationDuration[0];

                                // insert the content inside the tooltip
                                self.__contentInsert();

                                // reposition the tooltip and attach to the DOM
                                self.reposition(event, true);

                                // animate in the tooltip. If the display plugin wants no css
                                // animations, it may override the animation option with a
                                // dummy value that will produce no effect
                                if (env.hasTransitions) {

                                    // note: there seems to be an issue with start animations which
                                    // are randomly not played on fast devices in both Chrome and FF,
                                    // couldn't find a way to solve it yet. It seems that applying
                                    // the classes before appending to the DOM helps a little, but
                                    // it messes up some CSS transitions. The issue almost never
                                    // happens when delay[0]==0 though
                                    self._$tooltip
                                        .addClass('tooltipster-' + self.__options.animation)
                                        .addClass('tooltipster-initial')
                                        .css({
                                            '-moz-animation-duration': self.__options.animationDuration[0] + 'ms',
                                            '-ms-animation-duration': self.__options.animationDuration[0] + 'ms',
                                            '-o-animation-duration': self.__options.animationDuration[0] + 'ms',
                                            '-webkit-animation-duration': self.__options.animationDuration[0] + 'ms',
                                            'animation-duration': self.__options.animationDuration[0] + 'ms',
                                            'transition-duration': self.__options.animationDuration[0] + 'ms'
                                        });

                                    setTimeout(
                                        function() {

                                            // a quick hover may have already triggered a mouseleave
                                            if (self.__state != 'closed') {

                                                self._$tooltip
                                                    .addClass('tooltipster-show')
                                                    .removeClass('tooltipster-initial');

                                                if (self.__options.animationDuration[0] > 0) {
                                                    self._$tooltip.delay(self.__options.animationDuration[0]);
                                                }

                                                self._$tooltip.queue(finish);
                                            }
                                        },
                                        0
                                    );
                                } else {

                                    // old browsers will have to live with this
                                    self._$tooltip
                                        .css('display', 'none')
                                        .fadeIn(self.__options.animationDuration[0], finish);
                                }

                                // checks if the origin is removed while the tooltip is open
                                self.__trackerStart();

                                // NOTE: the listeners below have a '-triggerClose' namespace
                                // because we'll remove them when the tooltip closes (unlike
                                // the '-triggerOpen' listeners). So some of them are actually
                                // not about close triggers, rather about positioning.

                                $(env.window)
                                    // reposition on resize
                                    .on('resize.' + self.__namespace + '-triggerClose', function(e) {

                                        var $ae = $(document.activeElement);

                                        // reposition only if the resize event was not triggered upon the opening
                                        // of a virtual keyboard due to an input field being focused within the tooltip
                                        // (otherwise the repositioning would lose the focus)
                                        if ((!$ae.is('input') && !$ae.is('textarea')) ||
                                            !$.contains(self._$tooltip[0], $ae[0])
                                        ) {
                                            self.reposition(e);
                                        }
                                    })
                                    // same as below for parents
                                    .on('scroll.' + self.__namespace + '-triggerClose', function(e) {
                                        self.__scrollHandler(e);
                                    });

                                self.__$originParents = self._$origin.parents();

                                // scrolling may require the tooltip to be moved or even
                                // repositioned in some cases
                                self.__$originParents.each(function(i, parent) {

                                    $(parent).on('scroll.' + self.__namespace + '-triggerClose', function(e) {
                                        self.__scrollHandler(e);
                                    });
                                });

                                if (self.__options.triggerClose.mouseleave ||
                                    (self.__options.triggerClose.touchleave && env.hasTouchCapability)
                                ) {

                                    // we use an event to allow users/plugins to control when the mouseleave/touchleave
                                    // close triggers will come to action. It allows to have more triggering elements
                                    // than just the origin and the tooltip for example, or to cancel/delay the closing,
                                    // or to make the tooltip interactive even if it wasn't when it was open, etc.
                                    self._on('dismissable', function(event) {

                                        if (event.dismissable) {

                                            if (event.delay) {

                                                timeout = setTimeout(function() {
                                                    // event.event may be undefined
                                                    self._close(event.event);
                                                }, event.delay);

                                                self.__timeouts.close.push(timeout);
                                            } else {
                                                self._close(event);
                                            }
                                        } else {
                                            clearTimeout(timeout);
                                        }
                                    });

                                    // now set the listeners that will trigger 'dismissable' events
                                    var $elements = self._$origin,
                                        eventNamesIn = '',
                                        eventNamesOut = '';

                                    timeout = null;

                                    // if we have to allow interaction, bind on the tooltip too
                                    if (self.__options.interactive) {
                                        $elements = $elements.add(self._$tooltip);
                                    }

                                    if (self.__options.triggerClose.mouseleave) {
                                        eventNamesIn += 'mouseenter.' + self.__namespace + '-triggerClose ';
                                        eventNamesOut += 'mouseleave.' + self.__namespace + '-triggerClose ';
                                    }
                                    if (self.__options.triggerClose.touchleave && env.hasTouchCapability) {
                                        eventNamesIn += 'touchstart.' + self.__namespace + '-triggerClose';
                                        eventNamesOut += 'touchend.' + self.__namespace + '-triggerClose touchcancel.' + self.__namespace + '-triggerClose';
                                    }

                                    $elements
                                        // close after some time spent outside of the elements
                                        .on(eventNamesOut, function(event) {

                                            // it's ok if the touch gesture ended up to be a swipe,
                                            // it's still a "touch leave" situation
                                            if (self._touchIsTouchEvent(event) ||
                                                !self._touchIsEmulatedEvent(event)
                                            ) {

                                                var delay = (event.type == 'mouseleave') ?
                                                    self.__options.delay :
                                                    self.__options.delayTouch;

                                                self._trigger({
                                                    delay: delay[1],
                                                    dismissable: true,
                                                    event: event,
                                                    type: 'dismissable'
                                                });
                                            }
                                        })
                                        // suspend the mouseleave timeout when the pointer comes back
                                        // over the elements
                                        .on(eventNamesIn, function(event) {

                                            // it's also ok if the touch event is a swipe gesture
                                            if (self._touchIsTouchEvent(event) ||
                                                !self._touchIsEmulatedEvent(event)
                                            ) {
                                                self._trigger({
                                                    dismissable: false,
                                                    event: event,
                                                    type: 'dismissable'
                                                });
                                            }
                                        });
                                }

                                // close the tooltip when the origin gets a mouse click (common behavior of
                                // native tooltips)
                                if (self.__options.triggerClose.originClick) {

                                    self._$origin.on('click.' + self.__namespace + '-triggerClose', function(event) {

                                        // we could actually let a tap trigger this but this feature just
                                        // does not make sense on touch devices
                                        if (!self._touchIsTouchEvent(event) &&
                                            !self._touchIsEmulatedEvent(event)
                                        ) {
                                            self._close(event);
                                        }
                                    });
                                }

                                // set the same bindings for click and touch on the body to close the tooltip
                                if (self.__options.triggerClose.click ||
                                    (self.__options.triggerClose.tap && env.hasTouchCapability)
                                ) {

                                    // don't set right away since the click/tap event which triggered this method
                                    // (if it was a click/tap) is going to bubble up to the body, we don't want it
                                    // to close the tooltip immediately after it opened
                                    setTimeout(function() {

                                        if (self.__state != 'closed') {

                                            var eventNames = '',
                                                $body = $(env.window.document.body);

                                            if (self.__options.triggerClose.click) {
                                                eventNames += 'click.' + self.__namespace + '-triggerClose ';
                                            }
                                            if (self.__options.triggerClose.tap && env.hasTouchCapability) {
                                                eventNames += 'touchend.' + self.__namespace + '-triggerClose';
                                            }

                                            $body.on(eventNames, function(event) {

                                                if (self._touchIsMeaningfulEvent(event)) {

                                                    self._touchRecordEvent(event);

                                                    if (!self.__options.interactive || !$.contains(self._$tooltip[0], event.target)) {
                                                        self._close(event);
                                                    }
                                                }
                                            });

                                            // needed to detect and ignore swiping
                                            if (self.__options.triggerClose.tap && env.hasTouchCapability) {

                                                $body.on('touchstart.' + self.__namespace + '-triggerClose', function(event) {
                                                    self._touchRecordEvent(event);
                                                });
                                            }
                                        }
                                    }, 0);
                                }

                                self._trigger('ready');

                                // call our custom callback
                                if (self.__options.functionReady) {
                                    self.__options.functionReady.call(self, self, {
                                        origin: self._$origin[0],
                                        tooltip: self._$tooltip[0]
                                    });
                                }
                            }

                            // if we have a timer set, let the countdown begin
                            if (self.__options.timer > 0) {

                                timeout = setTimeout(function() {
                                    self._close();
                                }, self.__options.timer + extraTime);

                                self.__timeouts.close.push(timeout);
                            }
                        }
                    }
                }
            }

            return self;
        },

        /**
         * When using the mouseenter/touchstart open triggers, this function will
         * schedule the opening of the tooltip after the delay, if there is one
         *
         * @param event
         * @returns {self}
         * @protected
         */
        _openShortly: function(event) {

            var self = this,
                ok = true;

            if (self.__state != 'stable' && self.__state != 'appearing') {

                // if a timeout is not already running
                if (!self.__timeouts.open) {

                    self._trigger({
                        type: 'start',
                        event: event,
                        stop: function() {
                            ok = false;
                        }
                    });

                    if (ok) {

                        var delay = (event.type.indexOf('touch') == 0) ?
                            self.__options.delayTouch :
                            self.__options.delay;

                        if (delay[0]) {

                            self.__timeouts.open = setTimeout(function() {

                                self.__timeouts.open = null;

                                // open only if the pointer (mouse or touch) is still over the origin.
                                // The check on the "meaningful event" can only be made here, after some
                                // time has passed (to know if the touch was a swipe or not)
                                if (self.__pointerIsOverOrigin && self._touchIsMeaningfulEvent(event)) {

                                    // signal that we go on
                                    self._trigger('startend');

                                    self._open(event);
                                } else {
                                    // signal that we cancel
                                    self._trigger('startcancel');
                                }
                            }, delay[0]);
                        } else {
                            // signal that we go on
                            self._trigger('startend');

                            self._open(event);
                        }
                    }
                }
            }

            return self;
        },

        /**
         * Meant for plugins to get their options
         * 
         * @param {string} pluginName The name of the plugin that asks for its options
         * @param {object} defaultOptions The default options of the plugin
         * @returns {object} The options
         * @protected
         */
        _optionsExtract: function(pluginName, defaultOptions) {

            var self = this,
                options = $.extend(true, {}, defaultOptions);

            // if the plugin options were isolated in a property named after the
            // plugin, use them (prevents conflicts with other plugins)
            var pluginOptions = self.__options[pluginName];

            // if not, try to get them as regular options
            if (!pluginOptions) {

                pluginOptions = {};

                $.each(defaultOptions, function(optionName) {

                    var o = self.__options[optionName];

                    if (o !== undefined) {
                        pluginOptions[optionName] = o;
                    }
                });
            }

            // let's merge the default options and the ones that were provided. We'd want
            // to do a deep copy but not let jQuery merge arrays, so we'll do a shallow
            // extend on two levels, that will be enough if options are not more than 1
            // level deep
            $.each(options, function(optionName, value) {

                if (pluginOptions[optionName] !== undefined) {

                    if ((typeof value == 'object' &&
                            !(value instanceof Array) &&
                            value != null
                        ) &&
                        (typeof pluginOptions[optionName] == 'object' &&
                            !(pluginOptions[optionName] instanceof Array) &&
                            pluginOptions[optionName] != null
                        )
                    ) {
                        $.extend(options[optionName], pluginOptions[optionName]);
                    } else {
                        options[optionName] = pluginOptions[optionName];
                    }
                }
            });

            return options;
        },

        /**
         * Used at instantiation of the plugin, or afterwards by plugins that activate themselves
         * on existing instances
         * 
         * @param {object} pluginName
         * @returns {self}
         * @protected
         */
        _plug: function(pluginName) {

            var plugin = $.tooltipster._plugin(pluginName);

            if (plugin) {

                // if there is a constructor for instances
                if (plugin.instance) {

                    // proxy non-private methods on the instance to allow new instance methods
                    $.tooltipster.__bridge(plugin.instance, this, plugin.name);
                }
            } else {
                throw new Error('The "' + pluginName + '" plugin is not defined');
            }

            return this;
        },

        /**
         * This will return true if the event is a mouse event which was
         * emulated by the browser after a touch event. This allows us to
         * really dissociate mouse and touch triggers.
         * 
         * There is a margin of error if a real mouse event is fired right
         * after (within the delay shown below) a touch event on the same
         * element, but hopefully it should not happen often.
         * 
         * @returns {boolean}
         * @protected
         */
        _touchIsEmulatedEvent: function(event) {

            var isEmulated = false,
                now = new Date().getTime();

            for (var i = this.__touchEvents.length - 1; i >= 0; i--) {

                var e = this.__touchEvents[i];

                // delay, in milliseconds. It's supposed to be 300ms in
                // most browsers (350ms on iOS) to allow a double tap but
                // can be less (check out FastClick for more info)
                if (now - e.time < 500) {

                    if (e.target === event.target) {
                        isEmulated = true;
                    }
                } else {
                    break;
                }
            }

            return isEmulated;
        },

        /**
         * Returns false if the event was an emulated mouse event or
         * a touch event involved in a swipe gesture.
         * 
         * @param {object} event
         * @returns {boolean}
         * @protected
         */
        _touchIsMeaningfulEvent: function(event) {
            return (
                (this._touchIsTouchEvent(event) && !this._touchSwiped(event.target)) ||
                (!this._touchIsTouchEvent(event) && !this._touchIsEmulatedEvent(event))
            );
        },

        /**
         * Checks if an event is a touch event
         * 
         * @param {object} event
         * @returns {boolean}
         * @protected
         */
        _touchIsTouchEvent: function(event) {
            return event.type.indexOf('touch') == 0;
        },

        /**
         * Store touch events for a while to detect swiping and emulated mouse events
         * 
         * @param {object} event
         * @returns {self}
         * @protected
         */
        _touchRecordEvent: function(event) {

            if (this._touchIsTouchEvent(event)) {
                event.time = new Date().getTime();
                this.__touchEvents.push(event);
            }

            return this;
        },

        /**
         * Returns true if a swipe happened after the last touchstart event fired on
         * event.target.
         * 
         * We need to differentiate a swipe from a tap before we let the event open
         * or close the tooltip. A swipe is when a touchmove (scroll) event happens
         * on the body between the touchstart and the touchend events of an element.
         * 
         * @param {object} target The HTML element that may have triggered the swipe
         * @returns {boolean}
         * @protected
         */
        _touchSwiped: function(target) {

            var swiped = false;

            for (var i = this.__touchEvents.length - 1; i >= 0; i--) {

                var e = this.__touchEvents[i];

                if (e.type == 'touchmove') {
                    swiped = true;
                    break;
                } else if (
                    e.type == 'touchstart' &&
                    target === e.target
                ) {
                    break;
                }
            }

            return swiped;
        },

        /**
         * Triggers an event on the instance emitters
         * 
         * @returns {self}
         * @protected
         */
        _trigger: function() {

            var args = Array.prototype.slice.apply(arguments);

            if (typeof args[0] == 'string') {
                args[0] = {
                    type: args[0]
                };
            }

            // add properties to the event
            args[0].instance = this;
            args[0].origin = this._$origin ? this._$origin[0] : null;
            args[0].tooltip = this._$tooltip ? this._$tooltip[0] : null;

            // note: the order of emitters matters
            this.__$emitterPrivate.trigger.apply(this.__$emitterPrivate, args);
            $.tooltipster._trigger.apply($.tooltipster, args);
            this.__$emitterPublic.trigger.apply(this.__$emitterPublic, args);

            return this;
        },

        /**
         * Deactivate a plugin on this instance
         * 
         * @returns {self}
         * @protected
         */
        _unplug: function(pluginName) {

            var self = this;

            // if the plugin has been activated on this instance
            if (self[pluginName]) {

                var plugin = $.tooltipster._plugin(pluginName);

                // if there is a constructor for instances
                if (plugin.instance) {

                    // unbridge
                    $.each(plugin.instance, function(methodName) {

                        // if the method exists (privates methods do not) and comes indeed from
                        // this plugin (may be missing or come from a conflicting plugin).
                        if (self[methodName] &&
                            self[methodName].bridged === self[pluginName]
                        ) {
                            delete self[methodName];
                        }
                    });
                }

                // destroy the plugin
                if (self[pluginName].__destroy) {
                    self[pluginName].__destroy();
                }

                // remove the reference to the plugin instance
                delete self[pluginName];
            }

            return self;
        },

        /**
         * @see self::_close
         * @returns {self}
         * @public
         */
        close: function(callback) {

            if (!this.__destroyed) {
                this._close(null, callback);
            } else {
                this.__destroyError();
            }

            return this;
        },

        /**
         * Sets or gets the content of the tooltip
         * 
         * @returns {mixed|self}
         * @public
         */
        content: function(content) {

            var self = this;

            // getter method
            if (content === undefined) {
                return self.__Content;
            }
            // setter method
            else {

                if (!self.__destroyed) {

                    // change the content
                    self.__contentSet(content);

                    if (self.__Content !== null) {

                        // update the tooltip if it is open
                        if (self.__state !== 'closed') {

                            // reset the content in the tooltip
                            self.__contentInsert();

                            // reposition and resize the tooltip
                            self.reposition();

                            // if we want to play a little animation showing the content changed
                            if (self.__options.updateAnimation) {

                                if (env.hasTransitions) {

                                    // keep the reference in the local scope
                                    var animation = self.__options.updateAnimation;

                                    self._$tooltip.addClass('tooltipster-update-' + animation);

                                    // remove the class after a while. The actual duration of the
                                    // update animation may be shorter, it's set in the CSS rules
                                    setTimeout(function() {

                                        if (self.__state != 'closed') {

                                            self._$tooltip.removeClass('tooltipster-update-' + animation);
                                        }
                                    }, 1000);
                                } else {
                                    self._$tooltip.fadeTo(200, 0.5, function() {
                                        if (self.__state != 'closed') {
                                            self._$tooltip.fadeTo(200, 1);
                                        }
                                    });
                                }
                            }
                        }
                    } else {
                        self._close();
                    }
                } else {
                    self.__destroyError();
                }

                return self;
            }
        },

        /**
         * Destroys the tooltip
         * 
         * @returns {self}
         * @public
         */
        destroy: function() {

            var self = this;

            if (!self.__destroyed) {

                if (self.__state != 'closed') {

                    // no closing delay
                    self.option('animationDuration', 0)
                        // force closing
                        ._close(null, null, true);
                } else {
                    // there might be an open timeout still running
                    self.__timeoutsClear();
                }

                // send event
                self._trigger('destroy');

                self.__destroyed = true;

                self._$origin
                    .removeData(self.__namespace)
                    // remove the open trigger listeners
                    .off('.' + self.__namespace + '-triggerOpen');

                // remove the touch listener
                $(env.window.document.body).off('.' + self.__namespace + '-triggerOpen');

                var ns = self._$origin.data('tooltipster-ns');

                // if the origin has been removed from DOM, its data may
                // well have been destroyed in the process and there would
                // be nothing to clean up or restore
                if (ns) {

                    // if there are no more tooltips on this element
                    if (ns.length === 1) {

                        // optional restoration of a title attribute
                        var title = null;
                        if (self.__options.restoration == 'previous') {
                            title = self._$origin.data('tooltipster-initialTitle');
                        } else if (self.__options.restoration == 'current') {

                            // old school technique to stringify when outerHTML is not supported
                            title = (typeof self.__Content == 'string') ?
                                self.__Content :
                                $('<div></div>').append(self.__Content).html();
                        }

                        if (title) {
                            self._$origin.attr('title', title);
                        }

                        // final cleaning

                        self._$origin.removeClass('tooltipstered');

                        self._$origin
                            .removeData('tooltipster-ns')
                            .removeData('tooltipster-initialTitle');
                    } else {
                        // remove the instance namespace from the list of namespaces of
                        // tooltips present on the element
                        ns = $.grep(ns, function(el) {
                            return el !== self.__namespace;
                        });
                        self._$origin.data('tooltipster-ns', ns);
                    }
                }

                // last event
                self._trigger('destroyed');

                // unbind private and public event listeners
                self._off();
                self.off();

                // remove external references, just in case
                self.__Content = null;
                self.__$emitterPrivate = null;
                self.__$emitterPublic = null;
                self.__options.parent = null;
                self._$origin = null;
                self._$tooltip = null;

                // make sure the object is no longer referenced in there to prevent
                // memory leaks
                $.tooltipster.__instancesLatestArr = $.grep($.tooltipster.__instancesLatestArr, function(el) {
                    return self !== el;
                });

                clearInterval(self.__garbageCollector);
            } else {
                self.__destroyError();
            }

            // we return the scope rather than true so that the call to
            // .tooltipster('destroy') actually returns the matched elements
            // and applies to all of them
            return self;
        },

        /**
         * Disables the tooltip
         * 
         * @returns {self}
         * @public
         */
        disable: function() {

            if (!this.__destroyed) {

                // close first, in case the tooltip would not disappear on
                // its own (no close trigger)
                this._close();
                this.__enabled = false;

                return this;
            } else {
                this.__destroyError();
            }

            return this;
        },

        /**
         * Returns the HTML element of the origin
         *
         * @returns {self}
         * @public
         */
        elementOrigin: function() {

            if (!this.__destroyed) {
                return this._$origin[0];
            } else {
                this.__destroyError();
            }
        },

        /**
         * Returns the HTML element of the tooltip
         *
         * @returns {self}
         * @public
         */
        elementTooltip: function() {
            return this._$tooltip ? this._$tooltip[0] : null;
        },

        /**
         * Enables the tooltip
         * 
         * @returns {self}
         * @public
         */
        enable: function() {
            this.__enabled = true;
            return this;
        },

        /**
         * Alias, deprecated in 4.0.0
         * 
         * @param {function} callback
         * @returns {self}
         * @public
         */
        hide: function(callback) {
            return this.close(callback);
        },

        /**
         * Returns the instance
         * 
         * @returns {self}
         * @public
         */
        instance: function() {
            return this;
        },

        /**
         * For public use only, not to be used by plugins (use ::_off() instead)
         * 
         * @returns {self}
         * @public
         */
        off: function() {

            if (!this.__destroyed) {
                this.__$emitterPublic.off.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments));
            }

            return this;
        },

        /**
         * For public use only, not to be used by plugins (use ::_on() instead)
         *
         * @returns {self}
         * @public
         */
        on: function() {

            if (!this.__destroyed) {
                this.__$emitterPublic.on.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments));
            } else {
                this.__destroyError();
            }

            return this;
        },

        /**
         * For public use only, not to be used by plugins
         *
         * @returns {self}
         * @public
         */
        one: function() {

            if (!this.__destroyed) {
                this.__$emitterPublic.one.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments));
            } else {
                this.__destroyError();
            }

            return this;
        },

        /**
         * @see self::_open
         * @returns {self}
         * @public
         */
        open: function(callback) {

            if (!this.__destroyed) {
                this._open(null, callback);
            } else {
                this.__destroyError();
            }

            return this;
        },

        /**
         * Get or set options. For internal use and advanced users only.
         * 
         * @param {string} o Option name
         * @param {mixed} val optional A new value for the option
         * @return {mixed|self} If val is omitted, the value of the option
         * is returned, otherwise the instance itself is returned
         * @public
         */
        option: function(o, val) {

            // getter
            if (val === undefined) {
                return this.__options[o];
            }
            // setter
            else {

                if (!this.__destroyed) {

                    // change value
                    this.__options[o] = val;

                    // format
                    this.__optionsFormat();

                    // re-prepare the triggers if needed
                    if ($.inArray(o, ['trigger', 'triggerClose', 'triggerOpen']) >= 0) {
                        this.__prepareOrigin();
                    }

                    if (o === 'selfDestruction') {
                        this.__prepareGC();
                    }
                } else {
                    this.__destroyError();
                }

                return this;
            }
        },

        /**
         * This method is in charge of setting the position and size properties of the tooltip.
         * All the hard work is delegated to the display plugin.
         * Note: The tooltip may be detached from the DOM at the moment the method is called 
         * but must be attached by the end of the method call.
         * 
         * @param {object} event For internal use only. Defined if an event such as
         * window resizing triggered the repositioning
         * @param {boolean} tooltipIsDetached For internal use only. Set this to true if you
         * know that the tooltip not being in the DOM is not an issue (typically when the
         * tooltip element has just been created but has not been added to the DOM yet).
         * @returns {self}
         * @public
         */
        reposition: function(event, tooltipIsDetached) {

            var self = this;

            if (!self.__destroyed) {

                // if the tooltip is still open and the origin is still in the DOM
                if (self.__state != 'closed' && bodyContains(self._$origin)) {

                    // if the tooltip has not been removed from DOM manually (or if it
                    // has been detached on purpose)
                    if (tooltipIsDetached || bodyContains(self._$tooltip)) {

                        if (!tooltipIsDetached) {
                            // detach in case the tooltip overflows the window and adds
                            // scrollbars to it, so __geometry can be accurate
                            self._$tooltip.detach();
                        }

                        // refresh the geometry object before passing it as a helper
                        self.__Geometry = self.__geometry();

                        // let a plugin fo the rest
                        self._trigger({
                            type: 'reposition',
                            event: event,
                            helper: {
                                geo: self.__Geometry
                            }
                        });
                    }
                }
            } else {
                self.__destroyError();
            }

            return self;
        },

        /**
         * Alias, deprecated in 4.0.0
         *
         * @param callback
         * @returns {self}
         * @public
         */
        show: function(callback) {
            return this.open(callback);
        },

        /**
         * Returns some properties about the instance
         * 
         * @returns {object}
         * @public
         */
        status: function() {

            return {
                destroyed: this.__destroyed,
                enabled: this.__enabled,
                open: this.__state !== 'closed',
                state: this.__state
            };
        },

        /**
         * For public use only, not to be used by plugins
         *
         * @returns {self}
         * @public
         */
        triggerHandler: function() {

            if (!this.__destroyed) {
                this.__$emitterPublic.triggerHandler.apply(this.__$emitterPublic, Array.prototype.slice.apply(arguments));
            } else {
                this.__destroyError();
            }

            return this;
        }
    };

    $.fn.tooltipster = function() {

        // for using in closures
        var args = Array.prototype.slice.apply(arguments),
            // common mistake: an HTML element can't be in several tooltips at the same time
            contentCloningWarning = 'You are using a single HTML element as content for several tooltips. You probably want to set the contentCloning option to TRUE.';

        // this happens with $(sel).tooltipster(...) when $(sel) does not match anything
        if (this.length === 0) {

            // still chainable
            return this;
        }
        // this happens when calling $(sel).tooltipster('methodName or options')
        // where $(sel) matches one or more elements
        else {

            // method calls
            if (typeof args[0] === 'string') {

                var v = '#*$~&';

                this.each(function() {

                    // retrieve the namepaces of the tooltip(s) that exist on that element.
                    // We will interact with the first tooltip only.
                    var ns = $(this).data('tooltipster-ns'),
                        // self represents the instance of the first tooltipster plugin
                        // associated to the current HTML object of the loop
                        self = ns ? $(this).data(ns[0]) : null;

                    // if the current element holds a tooltipster instance
                    if (self) {

                        var resp;
                        if (typeof self[args[0]] === 'function') {

                            if (this.length > 1 &&
                                args[0] == 'content' &&
                                (args[1] instanceof $ ||
                                    (typeof args[1] == 'object' && args[1] != null && args[1].tagName)
                                ) &&
                                !self.__options.contentCloning &&
                                self.__options.debug
                            ) {
                                console.log(contentCloningWarning);
                            }

                            // note : args[1] and args[2] may not be defined
                            resp = self[args[0]](args[1], args[2]);
                        } else {
                            throw new Error('Unknown method "' + args[0] + '"');
                        }

                        // if the function returned anything other than the instance
                        // itself (which implies chaining, except for the `instance` method)
                        if (resp !== self || args[0] === 'instance') {

                            v = resp;

                            // return false to stop .each iteration on the first element
                            // matched by the selector
                            return false;
                        }
                    } else {
                        throw new Error('You called Tooltipster\'s "' + args[0] + '" method on an uninitialized element');
                    }
                });

                return (v !== '#*$~&') ? v : this;
            }
            // first argument is undefined or an object: the tooltip is initializing
            else {

                // reset the array of last initialized objects
                $.tooltipster.__instancesLatestArr = [];

                // is there a defined value for the multiple option in the options object ?
                var multipleIsSet = args[0] && args[0].multiple !== undefined,
                    // if the multiple option is set to true, or if it's not defined but
                    // set to true in the defaults
                    multiple = (multipleIsSet && args[0].multiple) || (!multipleIsSet && defaults.multiple),
                    // same for content
                    contentIsSet = args[0] && args[0].content !== undefined,
                    content = (contentIsSet && args[0].content) || (!contentIsSet && defaults.content),
                    // same for contentCloning
                    contentCloningIsSet = args[0] && args[0].contentCloning !== undefined,
                    contentCloning =
                    (contentCloningIsSet && args[0].contentCloning) ||
                    (!contentCloningIsSet && defaults.contentCloning),
                    // same for debug
                    debugIsSet = args[0] && args[0].debug !== undefined,
                    debug = (debugIsSet && args[0].debug) || (!debugIsSet && defaults.debug);

                if (this.length > 1 &&
                    (content instanceof $ ||
                        (typeof content == 'object' && content != null && content.tagName)
                    ) &&
                    !contentCloning &&
                    debug
                ) {
                    console.log(contentCloningWarning);
                }

                // create a tooltipster instance for each element if it doesn't
                // already have one or if the multiple option is set, and attach the
                // object to it
                this.each(function() {

                    var go = false,
                        $this = $(this),
                        ns = $this.data('tooltipster-ns'),
                        obj = null;

                    if (!ns) {
                        go = true;
                    } else if (multiple) {
                        go = true;
                    } else if (debug) {
                        console.log('Tooltipster: one or more tooltips are already attached to the element below. Ignoring.');
                        console.log(this);
                    }

                    if (go) {
                        obj = new $.Tooltipster(this, args[0]);

                        // save the reference of the new instance
                        if (!ns) ns = [];
                        ns.push(obj.__namespace);
                        $this.data('tooltipster-ns', ns);

                        // save the instance itself
                        $this.data(obj.__namespace, obj);

                        // call our constructor custom function.
                        // we do this here and not in ::init() because we wanted
                        // the object to be saved in $this.data before triggering
                        // it
                        if (obj.__options.functionInit) {
                            obj.__options.functionInit.call(obj, obj, {
                                origin: this
                            });
                        }

                        // and now the event, for the plugins and core emitter
                        obj._trigger('init');
                    }

                    $.tooltipster.__instancesLatestArr.push(obj);
                });

                return this;
            }
        }
    };

    // Utilities

    /**
     * A class to check if a tooltip can fit in given dimensions
     * 
     * @param {object} $tooltip The jQuery wrapped tooltip element, or a clone of it
     */
    function Ruler($tooltip) {

        // list of instance variables

        //this.$container;
        this.constraints = null;
        //this.__$tooltip;

        this.__init($tooltip);
    }

    Ruler.prototype = {

        /**
         * Move the tooltip into an invisible div that does not allow overflow to make
         * size tests. Note: the tooltip may or may not be attached to the DOM at the
         * moment this method is called, it does not matter.
         * 
         * @param {object} $tooltip The object to test. May be just a clone of the
         * actual tooltip.
         * @private
         */
        __init: function($tooltip) {

            this.__$tooltip = $tooltip;

            this.__$tooltip
                .css({
                    // for some reason we have to specify top and left 0
                    left: 0,
                    // any overflow will be ignored while measuring
                    overflow: 'hidden',
                    // positions at (0,0) without the div using 100% of the available width
                    position: 'absolute',
                    top: 0
                })
                // overflow must be auto during the test. We re-set this in case
                // it were modified by the user
                .find('.tooltipster-content')
                .css('overflow', 'auto');

            this.$container = $('<div class="tooltipster-ruler"></div>')
                .append(this.__$tooltip)
                .appendTo(env.window.document.body);
        },

        /**
         * Force the browser to redraw (re-render) the tooltip immediately. This is required
         * when you changed some CSS properties and need to make something with it
         * immediately, without waiting for the browser to redraw at the end of instructions.
         *
         * @see http://stackoverflow.com/questions/3485365/how-can-i-force-webkit-to-redraw-repaint-to-propagate-style-changes
         * @private
         */
        __forceRedraw: function() {

            // note: this would work but for Webkit only
            //this.__$tooltip.close();
            //this.__$tooltip[0].offsetHeight;
            //this.__$tooltip.open();

            // works in FF too
            var $p = this.__$tooltip.parent();
            this.__$tooltip.detach();
            this.__$tooltip.appendTo($p);
        },

        /**
         * Set maximum dimensions for the tooltip. A call to ::measure afterwards
         * will tell us if the content overflows or if it's ok
         *
         * @param {int} width
         * @param {int} height
         * @return {Ruler}
         * @public
         */
        constrain: function(width, height) {

            this.constraints = {
                width: width,
                height: height
            };

            this.__$tooltip.css({
                // we disable display:flex, otherwise the content would overflow without
                // creating horizontal scrolling (which we need to detect).
                display: 'block',
                // reset any previous height
                height: '',
                // we'll check if horizontal scrolling occurs
                overflow: 'auto',
                // we'll set the width and see what height is generated and if there
                // is horizontal overflow
                width: width
            });

            return this;
        },

        /**
         * Reset the tooltip content overflow and remove the test container
         * 
         * @returns {Ruler}
         * @public
         */
        destroy: function() {

            // in case the element was not a clone
            this.__$tooltip
                .detach()
                .find('.tooltipster-content')
                .css({
                    // reset to CSS value
                    display: '',
                    overflow: ''
                });

            this.$container.remove();
        },

        /**
         * Removes any constraints
         * 
         * @returns {Ruler}
         * @public
         */
        free: function() {

            this.constraints = null;

            // reset to natural size
            this.__$tooltip.css({
                display: '',
                height: '',
                overflow: 'visible',
                width: ''
            });

            return this;
        },

        /**
         * Returns the size of the tooltip. When constraints are applied, also returns
         * whether the tooltip fits in the provided dimensions.
         * The idea is to see if the new height is small enough and if the content does
         * not overflow horizontally.
         *
         * @param {int} width
         * @param {int} height
         * @returns {object} An object with a bool `fits` property and a `size` property
         * @public
         */
        measure: function() {

            this.__forceRedraw();

            var tooltipBcr = this.__$tooltip[0].getBoundingClientRect(),
                result = {
                    size: {
                        // bcr.width/height are not defined in IE8- but in this
                        // case, bcr.right/bottom will have the same value
                        // except in iOS 8+ where tooltipBcr.bottom/right are wrong
                        // after scrolling for reasons yet to be determined.
                        // tooltipBcr.top/left might not be 0, see issue #514
                        height: tooltipBcr.height || (tooltipBcr.bottom - tooltipBcr.top),
                        width: tooltipBcr.width || (tooltipBcr.right - tooltipBcr.left)
                    }
                };

            if (this.constraints) {

                // note: we used to use offsetWidth instead of boundingRectClient but
                // it returned rounded values, causing issues with sub-pixel layouts.

                // note2: noticed that the bcrWidth of text content of a div was once
                // greater than the bcrWidth of its container by 1px, causing the final
                // tooltip box to be too small for its content. However, evaluating
                // their widths one against the other (below) surprisingly returned
                // equality. Happened only once in Chrome 48, was not able to reproduce
                // => just having fun with float position values...

                var $content = this.__$tooltip.find('.tooltipster-content'),
                    height = this.__$tooltip.outerHeight(),
                    contentBcr = $content[0].getBoundingClientRect(),
                    fits = {
                        height: height <= this.constraints.height,
                        width: ( tooltipBcr.width <= this.constraints.width && contentBcr.width >= $content[0].scrollWidth - 1 )
                            // this condition accounts for min-width property that
                            // may apply
                            // the -1 is here because scrollWidth actually returns
                            // a rounded value, and may be greater than bcr.width if
                            // it was rounded up. This may cause an issue for contents
                            // which actually really overflow  by 1px or so, but that
                            // should be rare. Not sure how to solve this efficiently.
                            // See http://blogs.msdn.com/b/ie/archive/2012/02/17/sub-pixel-rendering-and-the-css-object-model.aspx
                    };

                result.fits = fits.height && fits.width;
            }

            // old versions of IE get the width wrong for some reason and it causes
            // the text to be broken to a new line, so we round it up. If the width
            // is the width of the screen though, we can assume it is accurate.
            if (env.IE &&
                env.IE <= 11 &&
                result.size.width !== env.window.document.documentElement.clientWidth
            ) {
                result.size.width = Math.ceil(result.size.width) + 1;
            }

            return result;
        }
    };

    // quick & dirty compare function, not bijective nor multidimensional
    function areEqual(a, b) {
        var same = true;
        $.each(a, function(i) {
            if (b[i] === undefined || a[i] !== b[i]) {
                same = false;
                return false;
            }
        });
        return same;
    }

    /**
     * A fast function to check if an element is still in the DOM. It
     * tries to use an id as ids are indexed by the browser, or falls
     * back to jQuery's `contains` method. May fail if two elements
     * have the same id, but so be it
     *
     * @param {object} $obj A jQuery-wrapped HTML element
     * @return {boolean}
     */
    function bodyContains($obj) {
        var id = $obj.attr('id'),
            el = id ? env.window.document.getElementById(id) : null;
        // must also check that the element with the id is the one we want
        return el ? el === $obj[0] : $.contains(env.window.document.body, $obj[0]);
    }

    // detect IE versions for dirty fixes
    var uA = navigator.userAgent.toLowerCase();
    if (uA.indexOf('msie') != -1) env.IE = parseInt(uA.split('msie')[1], 10);
    else if (uA.toLowerCase().indexOf('trident') !== -1 && uA.indexOf(' rv:11') !== -1) env.IE = 11;
    else if (uA.toLowerCase().indexOf('edge/') != -1) env.IE = parseInt(uA.toLowerCase().split('edge/')[1], 10);

    // detecting support for CSS transitions
    function transitionSupport() {

        // env.window is not defined yet when this is called
        if (!win) return false;

        var b = win.document.body || win.document.documentElement,
            s = b.style,
            p = 'transition',
            v = ['Moz', 'Webkit', 'Khtml', 'O', 'ms'];

        if (typeof s[p] == 'string') {
            return true;
        }

        p = p.charAt(0).toUpperCase() + p.substr(1);
        for (var i = 0; i < v.length; i++) {
            if (typeof s[v[i] + p] == 'string') {
                return true;
            }
        }
        return false;
    }

    // we'll return jQuery for plugins not to have to declare it as a dependency,
    // but it's done by a build task since it should be included only once at the
    // end when we concatenate the main file with a plugin
    // sideTip is Tooltipster's default plugin.
    // This file will be UMDified by a build task.

    var pluginName = 'tooltipster.sideTip';

    $.tooltipster._plugin({
        name: pluginName,
        instance: {
            /**
             * Defaults are provided as a function for an easy override by inheritance
             *
             * @return {object} An object with the defaults options
             * @private
             */
            __defaults: function() {

                return {
                    // if the tooltip should display an arrow that points to the origin
                    arrow: true,
                    // the distance in pixels between the tooltip and the origin
                    distance: 6,
                    // allows to easily change the position of the tooltip
                    functionPosition: null,
                    maxWidth: null,
                    // used to accomodate the arrow of tooltip if there is one.
                    // First to make sure that the arrow target is not too close
                    // to the edge of the tooltip, so the arrow does not overflow
                    // the tooltip. Secondly when we reposition the tooltip to
                    // make sure that it's positioned in such a way that the arrow is
                    // still pointing at the target (and not a few pixels beyond it).
                    // It should be equal to or greater than half the width of
                    // the arrow (by width we mean the size of the side which touches
                    // the side of the tooltip).
                    minIntersection: 16,
                    minWidth: 0,
                    // deprecated in 4.0.0. Listed for _optionsExtract to pick it up
                    position: null,
                    side: 'top',
                    // set to false to position the tooltip relatively to the document rather
                    // than the window when we open it
                    viewportAware: true
                };
            },

            /**
             * Run once: at instantiation of the plugin
             *
             * @param {object} instance The tooltipster object that instantiated this plugin
             * @private
             */
            __init: function(instance) {

                var self = this;

                // list of instance variables

                self.__instance = instance;
                self.__namespace = 'tooltipster-sideTip-' + Math.round(Math.random() * 1000000);
                self.__previousState = 'closed';
                //self.__options;

                // initial formatting
                self.__optionsFormat();

                self.__instance._on('state.' + self.__namespace, function(event) {

                    if (event.state == 'closed') {
                        self.__close();
                    } else if (event.state == 'appearing' && self.__previousState == 'closed') {
                        self.__create();
                    }

                    self.__previousState = event.state;
                });

                // reformat every time the options are changed
                self.__instance._on('options.' + self.__namespace, function() {
                    self.__optionsFormat();
                });

                self.__instance._on('reposition.' + self.__namespace, function(e) {
                    self.__reposition(e.event, e.helper);
                });
            },

            /**
             * Called when the tooltip has closed
             * 
             * @private
             */
            __close: function() {

                // detach our content object first, so the next jQuery's remove()
                // call does not unbind its event handlers
                if (this.__instance.content() instanceof $) {
                    this.__instance.content().detach();
                }

                // remove the tooltip from the DOM
                this.__instance._$tooltip.remove();
                this.__instance._$tooltip = null;
            },

            /**
             * Creates the HTML element of the tooltip.
             * 
             * @private
             */
            __create: function() {

                // note: we wrap with a .tooltipster-box div to be able to set a margin on it
                // (.tooltipster-base must not have one)
                var $html = $(
                    '<div class="tooltipster-base tooltipster-sidetip">' +
                    '<div class="tooltipster-box">' +
                    '<div class="tooltipster-content"></div>' +
                    '</div>' +
                    '<div class="tooltipster-arrow">' +
                    '<div class="tooltipster-arrow-uncropped">' +
                    '<div class="tooltipster-arrow-border"></div>' +
                    '<div class="tooltipster-arrow-background"></div>' +
                    '</div>' +
                    '</div>' +
                    '</div>'
                );

                // hide arrow if asked
                if (!this.__options.arrow) {
                    $html
                        .find('.tooltipster-box')
                        .css('margin', 0)
                        .end()
                        .find('.tooltipster-arrow')
                        .hide();
                }

                // apply min/max width if asked
                if (this.__options.minWidth) {
                    $html.css('min-width', this.__options.minWidth + 'px');
                }
                if (this.__options.maxWidth) {
                    $html.css('max-width', this.__options.maxWidth + 'px');
                }

                this.__instance._$tooltip = $html;

                // tell the instance that the tooltip element has been created
                this.__instance._trigger('created');
            },

            /**
             * Used when the plugin is to be unplugged
             *
             * @private
             */
            __destroy: function() {
                this.__instance._off('.' + this.__namespace);
            },

            /**
             * (Re)compute this.__options from the options declared to the instance
             *
             * @private
             */
            __optionsFormat: function() {

                var self = this;

                // get the options
                self.__options = self.__instance._optionsExtract(pluginName, self.__defaults());

                // for backward compatibility, deprecated in v4.0.0
                if (self.__options.position) {
                    self.__options.side = self.__options.position;
                }

                // options formatting

                // format distance as a four-cell array if it ain't one yet and then make
                // it an object with top/bottom/left/right properties
                if (typeof self.__options.distance != 'object') {
                    self.__options.distance = [self.__options.distance];
                }
                if (self.__options.distance.length < 4) {

                    if (self.__options.distance[1] === undefined) self.__options.distance[1] = self.__options.distance[0];
                    if (self.__options.distance[2] === undefined) self.__options.distance[2] = self.__options.distance[0];
                    if (self.__options.distance[3] === undefined) self.__options.distance[3] = self.__options.distance[1];

                    self.__options.distance = {
                        top: self.__options.distance[0],
                        right: self.__options.distance[1],
                        bottom: self.__options.distance[2],
                        left: self.__options.distance[3]
                    };
                }

                // let's transform:
                // 'top' into ['top', 'bottom', 'right', 'left']
                // 'right' into ['right', 'left', 'top', 'bottom']
                // 'bottom' into ['bottom', 'top', 'right', 'left']
                // 'left' into ['left', 'right', 'top', 'bottom']
                if (typeof self.__options.side == 'string') {

                    var opposites = {
                        'top': 'bottom',
                        'right': 'left',
                        'bottom': 'top',
                        'left': 'right'
                    };

                    self.__options.side = [self.__options.side, opposites[self.__options.side]];

                    if (self.__options.side[0] == 'left' || self.__options.side[0] == 'right') {
                        self.__options.side.push('top', 'bottom');
                    } else {
                        self.__options.side.push('right', 'left');
                    }
                }

                // misc
                // disable the arrow in IE6 unless the arrow option was explicitly set to true
                if ($.tooltipster._env.IE === 6 &&
                    self.__options.arrow !== true
                ) {
                    self.__options.arrow = false;
                }
            },

            /**
             * This method must compute and set the positioning properties of the
             * tooltip (left, top, width, height, etc.). It must also make sure the
             * tooltip is eventually appended to its parent (since the element may be
             * detached from the DOM at the moment the method is called).
             *
             * We'll evaluate positioning scenarios to find which side can contain the
             * tooltip in the best way. We'll consider things relatively to the window
             * (unless the user asks not to), then to the document (if need be, or if the
             * user explicitly requires the tests to run on the document). For each
             * scenario, measures are taken, allowing us to know how well the tooltip
             * is going to fit. After that, a sorting function will let us know what
             * the best scenario is (we also allow the user to choose his favorite
             * scenario by using an event).
             * 
             * @param {object} helper An object that contains variables that plugin
             * creators may find useful (see below)
             * @param {object} helper.geo An object with many layout properties
             * about objects of interest (window, document, origin). This should help
             * plugin users compute the optimal position of the tooltip
             * @private
             */
            __reposition: function(event, helper) {

                var self = this,
                    finalResult,
                    // to know where to put the tooltip, we need to know on which point
                    // of the x or y axis we should center it. That coordinate is the target
                    targets = self.__targetFind(helper),
                    testResults = [];

                // make sure the tooltip is detached while we make tests on a clone
                self.__instance._$tooltip.detach();

                // we could actually provide the original element to the Ruler and
                // not a clone, but it just feels right to keep it out of the
                // machinery.
                var $clone = self.__instance._$tooltip.clone(),
                    // start position tests session
                    ruler = $.tooltipster._getRuler($clone),
                    satisfied = false,
                    animation = self.__instance.option('animation');

                // an animation class could contain properties that distort the size
                if (animation) {
                    $clone.removeClass('tooltipster-' + animation);
                }

                // start evaluating scenarios
                $.each(['window', 'document'], function(i, container) {

                    var takeTest = null;

                    // let the user decide to keep on testing or not
                    self.__instance._trigger({
                        container: container,
                        helper: helper,
                        satisfied: satisfied,
                        takeTest: function(bool) {
                            takeTest = bool;
                        },
                        results: testResults,
                        type: 'positionTest'
                    });

                    if (takeTest == true || (takeTest != false && satisfied == false && (container != 'window' || self.__options.viewportAware) ) ) {
                        // skip the window scenarios if asked. If they are reintegrated by
                        // the callback of the positionTest event, they will have to be
                        // excluded using the callback of positionTested

                        // for each allowed side
                        for (i = 0; i < self.__options.side.length; i++) {

                            var distance = {
                                    horizontal: 0,
                                    vertical: 0
                                },
                                side = self.__options.side[i];

                            if (side == 'top' || side == 'bottom') {
                                distance.vertical = self.__options.distance[side];
                            } else {
                                distance.horizontal = self.__options.distance[side];
                            }

                            // this may have an effect on the size of the tooltip if there are css
                            // rules for the arrow or something else
                            self.__sideChange($clone, side);

                            $.each(['natural', 'constrained'], function(i, mode) {

                                takeTest = null;

                                // emit an event on the instance
                                self.__instance._trigger({
                                    container: container,
                                    event: event,
                                    helper: helper,
                                    mode: mode,
                                    results: testResults,
                                    satisfied: satisfied,
                                    side: side,
                                    takeTest: function(bool) {
                                        takeTest = bool;
                                    },
                                    type: 'positionTest'
                                });

                                if (takeTest == true ||
                                    (takeTest != false &&
                                        satisfied == false
                                    )
                                ) {

                                    var testResult = {
                                        container: container,
                                        // we let the distance as an object here, it can make things a little easier
                                        // during the user's calculations at positionTest/positionTested
                                        distance: distance,
                                        // whether the tooltip can fit in the size of the viewport (does not mean
                                        // that we'll be able to make it initially entirely visible, see 'whole')
                                        fits: null,
                                        mode: mode,
                                        outerSize: null,
                                        side: side,
                                        size: null,
                                        target: targets[side],
                                        // check if the origin has enough surface on screen for the tooltip to
                                        // aim at it without overflowing the viewport (this is due to the thickness
                                        // of the arrow represented by the minIntersection length).
                                        // If not, the tooltip will have to be partly or entirely off screen in
                                        // order to stay docked to the origin. This value will stay null when the
                                        // container is the document, as it is not relevant
                                        whole: null
                                    };

                                    // get the size of the tooltip with or without size constraints
                                    var rulerConfigured = (mode == 'natural') ?
                                        ruler.free() :
                                        ruler.constrain(
                                            helper.geo.available[container][side].width - distance.horizontal,
                                            helper.geo.available[container][side].height - distance.vertical
                                        ),
                                        rulerResults = rulerConfigured.measure();

                                    testResult.size = rulerResults.size;
                                    testResult.outerSize = {
                                        height: rulerResults.size.height + distance.vertical,
                                        width: rulerResults.size.width + distance.horizontal
                                    };

                                    if (mode == 'natural') {

                                        if (helper.geo.available[container][side].width >= testResult.outerSize.width &&
                                            helper.geo.available[container][side].height >= testResult.outerSize.height
                                        ) {
                                            testResult.fits = true;
                                        } else {
                                            testResult.fits = false;
                                        }
                                    } else {
                                        testResult.fits = rulerResults.fits;
                                    }

                                    if (container == 'window') {

                                        if (!testResult.fits) {
                                            testResult.whole = false;
                                        } else {
                                            if (side == 'top' || side == 'bottom') {

                                                testResult.whole = (
                                                    helper.geo.origin.windowOffset.right >= self.__options.minIntersection &&
                                                    helper.geo.window.size.width - helper.geo.origin.windowOffset.left >= self.__options.minIntersection
                                                );
                                            } else {
                                                testResult.whole = (
                                                    helper.geo.origin.windowOffset.bottom >= self.__options.minIntersection &&
                                                    helper.geo.window.size.height - helper.geo.origin.windowOffset.top >= self.__options.minIntersection
                                                );
                                            }
                                        }
                                    }

                                    testResults.push(testResult);

                                    // we don't need to compute more positions if we have one fully on screen
                                    if (testResult.whole) {
                                        satisfied = true;
                                    } else {
                                        // don't run the constrained test unless the natural width was greater
                                        // than the available width, otherwise it's pointless as we know it
                                        // wouldn't fit either
                                        if (testResult.mode == 'natural' &&
                                            (testResult.fits ||
                                                testResult.size.width <= helper.geo.available[container][side].width
                                            )
                                        ) {
                                            return false;
                                        }
                                    }
                                }
                            });
                        }
                    }
                });

                // the user may eliminate the unwanted scenarios from testResults, but he's
                // not supposed to alter them at this point. functionPosition and the
                // position event serve that purpose.
                self.__instance._trigger({
                    edit: function(r) {
                        testResults = r;
                    },
                    event: event,
                    helper: helper,
                    results: testResults,
                    type: 'positionTested'
                });

                /**
                 * Sort the scenarios to find the favorite one.
                 * 
                 * The favorite scenario is when we can fully display the tooltip on screen,
                 * even if it means that the middle of the tooltip is no longer centered on
                 * the middle of the origin (when the origin is near the edge of the screen
                 * or even partly off screen). We want the tooltip on the preferred side,
                 * even if it means that we have to use a constrained size rather than a
                 * natural one (as long as it fits). When the origin is off screen at the top
                 * the tooltip will be positioned at the bottom (if allowed), if the origin
                 * is off screen on the right, it will be positioned on the left, etc.
                 * If there are no scenarios where the tooltip can fit on screen, or if the
                 * user does not want the tooltip to fit on screen (viewportAware == false),
                 * we fall back to the scenarios relative to the document.
                 * 
                 * When the tooltip is bigger than the viewport in either dimension, we stop
                 * looking at the window scenarios and consider the document scenarios only,
                 * with the same logic to find on which side it would fit best.
                 * 
                 * If the tooltip cannot fit the document on any side, we force it at the
                 * bottom, so at least the user can scroll to see it.
                 */
                testResults.sort(function(a, b) {

                    var ai,
                    	bi;

                    // best if it's whole (the tooltip fits and adapts to the viewport)
                    if (a.whole && !b.whole) {
                        return -1;
                    } else if (!a.whole && b.whole) {
                        return 1;
                    } else if (a.whole && b.whole) {

                        ai = self.__options.side.indexOf(a.side);
                        bi = self.__options.side.indexOf(b.side);

                        // use the user's sides fallback array
                        if (ai < bi) {
                            return -1;
                        } else if (ai > bi) {
                            return 1;
                        } else {
                            // will be used if the user forced the tests to continue
                            return a.mode == 'natural' ? -1 : 1;
                        }
                    } else {

                        // better if it fits
                        if (a.fits && !b.fits) {
                            return -1;
                        } else if (!a.fits && b.fits) {
                            return 1;
                        } else if (a.fits && b.fits) {

                            ai = self.__options.side.indexOf(a.side);
                            bi = self.__options.side.indexOf(b.side);

                            // use the user's sides fallback array
                            if (ai < bi) {
                                return -1;
                            } else if (ai > bi) {
                                return 1;
                            } else {
                                // will be used if the user forced the tests to continue
                                return a.mode == 'natural' ? -1 : 1;
                            }
                        } else {

                            // if everything failed, this will give a preference to the case where
                            // the tooltip overflows the document at the bottom
                            if (a.container == 'document' &&
                                a.side == 'bottom' &&
                                a.mode == 'natural'
                            ) {
                                return -1;
                            } else {
                                return 1;
                            }
                        }
                    }
                });

                finalResult = testResults[0];


                // now let's find the coordinates of the tooltip relatively to the window
                finalResult.coord = {};

                switch (finalResult.side) {

                    case 'left':
                    case 'right':
                        finalResult.coord.top = Math.floor(finalResult.target - finalResult.size.height / 2);
                        break;

                    case 'bottom':
                    case 'top':
                        finalResult.coord.left = Math.floor(finalResult.target - finalResult.size.width / 2);
                        break;
                }

                switch (finalResult.side) {

                    case 'left':
                        finalResult.coord.left = helper.geo.origin.windowOffset.left - finalResult.outerSize.width;
                        break;

                    case 'right':
                        finalResult.coord.left = helper.geo.origin.windowOffset.right + finalResult.distance.horizontal;
                        break;

                    case 'top':
                        finalResult.coord.top = helper.geo.origin.windowOffset.top - finalResult.outerSize.height;
                        break;

                    case 'bottom':
                        finalResult.coord.top = helper.geo.origin.windowOffset.bottom + finalResult.distance.vertical;
                        break;
                }

                // if the tooltip can potentially be contained within the viewport dimensions
                // and that we are asked to make it fit on screen
                if (finalResult.container == 'window') {

                    // if the tooltip overflows the viewport, we'll move it accordingly (then it will
                    // not be centered on the middle of the origin anymore). We only move horizontally
                    // for top and bottom tooltips and vice versa.
                    if (finalResult.side == 'top' || finalResult.side == 'bottom') {

                        // if there is an overflow on the left
                        if (finalResult.coord.left < 0) {

                            // prevent the overflow unless the origin itself gets off screen (minus the
                            // margin needed to keep the arrow pointing at the target)
                            if (helper.geo.origin.windowOffset.right - this.__options.minIntersection >= 0) {
                                finalResult.coord.left = 0;
                            } else {
                                finalResult.coord.left = helper.geo.origin.windowOffset.right - this.__options.minIntersection - 1;
                            }
                        }
                        // or an overflow on the right
                        else if (finalResult.coord.left > helper.geo.window.size.width - finalResult.size.width) {

                            if (helper.geo.origin.windowOffset.left + this.__options.minIntersection <= helper.geo.window.size.width) {
                                finalResult.coord.left = helper.geo.window.size.width - finalResult.size.width;
                            } else {
                                finalResult.coord.left = helper.geo.origin.windowOffset.left + this.__options.minIntersection + 1 - finalResult.size.width;
                            }
                        }
                    } else {

                        // overflow at the top
                        if (finalResult.coord.top < 0) {

                            if (helper.geo.origin.windowOffset.bottom - this.__options.minIntersection >= 0) {
                                finalResult.coord.top = 0;
                            } else {
                                finalResult.coord.top = helper.geo.origin.windowOffset.bottom - this.__options.minIntersection - 1;
                            }
                        }
                        // or at the bottom
                        else if (finalResult.coord.top > helper.geo.window.size.height - finalResult.size.height) {

                            if (helper.geo.origin.windowOffset.top + this.__options.minIntersection <= helper.geo.window.size.height) {
                                finalResult.coord.top = helper.geo.window.size.height - finalResult.size.height;
                            } else {
                                finalResult.coord.top = helper.geo.origin.windowOffset.top + this.__options.minIntersection + 1 - finalResult.size.height;
                            }
                        }
                    }
                } else {

                    // there might be overflow here too but it's easier to handle. If there has
                    // to be an overflow, we'll make sure it's on the right side of the screen
                    // (because the browser will extend the document size if there is an overflow
                    // on the right, but not on the left). The sort function above has already
                    // made sure that a bottom document overflow is preferred to a top overflow,
                    // so we don't have to care about it.

                    // if there is an overflow on the right
                    if (finalResult.coord.left > helper.geo.window.size.width - finalResult.size.width) {

                        // this may actually create on overflow on the left but we'll fix it in a sec
                        finalResult.coord.left = helper.geo.window.size.width - finalResult.size.width;
                    }

                    // if there is an overflow on the left
                    if (finalResult.coord.left < 0) {

                        // don't care if it overflows the right after that, we made our best
                        finalResult.coord.left = 0;
                    }
                }


                // submit the positioning proposal to the user function which may choose to change
                // the side, size and/or the coordinates

                // first, set the rules that corresponds to the proposed side: it may change
                // the size of the tooltip, and the custom functionPosition may want to detect the
                // size of something before making a decision. So let's make things easier for the
                // implementor
                self.__sideChange($clone, finalResult.side);

                // add some variables to the helper
                helper.tooltipClone = $clone[0];
                helper.tooltipParent = self.__instance.option('parent').parent[0];
                // move informative values to the helper
                helper.mode = finalResult.mode;
                helper.whole = finalResult.whole;
                // add some variables to the helper for the functionPosition callback (these
                // will also be added to the event fired by self.__instance._trigger but that's
                // ok, we're just being consistent)
                helper.origin = self.__instance._$origin[0];
                helper.tooltip = self.__instance._$tooltip[0];

                // leave only the actionable values in there for functionPosition
                delete finalResult.container;
                delete finalResult.fits;
                delete finalResult.mode;
                delete finalResult.outerSize;
                delete finalResult.whole;

                // keep only the distance on the relevant side, for clarity
                finalResult.distance = finalResult.distance.horizontal || finalResult.distance.vertical;

                // beginners may not be comfortable with the concept of editing the object
                //  passed by reference, so we provide an edit function and pass a clone
                var finalResultClone = $.extend(true, {}, finalResult);

                // emit an event on the instance
                self.__instance._trigger({
                    edit: function(result) {
                        finalResult = result;
                    },
                    event: event,
                    helper: helper,
                    position: finalResultClone,
                    type: 'position'
                });

                if (self.__options.functionPosition) {

                    var result = self.__options.functionPosition.call(self, self.__instance, helper, finalResultClone);

                    if (result) finalResult = result;
                }

                // end the positioning tests session (the user might have had a
                // use for it during the position event, now it's over)
                ruler.destroy();

                // compute the position of the target relatively to the tooltip root
                // element so we can place the arrow and make the needed adjustments
                var arrowCoord,
                    maxVal;

                if (finalResult.side == 'top' || finalResult.side == 'bottom') {

                    arrowCoord = {
                        prop: 'left',
                        val: finalResult.target - finalResult.coord.left
                    };
                    maxVal = finalResult.size.width - this.__options.minIntersection;
                } else {

                    arrowCoord = {
                        prop: 'top',
                        val: finalResult.target - finalResult.coord.top
                    };
                    maxVal = finalResult.size.height - this.__options.minIntersection;
                }

                // cannot lie beyond the boundaries of the tooltip, minus the
                // arrow margin
                if (arrowCoord.val < this.__options.minIntersection) {
                    arrowCoord.val = this.__options.minIntersection;
                } else if (arrowCoord.val > maxVal) {
                    arrowCoord.val = maxVal;
                }

                var originParentOffset;

                // let's convert the window-relative coordinates into coordinates relative to the
                // future positioned parent that the tooltip will be appended to
                if (helper.geo.origin.fixedLineage) {

                    // same as windowOffset when the position is fixed
                    originParentOffset = helper.geo.origin.windowOffset;
                } else {

                    // this assumes that the parent of the tooltip is located at
                    // (0, 0) in the document, typically like when the parent is
                    // <body>.
                    // If we ever allow other types of parent, .tooltipster-ruler
                    // will have to be appended to the parent to inherit css style
                    // values that affect the display of the text and such.
                    originParentOffset = {
                        left: helper.geo.origin.windowOffset.left + helper.geo.window.scroll.left,
                        top: helper.geo.origin.windowOffset.top + helper.geo.window.scroll.top
                    };
                }

                finalResult.coord = {
                    left: originParentOffset.left + (finalResult.coord.left - helper.geo.origin.windowOffset.left),
                    top: originParentOffset.top + (finalResult.coord.top - helper.geo.origin.windowOffset.top)
                };

                // set position values on the original tooltip element

                self.__sideChange(self.__instance._$tooltip, finalResult.side);

                if (helper.geo.origin.fixedLineage) {
                    self.__instance._$tooltip
                        .css('position', 'fixed');
                } else {
                    // CSS default
                    self.__instance._$tooltip
                        .css('position', '');
                }

                self.__instance._$tooltip
                    .css({
                        left: finalResult.coord.left,
                        top: finalResult.coord.top,
                        // we need to set a size even if the tooltip is in its natural size
                        // because when the tooltip is positioned beyond the width of the body
                        // (which is by default the width of the window; it will happen when
                        // you scroll the window horizontally to get to the origin), its text
                        // content will otherwise break lines at each word to keep up with the
                        // body overflow strategy.
                        height: finalResult.size.height,
                        width: finalResult.size.width
                    })
                    .find('.tooltipster-arrow')
                    .css({
                        'left': '',
                        'top': ''
                    })
                    .css(arrowCoord.prop, arrowCoord.val);

                // append the tooltip HTML element to its parent
                self.__instance._$tooltip.appendTo(self.__instance.option('parent'));

                self.__instance._trigger({
                    type: 'repositioned',
                    event: event,
                    position: finalResult
                });
            },

            /**
             * Make whatever modifications are needed when the side is changed. This has
             * been made an independant method for easy inheritance in custom plugins based
             * on this default plugin.
             *
             * @param {object} $obj
             * @param {string} side
             * @private
             */
            __sideChange: function($obj, side) {

                $obj
                    .removeClass('tooltipster-bottom')
                    .removeClass('tooltipster-left')
                    .removeClass('tooltipster-right')
                    .removeClass('tooltipster-top')
                    .addClass('tooltipster-' + side);
            },

            /**
             * Returns the target that the tooltip should aim at for a given side.
             * The calculated value is a distance from the edge of the window
             * (left edge for top/bottom sides, top edge for left/right side). The
             * tooltip will be centered on that position and the arrow will be
             * positioned there (as much as possible).
             *
             * @param {object} helper
             * @return {integer}
             * @private
             */
            __targetFind: function(helper) {

                var target = {},
                    rects = this.__instance._$origin[0].getClientRects();

                // these lines fix a Chrome bug (issue #491)
                if (rects.length > 1) {
                    var opacity = this.__instance._$origin.css('opacity');
                    if (opacity == 1) {
                        this.__instance._$origin.css('opacity', 0.99);
                        rects = this.__instance._$origin[0].getClientRects();
                        this.__instance._$origin.css('opacity', 1);
                    }
                }

                // by default, the target will be the middle of the origin
                if (rects.length < 2) {

                    target.top = Math.floor(helper.geo.origin.windowOffset.left + (helper.geo.origin.size.width / 2));
                    target.bottom = target.top;

                    target.left = Math.floor(helper.geo.origin.windowOffset.top + (helper.geo.origin.size.height / 2));
                    target.right = target.left;
                }
                // if multiple client rects exist, the element may be text split
                // up into multiple lines and the middle of the origin may not be
                // best option anymore. We need to choose the best target client rect
                else {

                    // top: the first
                    var targetRect = rects[0];
                    target.top = Math.floor(targetRect.left + (targetRect.right - targetRect.left) / 2);

                    // right: the middle line, rounded down in case there is an even
                    // number of lines (looks more centered => check out the
                    // demo with 4 split lines)
                    if (rects.length > 2) {
                        targetRect = rects[Math.ceil(rects.length / 2) - 1];
                    } else {
                        targetRect = rects[0];
                    }
                    target.right = Math.floor(targetRect.top + (targetRect.bottom - targetRect.top) / 2);

                    // bottom: the last
                    targetRect = rects[rects.length - 1];
                    target.bottom = Math.floor(targetRect.left + (targetRect.right - targetRect.left) / 2);

                    // left: the middle line, rounded up
                    if (rects.length > 2) {
                        targetRect = rects[Math.ceil((rects.length + 1) / 2) - 1];
                    } else {
                        targetRect = rects[rects.length - 1];
                    }

                    target.left = Math.floor(targetRect.top + (targetRect.bottom - targetRect.top) / 2);
                }

                return target;
            }
        }
    });

    /* a build task will add "return $;" here */
    return $;

}));
// source --> https://homelive.pt/wp-content/plugins/super-forms/assets/js/frontend/iban-check.js?ver=6.3.312 
/* eslint-disable no-undef */
// jshint ignore: start
(function (root, factory) {
    "use strict";
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['exports'], factory);
    } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
        // CommonJS
        factory(exports);
    } else {
        // Browser globals
        factory(root.IBAN = {});
    }
}(this, function(exports){

    "use strict";
    
    // Array.prototype.map polyfill
    // code from https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map
    if (!Array.prototype.map){
        Array.prototype.map = function(fun /*, thisArg */){

            if (this === void 0 || this === null)
                throw new TypeError();

            var t = Object(this);
            var len = t.length >>> 0;
            if (typeof fun !== "function")
                throw new TypeError();

            var res = new Array(len);
            var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
            for (var i = 0; i < len; i++)
            {
                // NOTE: Absolute correctness would demand Object.defineProperty
                //       be used.  But this method is fairly new, and failure is
                //       possible only if Object.prototype or Array.prototype
                //       has a property |i| (very unlikely), so use a less-correct
                //       but more portable alternative.
                if (i in t)
                    res[i] = fun.call(thisArg, t[i], i, t);
            }

            return res;
        };
    }

    var A = 'A'.charCodeAt(0),
        Z = 'Z'.charCodeAt(0);

    /**
     * Prepare an IBAN for mod 97 computation by moving the first 4 chars to the end and transforming the letters to
     * numbers (A = 10, B = 11, ..., Z = 35), as specified in ISO13616.
     *
     * @param {string} iban the IBAN
     * @returns {string} the prepared IBAN
     */
    function iso13616Prepare(iban) {
        iban = iban.toUpperCase();
        iban = iban.substr(4) + iban.substr(0,4);

        return iban.split('').map(function(n){
            var code = n.charCodeAt(0);
            if (code >= A && code <= Z){
                // A = 10, B = 11, ... Z = 35
                return code - A + 10;
            } else {
                return n;
            }
        }).join('');
    }

    /**
     * Calculates the MOD 97 10 of the passed IBAN as specified in ISO7064.
     *
     * @param iban
     * @returns {number}
     */
    function iso7064Mod97_10(iban) {
        var remainder = iban,
            block;

        while (remainder.length > 2){
            block = remainder.slice(0, 9);
            remainder = parseInt(block, 10) % 97 + remainder.slice(block.length);
        }

        return parseInt(remainder, 10) % 97;
    }

    /**
     * Parse the BBAN structure used to configure each IBAN Specification and returns a matching regular expression.
     * A structure is composed of blocks of 3 characters (one letter and 2 digits). Each block represents
     * a logical group in the typical representation of the BBAN. For each group, the letter indicates which characters
     * are allowed in this group and the following 2-digits number tells the length of the group.
     *
     * @param {string} structure the structure to parse
     * @returns {RegExp}
     */
    function parseStructure(structure){
        // split in blocks of 3 chars
        var regex = structure.match(/(.{3})/g).map(function(block){

            // parse each structure block (1-char + 2-digits)
            var format,
                pattern = block.slice(0, 1),
                repeats = parseInt(block.slice(1), 10);

            switch (pattern){
                case "A": format = "0-9A-Za-z"; break;
                case "B": format = "0-9A-Z"; break;
                case "C": format = "A-Za-z"; break;
                case "F": format = "0-9"; break;
                case "L": format = "a-z"; break;
                case "U": format = "A-Z"; break;
                case "W": format = "0-9a-z"; break;
            }

            return '([' + format + ']{' + repeats + '})';
        });

        return new RegExp('^' + regex.join('') + '$');
    }

    /**
     *
     * @param iban
     * @returns {string}
     */
    function electronicFormat(iban){
        return iban.replace(NON_ALPHANUM, '').toUpperCase();
    }


    /**
     * Create a new Specification for a valid IBAN number.
     *
     * @param countryCode the code of the country
     * @param length the length of the IBAN
     * @param structure the structure of the underlying BBAN (for validation and formatting)
     * @param example an example valid IBAN
     * @constructor
     */
    function Specification(countryCode, length, structure, example){

        this.countryCode = countryCode;
        this.length = length;
        this.structure = structure;
        this.example = example;
    }

    /**
     * Lazy-loaded regex (parse the structure and construct the regular expression the first time we need it for validation)
     */
    Specification.prototype._regex = function(){
        return this._cachedRegex || (this._cachedRegex = parseStructure(this.structure));
    };

    /**
     * Check if the passed iban is valid according to this specification.
     *
     * @param {String} iban the iban to validate
     * @returns {boolean} true if valid, false otherwise
     */
    Specification.prototype.isValid = function(iban){
        return this.length == iban.length && this.countryCode === iban.slice(0,2) && this._regex().test(iban.slice(4)) && iso7064Mod97_10(iso13616Prepare(iban)) == 1;
    };

    /**
     * Convert the passed IBAN to a country-specific BBAN.
     *
     * @param iban the IBAN to convert
     * @param separator the separator to use between BBAN blocks
     * @returns {string} the BBAN
     */
    Specification.prototype.toBBAN = function(iban, separator) {
        return this._regex().exec(iban.slice(4)).slice(1).join(separator);
    };

    /**
     * Convert the passed BBAN to an IBAN for this country specification.
     * Please note that <i>"generation of the IBAN shall be the exclusive responsibility of the bank/branch servicing the account"</i>.
     * This method implements the preferred algorithm described in http://en.wikipedia.org/wiki/International_Bank_Account_Number#Generating_IBAN_check_digits
     *
     * @param bban the BBAN to convert to IBAN
     * @returns {string} the IBAN
     */
    Specification.prototype.fromBBAN = function(bban) {
        if (!this.isValidBBAN(bban)){
            throw new Error('Invalid BBAN');
        }

        var remainder = iso7064Mod97_10(iso13616Prepare(this.countryCode + '00' + bban)),
            checkDigit = ('0' + (98 - remainder)).slice(-2);

        return this.countryCode + checkDigit + bban;
    };

    /**
     * Check of the passed BBAN is valid.
     * This function only checks the format of the BBAN (length and matching the letetr/number specs) but does not
     * verify the check digit.
     *
     * @param bban the BBAN to validate
     * @returns {boolean} true if the passed bban is a valid BBAN according to this specification, false otherwise
     */
    Specification.prototype.isValidBBAN = function(bban) {
        return this.length - 4 == bban.length && this._regex().test(bban);
    };

    var countries = {};

    function addSpecification(IBAN){
        countries[IBAN.countryCode] = IBAN;
    }

    addSpecification(new Specification("AD", 24, "F04F04A12",          "AD1200012030200359100100"));
    addSpecification(new Specification("AE", 23, "F03F16",             "AE070331234567890123456"));
    addSpecification(new Specification("AL", 28, "F08A16",             "AL47212110090000000235698741"));
    addSpecification(new Specification("AT", 20, "F05F11",             "AT611904300234573201"));
    addSpecification(new Specification("AZ", 28, "U04A20",             "AZ21NABZ00000000137010001944"));
    addSpecification(new Specification("BA", 20, "F03F03F08F02",       "BA391290079401028494"));
    addSpecification(new Specification("BE", 16, "F03F07F02",          "BE68539007547034"));
    addSpecification(new Specification("BG", 22, "U04F04F02A08",       "BG80BNBG96611020345678"));
    addSpecification(new Specification("BH", 22, "U04A14",             "BH67BMAG00001299123456"));
    addSpecification(new Specification("BR", 29, "F08F05F10U01A01",    "BR9700360305000010009795493P1"));
    addSpecification(new Specification("CH", 21, "F05A12",             "CH9300762011623852957"));
    addSpecification(new Specification("CR", 22, "F04F14",             "CR72012300000171549015"));
    addSpecification(new Specification("CY", 28, "F03F05A16",          "CY17002001280000001200527600"));
    addSpecification(new Specification("CZ", 24, "F04F06F10",          "CZ6508000000192000145399"));
    addSpecification(new Specification("DE", 22, "F08F10",             "DE89370400440532013000"));
    addSpecification(new Specification("DK", 18, "F04F09F01",          "DK5000400440116243"));
    addSpecification(new Specification("DO", 28, "U04F20",             "DO28BAGR00000001212453611324"));
    addSpecification(new Specification("EE", 20, "F02F02F11F01",       "EE382200221020145685"));
    addSpecification(new Specification("ES", 24, "F04F04F01F01F10",    "ES9121000418450200051332"));
    addSpecification(new Specification("FI", 18, "F06F07F01",          "FI2112345600000785"));
    addSpecification(new Specification("FO", 18, "F04F09F01",          "FO6264600001631634"));
    addSpecification(new Specification("FR", 27, "F05F05A11F02",       "FR1420041010050500013M02606"));
    addSpecification(new Specification("GB", 22, "U04F06F08",          "GB29NWBK60161331926819"));
    addSpecification(new Specification("GE", 22, "U02F16",             "GE29NB0000000101904917"));
    addSpecification(new Specification("GI", 23, "U04A15",             "GI75NWBK000000007099453"));
    addSpecification(new Specification("GL", 18, "F04F09F01",          "GL8964710001000206"));
    addSpecification(new Specification("GR", 27, "F03F04A16",          "GR1601101250000000012300695"));
    addSpecification(new Specification("GT", 28, "A04A20",             "GT82TRAJ01020000001210029690"));
    addSpecification(new Specification("HR", 21, "F07F10",             "HR1210010051863000160"));
    addSpecification(new Specification("HU", 28, "F03F04F01F15F01",    "HU42117730161111101800000000"));
    addSpecification(new Specification("IE", 22, "U04F06F08",          "IE29AIBK93115212345678"));
    addSpecification(new Specification("IL", 23, "F03F03F13",          "IL620108000000099999999"));
    addSpecification(new Specification("IS", 26, "F04F02F06F10",       "IS140159260076545510730339"));
    addSpecification(new Specification("IT", 27, "U01F05F05A12",       "IT60X0542811101000000123456"));
    addSpecification(new Specification("KW", 30, "U04A22",             "KW81CBKU0000000000001234560101"));
    addSpecification(new Specification("KZ", 20, "F03A13",             "KZ86125KZT5004100100"));
    addSpecification(new Specification("LB", 28, "F04A20",             "LB62099900000001001901229114"));
    addSpecification(new Specification("LC", 32, "U04F24",             "LC07HEMM000100010012001200013015"));
    addSpecification(new Specification("LI", 21, "F05A12",             "LI21088100002324013AA"));
    addSpecification(new Specification("LT", 20, "F05F11",             "LT121000011101001000"));
    addSpecification(new Specification("LU", 20, "F03A13",             "LU280019400644750000"));
    addSpecification(new Specification("LV", 21, "U04A13",             "LV80BANK0000435195001"));
    addSpecification(new Specification("MC", 27, "F05F05A11F02",       "MC5811222000010123456789030"));
    addSpecification(new Specification("MD", 24, "U02A18",             "MD24AG000225100013104168"));
    addSpecification(new Specification("ME", 22, "F03F13F02",          "ME25505000012345678951"));
    addSpecification(new Specification("MK", 19, "F03A10F02",          "MK07250120000058984"));
    addSpecification(new Specification("MR", 27, "F05F05F11F02",       "MR1300020001010000123456753"));
    addSpecification(new Specification("MT", 31, "U04F05A18",          "MT84MALT011000012345MTLCAST001S"));
    addSpecification(new Specification("MU", 30, "U04F02F02F12F03U03", "MU17BOMM0101101030300200000MUR"));
    addSpecification(new Specification("NL", 18, "U04F10",             "NL91ABNA0417164300"));
    addSpecification(new Specification("NO", 15, "F04F06F01",          "NO9386011117947"));
    addSpecification(new Specification("PK", 24, "U04A16",             "PK36SCBL0000001123456702"));
    addSpecification(new Specification("PL", 28, "F08F16",             "PL61109010140000071219812874"));
    addSpecification(new Specification("PS", 29, "U04A21",             "PS92PALS000000000400123456702"));
    addSpecification(new Specification("PT", 25, "F04F04F11F02",       "PT50000201231234567890154"));
    addSpecification(new Specification("RO", 24, "U04A16",             "RO49AAAA1B31007593840000"));
    addSpecification(new Specification("RS", 22, "F03F13F02",          "RS35260005601001611379"));
    addSpecification(new Specification("SA", 24, "F02A18",             "SA0380000000608010167519"));
    addSpecification(new Specification("SE", 24, "F03F16F01",          "SE4550000000058398257466"));
    addSpecification(new Specification("SI", 19, "F05F08F02",          "SI56263300012039086"));
    addSpecification(new Specification("SK", 24, "F04F06F10",          "SK3112000000198742637541"));
    addSpecification(new Specification("SM", 27, "U01F05F05A12",       "SM86U0322509800000000270100"));
    addSpecification(new Specification("ST", 25, "F08F11F02",          "ST68000100010051845310112"));
    addSpecification(new Specification("TL", 23, "F03F14F02",          "TL380080012345678910157"));
    addSpecification(new Specification("TN", 24, "F02F03F13F02",       "TN5910006035183598478831"));
    addSpecification(new Specification("TR", 26, "F05F01A16",          "TR330006100519786457841326"));
    addSpecification(new Specification("VG", 24, "U04F16",             "VG96VPVG0000012345678901"));
    addSpecification(new Specification("XK", 20, "F04F10F02",          "XK051212012345678906"));

    // Angola
    addSpecification(new Specification("AO", 25, "F21",                "AO69123456789012345678901"));
    // Burkina
    addSpecification(new Specification("BF", 27, "F23",                "BF2312345678901234567890123"));
    // Burundi
    addSpecification(new Specification("BI", 16, "F12",                "BI41123456789012"));
    // Benin
    addSpecification(new Specification("BJ", 28, "F24",                "BJ39123456789012345678901234"));
    // Ivory
    addSpecification(new Specification("CI", 28, "U01F23",             "CI17A12345678901234567890123"));
    // Cameron
    addSpecification(new Specification("CM", 27, "F23",                "CM9012345678901234567890123"));
    // Cape Verde
    addSpecification(new Specification("CV", 25, "F21",                "CV30123456789012345678901"));
    // Algeria
    addSpecification(new Specification("DZ", 24, "F20",                "DZ8612345678901234567890"));
    // Iran
    addSpecification(new Specification("IR", 26, "F22",                "IR861234568790123456789012"));
    // Jordan
    addSpecification(new Specification("JO", 30, "A04F22",             "JO15AAAA1234567890123456789012"));
    // Madagascar
    addSpecification(new Specification("MG", 27, "F23",                "MG1812345678901234567890123"));
    // Mali
    addSpecification(new Specification("ML", 28, "U01F23",             "ML15A12345678901234567890123"));
    // Mozambique
    addSpecification(new Specification("MZ", 25, "F21",                "MZ25123456789012345678901"));
    // Quatar
    addSpecification(new Specification("QA", 29, "U04A21",             "QA30AAAA123456789012345678901"));
    // Senegal
    addSpecification(new Specification("SN", 28, "U01F23",             "SN52A12345678901234567890123"));
    // Ukraine
    addSpecification(new Specification("UA", 29, "F25",                "UA511234567890123456789012345"));

    var NON_ALPHANUM = /[^a-zA-Z0-9]/g,
        EVERY_FOUR_CHARS =/(.{4})(?!$)/g;

    /**
     * Utility function to check if a variable is a String.
     *
     * @param v
     * @returns {boolean} true if the passed variable is a String, false otherwise.
     */
    function isString(v){
        return (typeof v == 'string' || v instanceof String);
    }

    /**
     * Check if an IBAN is valid.
     *
     * @param {String} iban the IBAN to validate.
     * @returns {boolean} true if the passed IBAN is valid, false otherwise
     */
    exports.isValid = function(iban){
        if (!isString(iban)){
            return false;
        }
        iban = electronicFormat(iban);
        var countryStructure = countries[iban.slice(0,2)];
        return !!countryStructure && countryStructure.isValid(iban);
    };

    /**
     * Convert an IBAN to a BBAN.
     *
     * @param iban
     * @param {String} [separator] the separator to use between the blocks of the BBAN, defaults to ' '
     * @returns {string|*}
     */
    exports.toBBAN = function(iban, separator){
        if (typeof separator == 'undefined'){
            separator = ' ';
        }
        iban = electronicFormat(iban);
        var countryStructure = countries[iban.slice(0,2)];
        if (!countryStructure) {
            throw new Error('No country with code ' + iban.slice(0,2));
        }
        return countryStructure.toBBAN(iban, separator);
    };

    /**
     * Convert the passed BBAN to an IBAN for this country specification.
     * Please note that <i>"generation of the IBAN shall be the exclusive responsibility of the bank/branch servicing the account"</i>.
     * This method implements the preferred algorithm described in http://en.wikipedia.org/wiki/International_Bank_Account_Number#Generating_IBAN_check_digits
     *
     * @param countryCode the country of the BBAN
     * @param bban the BBAN to convert to IBAN
     * @returns {string} the IBAN
     */
    exports.fromBBAN = function(countryCode, bban){
        var countryStructure = countries[countryCode];
        if (!countryStructure) {
            throw new Error('No country with code ' + countryCode);
        }
        return countryStructure.fromBBAN(electronicFormat(bban));
    };

    /**
     * Check the validity of the passed BBAN.
     *
     * @param countryCode the country of the BBAN
     * @param bban the BBAN to check the validity of
     */
    exports.isValidBBAN = function(countryCode, bban){
        if (!isString(bban)){
            return false;
        }
        var countryStructure = countries[countryCode];
        return countryStructure && countryStructure.isValidBBAN(electronicFormat(bban));
    };

    /**
     *
     * @param iban
     * @param separator
     * @returns {string}
     */
    exports.printFormat = function(iban, separator){
        if (typeof separator == 'undefined'){
            separator = ' ';
        }
        return electronicFormat(iban).replace(EVERY_FOUR_CHARS, "$1" + separator);
    };

    exports.electronicFormat = electronicFormat;
    /**
     * An object containing all the known IBAN specifications.
     */
    exports.countries = countries;

}));
// source --> https://homelive.pt/wp-content/plugins/super-forms/assets/js/frontend/masked-input.js?ver=6.3.312 
/* eslint-disable no-self-assign */
/* eslint-disable no-mixed-spaces-and-tabs */
/* eslint-disable no-undef */
// jshint ignore: start
/*
    jQuery Masked Input Plugin
    Copyright (c) 2007 - 2015 Josh Bush (digitalbush.com)
    Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
    Version: 1.4.1
*/
(function(factory) {
    "use strict";
    if (
        typeof exports === "object" &&
        exports &&
        typeof module === "object" &&
        module &&
        module.exports === exports
    ) {
        // Browserify. Attach to jQuery module.
        factory(require("jquery"));
    } else if (typeof define === "function" && define.amd) {
        // AMD. Register as an anonymous module.
        define(["jquery"], factory);
    } else {
        // Browser globals
        factory(jQuery);
    }
})(function($) {
    "use strict";
    var caretTimeoutId, ua = navigator.userAgent,
        iPhone = /iphone/i.test(ua),
        chrome = /chrome/i.test(ua),
        android = /android/i.test(ua);
    $.mask = {
        definitions: {
            "9": "[0-9]",
            a: "[A-Za-z]",
            "*": "[A-Za-z0-9]"
        },
        autoclear: !0,
        dataName: "rawMaskFn",
        placeholder: "_"
    };
    $.fn.extend({
        caret: function(begin, end) {
            var range;
            if (0 !== this.length && !this.is(":hidden")) return "number" == typeof begin ? (end = "number" == typeof end ? end : begin,
                this.each(function() {
                    if (this.setSelectionRange) {
                        this.setSelectionRange(begin, end);
                    } else {
                        if (this.createTextRange) {
                            range = this.createTextRange();
                            range.collapse(!0);
                            range.moveEnd("character", end);
                            range.moveStart("character", begin);
                            range.select();
                        }
                    }
                })) : (this[0].setSelectionRange ? (begin = this[0].selectionStart, end = this[0].selectionEnd) : document.selection && document.selection.createRange && (range = document.selection.createRange(),
                begin = 0 - range.duplicate().moveStart("character", -1e5), end = begin + range.text.length), {
                begin: begin,
                end: end
            });
        },
        unmask: function() {
            return this.trigger("unmask");
        },
        mask: function(mask, settings) {
            mask = String(mask);
            var input, defs, tests, partialPosition, firstNonMaskPos, lastRequiredNonMaskPos, len, oldVal;
            if (!mask && this.length > 0) {
                input = $(this[0]);
                var fn = input.data($.mask.dataName);
                return fn ? fn() : void 0;
            }
            return settings = $.extend({
                    autoclear: $.mask.autoclear,
                    placeholder: $.mask.placeholder,
                    completed: null
                }, settings),
                defs = $.mask.definitions,
                tests = [],
                partialPosition = len = mask.length,
                firstNonMaskPos = null,

                $.each(mask.split(""), function(i, c) {
                    if ("?" == c) {
                        len--;
                        partialPosition = i;
                    } else {
                        if (defs[c]) {
                            tests.push(new RegExp(defs[c]));
                            if (null === firstNonMaskPos) {
                                firstNonMaskPos = tests.length - 1;
                            }
                            if (partialPosition > i) {
                                lastRequiredNonMaskPos = tests.length - 1;
                            }
                        } else {
                            tests.push(null);
                        }
                    }
                }),
                this.trigger("unmask").each(function() {
                    function tryFireCompleted() {
                        if (settings.completed) {
                            for (var i = firstNonMaskPos; lastRequiredNonMaskPos >= i; i++)
                                if (tests[i] && buffer[i] === getPlaceholder(i)) return;
                            settings.completed.call(input);
                        }
                    }

                    function getPlaceholder(i) {
                        return settings.placeholder.charAt(i < settings.placeholder.length ? i : 0);
                    }

                    function seekNext(pos) {
                        for (; ++pos < len && !tests[pos];);
                        return pos;
                    }

                    function seekPrev(pos) {
                        for (; --pos >= 0 && !tests[pos];);
                        return pos;
                    }

                    function shiftL(begin, end) {
                        var i, j;
                        if (0 <= begin) {
                            for (i = begin, j = seekNext(end); len > i; i++)
                                if (tests[i]) {
                                    if (!(len > j && tests[i].test(buffer[j]))) break;
                                    buffer[i] = buffer[j];
                                    buffer[j] = getPlaceholder(j);
                                    j = seekNext(j);
                                }
                            writeBuffer();
                            input.caret(Math.max(firstNonMaskPos, begin));
                        }
                    }

                    var shiftR = function (pos) {
                        var i, c, j, t;
                        for (i = pos, c = getPlaceholder(pos); len > i; i++)
                            if (tests[i]) {
                                if (j = seekNext(i), t = buffer[i], buffer[i] = c, !(len > j && tests[j].test(t))) break;
                                c = t;
                            }
                    };

                    var androidInputEvent = function() {
                        var curVal = input.val(),
                            pos = input.caret();
                        if (oldVal && oldVal.length && oldVal.length > curVal.length) {
                            for (checkVal(!0); pos.begin > 0 && !tests[pos.begin - 1];) pos.begin--;
                            if (0 === pos.begin)
                                for (; pos.begin < firstNonMaskPos && !tests[pos.begin];) pos.begin++;
                            input.caret(pos.begin, pos.begin);
                        } else {
                            for (checkVal(!0); pos.begin < len && !tests[pos.begin];) pos.begin++;
                            input.caret(pos.begin, pos.begin);
                        }
                        tryFireCompleted();
                    };

                    var blurEvent = function() {
                        checkVal();
                        if (input.val() != focusText) {
                            input.change();
                        }
                    };

                    var KeydownEvent = function(e) {
                        if (!input.prop("readonly")) {
                            var pos, begin, end, k = e.which || e.keyCode;
                            oldVal = input.val();
                            if(8 === k || 46 === k || iPhone && 127 === k){ 
                        		pos = input.caret();
                            	begin = pos.begin;
                            	end = pos.end;
                            	if(end - begin === 0){
                            		if(46 !== k){
                            			begin = seekPrev(begin);
                            		}else{
                            			end = seekNext(begin - 1);
                            		}
                            		if(46 === k){
                            			end = seekNext(end);
                            		}else{
                            			end = end;
                            		}
                            	}
                                clearBuffer(begin, end); 
                                shiftL(begin, end - 1);
                            	e.preventDefault();
                            }else{ 
                            	if(13 === k){
                            		blurEvent.call(this, e);
                            	}else{
                            		if(27 === k){
										input.val(focusText);
                                		input.caret(0, checkVal());
                                		e.preventDefault();
                            		}
                            	}
                            }
                        }
                    };

                    var keypressEvent = function(e) {
                        if (!input.prop("readonly")) {
                            var p, c, next, k = e.which || e.keyCode,
                                pos = input.caret();
                            if (!(e.ctrlKey || e.altKey || e.metaKey || 32 > k) && k && 13 !== k) {
                                if (pos.end - pos.begin !== 0 && (clearBuffer(pos.begin, pos.end), shiftL(pos.begin, pos.end - 1)),
                                    p = seekNext(pos.begin - 1), len > p && (c = String.fromCharCode(k), tests[p].test(c))) {
                                    // Transform to uppercase?
                                    if($(this).parents('.super-shortcode:eq(0)').hasClass('super-uppercase')){
                                        c = c.toUpperCase();
                                    }
                                    if (shiftR(p), buffer[p] = c, writeBuffer(), next = seekNext(p), android) {
                                        var proxy = function() {
                                            $.proxy($.fn.caret, input, next)();
                                        };
                                        setTimeout(proxy, 0);
                                    } else {
                                    	input.caret(next);
                                    }
                                    if(pos.begin <= lastRequiredNonMaskPos) tryFireCompleted();
                                }
                                e.preventDefault();
                            }
                        }
                    };

                    var clearBuffer = function(start, end) {
                        var i;
                        for (i = start; end > i && len > i; i++) {
                        	if(tests[i]){
                        		buffer[i] = getPlaceholder(i);
                        	}
                        }
                    };

                    var writeBuffer = function() {
                        input.val(buffer.join(""));
                    };

                    var checkVal = function(allow) {
                        var i, c, pos, test = input.val(),
                            lastMatch = -1;
                        for (i = 0, pos = 0; len > i; i++)
                            if (tests[i]) {
                                for (buffer[i] = getPlaceholder(i); pos++ < test.length;)
                                    if ( c = test.charAt(pos - 1), tests[i].test(c) ) {
                                        buffer[i] = c;
                                    	lastMatch = i;
                                        break;
                                    }
                                if (pos > test.length) {
                                    clearBuffer(i + 1, len);
                                    break;
                                }
                            } else {
                            	if(buffer[i] === test.charAt(pos)) {
                            		pos++;
                            		if(partialPosition > i) {
                            			lastMatch = i;
                            		}
                            	}
                            }
                        return allow ? writeBuffer() : partialPosition > lastMatch + 1 ? settings.autoclear || buffer.join("") === defaultBuffer ? (input.val() && input.val(""),
                                clearBuffer(0, len)) : writeBuffer() : (writeBuffer(), input.val(input.val().substring(0, lastMatch + 1))),
                            partialPosition ? i : firstNonMaskPos;
                    };
                    var input = $(this);
                    var buffer = $.map(mask.split(""), function(c, i) {
                        return "?" != c ? defs[c] ? getPlaceholder(i) : c : void 0;
                    });
                    var defaultBuffer = buffer.join("");
                    var focusText = input.val();
                    input.data($.mask.dataName, function() {
						return $.map(buffer, function(c, i) {
					        return tests[i] && c != getPlaceholder(i) ? c : null;
					    }).join("");
					});
                    input.one("unmask", function() {
                    	input.off(".mask").removeData($.mask.dataName);
                    });
                    input.on("focus.mask", function() {
                        if (!input.prop("readonly")) {
                            clearTimeout(caretTimeoutId);
                            var pos = checkVal();
                            caretTimeoutId = setTimeout(function() {
                                if(input.get(0) === document.activeElement){
                                	writeBuffer();
                                	if(pos == mask.replace("?", "").length){
                                		input.caret(0, pos);
                                	}else{
                                		input.caret(pos);
                                	}
                                }
                            }, 10);
                        }
                    });
                    input.on("blur.mask", blurEvent).on("keydown.mask", KeydownEvent).on("keypress.mask", keypressEvent).on("input.mask paste.mask", function() {
                        if(input.prop("readonly")){
                        	setTimeout(function() {
                            	var pos = checkVal(!0);
                            	input.caret(pos);
                            	tryFireCompleted();
                        	}, 0);
                        }
                    });
                    if(chrome && android){
                    	input.off("input.mask").on("input.mask", androidInputEvent);
                    }
                    checkVal();
                });
        }
    });
});
// source --> https://homelive.pt/wp-content/plugins/super-forms/assets/js/backend/simpleslider.js?ver=6.3.312 
// jshint ignore: start
/*
 jQuery Simple Slider

 Copyright (c) 2012 James Smith (http://loopj.com)

 Licensed under the MIT license (http://mit-license.org/)
*/

(function($) {
    "use strict";

    var __slice = [].slice,
        __indexOf = [].indexOf || function(item) {
            for (var i = 0, l = this.length; i < l; i++) {
                if (i in this && this[i] === item) return i;
            }
            return -1;
        };
    
    var SimpleSlider;
    SimpleSlider = (function() {

        function SimpleSlider(input, options) {
            var ratio,
                _this = this;
            this.input = input;
            this.defaultOptions = {
                animate: true,
                snapMid: false,
                classPrefix: null,
                classSuffix: null,
                theme: null,
                highlight: false
            };
            this.settings = $.extend({}, this.defaultOptions, options);
            if (this.settings.theme) {
                this.settings.classSuffix = "-" + this.settings.theme;
            }
            this.input.hide();
            this.slider = $("<div>").addClass("slider" + (this.settings.classSuffix || "")).css({
                position: "relative",
                userSelect: "none",
                boxSizing: "border-box"
            }).insertBefore(this.input);
            if (this.input.attr("id")) {
                this.slider.attr("id", this.input.attr("id") + "-slider");
            }
            this.track = this.createDivElement("track").css({
                width: "100%"
            });
            if (this.settings.highlight) {
                this.highlightTrack = this.createDivElement("highlight-track").css({
                    width: "0"
                });
            }
            this.dragger = this.createDivElement("dragger");
            this.slider.css({
                minHeight: this.dragger.outerHeight(),
                marginLeft: this.dragger.outerWidth() / 2,
                marginRight: this.dragger.outerWidth() / 2
            });
            this.track.css({
                marginTop: this.track.outerHeight() / -2
            });
            if (this.settings.highlight) {
                this.highlightTrack.css({
                    marginTop: this.track.outerHeight() / -2
                });
            }
            this.dragger.css({
                marginTop: this.dragger.outerHeight() / -2,
                marginLeft: this.dragger.outerWidth() / -2
            });
            this.track.mousedown(function(e) {
                return _this.trackEvent(e);
            });
            if (this.settings.highlight) {
                this.highlightTrack.mousedown(function(e) {
                    return _this.trackEvent(e);
                });
            }
            this.dragger.mousedown(function(e) {
                if (e.which !== 1) {
                    return;
                }
                _this.dragging = true;
                _this.dragger.addClass("dragging");
                _this.domDrag(e.pageX, e.pageY);
                return false;
            });
            $("body").mousemove(function(e) {
                if (_this.dragging) {
                    _this.domDrag(e.pageX, e.pageY);
                    return $("body").css({
                        cursor: "pointer"
                    });
                }
            }).mouseup(function() {
                if (_this.dragging) {
                    _this.dragging = false;
                    _this.dragger.removeClass("dragging");
                    return $("body").css({
                        cursor: "auto"
                    });
                }
            });
            this.pagePos = 0;
            if (this.input.val() === "") {
                this.value = this.getRange().min;
                this.input.val(this.value);
            } else {
                this.value = this.nearestValidValue(this.input.val());
            }
            this.setSliderPositionFromValue(this.value);
            ratio = this.valueToRatio(this.value);
            this.input.trigger("slider:ready", {
                value: this.value,
                ratio: ratio,
                position: ratio * this.slider.outerWidth(),
                el: this.slider
            });

            // Zacky: mobile support
            this.dragger.bind('touchstart', function(e) {
                _this.dragging = true;
                _this.dragger.addClass("dragging");
                _this.domDrag(e.originalEvent.touches[0].pageX, e.originalEvent.touches[0].pageY);
                return false;
            });

            $("body").bind('touchmove', function(e) {
                if (_this.dragging) {
                    _this.domDrag(e.originalEvent.touches[0].pageX, e.originalEvent.touches[0].pageY);
                    return false;
                }
            }).bind('touchend', function() {
                if (_this.dragging) {
                    _this.dragging = false;
                    _this.dragger.removeClass("dragging");
                    return $("body").css({
                        cursor: "auto"
                    });
                }
            });
        }

        SimpleSlider.prototype.createDivElement = function(classname) {
            var item;
            item = $("<div>").addClass(classname).css({
                position: "absolute",
                top: "50%",
                userSelect: "none",
                cursor: "pointer"
            }).appendTo(this.slider);
            return item;
        };

        SimpleSlider.prototype.setRatio = function(ratio) {
            var value;
            ratio = Math.min(1, ratio);
            ratio = Math.max(0, ratio);
            value = this.ratioToValue(ratio);
            this.setSliderPositionFromValue(value);
            return this.valueChanged(value, ratio, "setRatio");
        };

        SimpleSlider.prototype.setValue = function(value) {
            var ratio;
            value = this.nearestValidValue(value);
            ratio = this.valueToRatio(value);
            this.setSliderPositionFromValue(value);
            return this.valueChanged(value, ratio, "setValue");
        };

        SimpleSlider.prototype.trackEvent = function(e) {
            if (e.which !== 1) {
                return;
            }
            this.domDrag(e.pageX, e.pageY, true);
            this.dragging = true;
            return false;
        };

        SimpleSlider.prototype.domDrag = function(pageX, pageY, animate) {
            var pagePos, ratio, value;
            if (animate == null) {
                animate = false;
            }
            pagePos = pageX - this.slider.offset().left;
            pagePos = Math.min(this.slider.outerWidth(), pagePos);
            pagePos = Math.max(0, pagePos);
            if (this.pagePos !== pagePos) {
                this.pagePos = pagePos;
                ratio = pagePos / this.slider.outerWidth();
                value = this.ratioToValue(ratio);
                this.valueChanged(value, ratio, "domDrag");
                if (this.settings.snap) {
                    return this.setSliderPositionFromValue(value, animate);
                } else {
                    return this.setSliderPosition(pagePos, animate);
                }
            }
        };

        SimpleSlider.prototype.setSliderPosition = function(position, animate) {
            if (animate == null) {
                animate = false;
            }
            if (animate && this.settings.animate) {
                this.dragger.animate({
                    left: position
                }, 200);
                if (this.settings.highlight) {
                    return this.highlightTrack.animate({
                        width: position
                    }, 200);
                }
            } else {
                this.dragger.css({
                    left: position
                });
                if (this.settings.highlight) {
                    return this.highlightTrack.css({
                        width: position
                    });
                }
            }
        };

        SimpleSlider.prototype.setSliderPositionFromValue = function(value, animate) {
            var ratio;
            if (animate == null) {
                animate = false;
            }
            ratio = this.valueToRatio(value);
            return this.setSliderPosition(ratio * this.slider.outerWidth(), animate);
        };

        SimpleSlider.prototype.getRange = function() {
            if (this.settings.allowedValues) {
                return {
                    min: Math.min.apply(Math, this.settings.allowedValues),
                    max: Math.max.apply(Math, this.settings.allowedValues)
                };
            } else if (this.settings.range) {
                return {
                    min: parseFloat(this.settings.range[0]),
                    max: parseFloat(this.settings.range[1])
                };
            } else {
                return {
                    min: 0,
                    max: 1
                };
            }
        };

        SimpleSlider.prototype.nearestValidValue = function(rawValue) {
            var closest, maxSteps, range, steps;
            range = this.getRange();
            rawValue = Math.min(range.max, rawValue);
            rawValue = Math.max(range.min, rawValue);
            if (this.settings.allowedValues) {
                closest = null;
                $.each(this.settings.allowedValues, function() {
                    if (closest === null || Math.abs(this - rawValue) < Math.abs(closest - rawValue)) {
                        closest = this;
                        return closest;
                    }
                });
                return closest;
            } else if (this.settings.step) {
                maxSteps = (range.max - range.min) / this.settings.step;
                steps = Math.floor((rawValue - range.min) / this.settings.step);
                if ((rawValue - range.min) % this.settings.step > this.settings.step / 2 && steps < maxSteps) {
                    steps += 1;
                }
                return steps * this.settings.step + range.min;
            } else {
                return rawValue;
            }
        };

        SimpleSlider.prototype.valueToRatio = function(value) {
            var allowedVal, closest, closestIdx, idx, range, _i, _len, _ref;
            if (this.settings.equalSteps) {
                _ref = this.settings.allowedValues;
                for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
                    allowedVal = _ref[idx];
                    if (!(typeof closest !== "undefined" && closest !== null) || Math.abs(allowedVal - value) < Math.abs(closest - value)) {
                        closest = allowedVal;
                        closestIdx = idx;
                    }
                }
                if (this.settings.snapMid) {
                    return (closestIdx + 0.5) / this.settings.allowedValues.length;
                } else {
                    return closestIdx / (this.settings.allowedValues.length - 1);
                }
            } else {
                range = this.getRange();
                return (value - range.min) / (range.max - range.min);
            }
        };

        SimpleSlider.prototype.ratioToValue = function(ratio) {
            var idx, range, rawValue, step, steps;
            if (this.settings.equalSteps) {
                steps = this.settings.allowedValues.length;
                step = Math.round(ratio * steps - 0.5);
                idx = Math.min(step, this.settings.allowedValues.length - 1);
                return this.settings.allowedValues[idx];
            } else {
                range = this.getRange();
                rawValue = ratio * (range.max - range.min) + range.min;
                return this.nearestValidValue(rawValue);
            }
        };

        SimpleSlider.prototype.valueChanged = function(value, ratio, trigger) {
            var eventData;
            if (value.toString() === this.value.toString()) {
                return;
            }
            value = parseFloat(value.toFixed(2));
            this.value = value;
            eventData = {
                value: value,
                ratio: ratio,
                position: ratio * this.slider.outerWidth(),
                trigger: trigger,
                el: this.slider
            };
            return this.input.val(value).trigger($.Event("change", eventData)).trigger("slider:changed", eventData);
        };

        return SimpleSlider;

    })();
    $.extend($.fn, {
        simpleSlider: function() {
            var publicMethods = ["setRatio", "setValue"],
                settingsOrMethod = arguments[0],
                params = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
            return $(this).each(function() {
                var obj, settings;
                if (settingsOrMethod && __indexOf.call(publicMethods, settingsOrMethod) >= 0) {
                    obj = $(this).data("slider-object");
                    return obj[settingsOrMethod].apply(obj, params);
                } else {
                    settings = settingsOrMethod;
                    return $(this).data("slider-object", new SimpleSlider($(this), settings));
                }
            });
        }
    });
    return $(function() {
        return $("[data-slider]").each(function() {
            var $el, allowedValues, settings, x;
            $el = $(this);
            settings = {};
            allowedValues = $el.data("slider-values");
            if (allowedValues) {
                settings.allowedValues = (function() {
                    var _i, _len, _ref, _results;
                    _ref = allowedValues.split(",");
                    _results = [];
                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
                        x = _ref[_i];
                        _results.push(parseFloat(x));
                    }
                    return _results;
                })();
            }
            if ($el.data("slider-range")) {
                settings.range = $el.data("slider-range").split(",");
            }
            if ($el.data("slider-step")) {
                settings.step = $el.data("slider-step");
            }
            settings.snap = $el.data("slider-snap");
            settings.equalSteps = $el.data("slider-equal-steps");
            if ($el.data("slider-theme")) {
                settings.theme = $el.data("slider-theme");
            }
            if ($el.attr("data-slider-highlight")) {
                settings.highlight = $el.data("slider-highlight");
            }
            if ($el.data("slider-animate") != null) {
                settings.animate = $el.data("slider-animate");
            }
            return $el.simpleSlider(settings);
        });
    });
})(this.jQuery || this.Zepto, this);
// source --> https://homelive.pt/wp-content/plugins/super-forms/assets/js/frontend/carousel.js?ver=6.3.312 
// Author: Rens Tillmann
// URL: github.com/RensTillmann/CarouselJS
// Description: A lightweight carousel/slider script, designed for `Super Forms`

"use strict";
var CarouselJS = {

    // Settings & Options
    settings: {
        customClass: 'super-carousel',  // A custom class to be added on the container
        selector: '.carouseljs',        // Selector to intialize the carousel element
        method: 'multi',                // This determines how the slide should be executed
                                        // `single` : slide only one item forward/backward at a time
                                        // `multi` : slide all visible items forward/backward up to "nextItem"
        layout: 'grid',                 // Choose what layout to use
                                        // `grid` : use flex grid, allowing you to only display a specific amount of items per slide 
                                        // `auto` : puts each item simply behind eachother, not caring about how many are visible
        columns: 4,                     // The items per slide (only works when `grid` layout is enabled)
                                        // This will basically create slides of X items each
                                        // Each item will get a width based on the carousel container width
                                        // For instance: if the carousel is 900px in width, each element would be 300px in width when
                                        // this option is set to `columns: 3`
        minwidth: 100,                  // Define the minimum width an item must have before applying responsive settings.
                                        // For instance let's say the screen size of the device is 768 (iPad).
                                        // And let's assume that our carousel is inside a 100% width element meaning our carousel wrapper is 768 in width.
                                        // And let's assume we have defined `columns: 5` (5 items per slide).
                                        // 5x200=1000 (exceeds the width of the carousel wrapper which is 768).
                                        // This means that there is not enough space to create items with a width of 200.
                                        // In that case the script will determine a new width based on the 768 wrapper width.
                                        // It always first checks if 1000 is below the wrapper width, if it is below this, it will decrease the `columns: 5`.
                                        // It then checks if the new width of 800 is below the wrapper width, if not, it repeats the above.
                                        // The next check would be done with `columns: 3` resulting in a 600 width total against 768.
                                        // Of course this means that there is still some space left unused.
                                        // To solve this we would simply devide 768 by 3 to get the width for each item
                                        // In case there is only room for 1 item, it will apply 100% width on the item
        
        // Navigation
        navigation: true,                       // Display Prev/Next buttons (true|false)
        dots: true,                             // Display "Dots" naviagtion below the slider

        // Colors
        trackBg: '',        // Background color for the slider (track background)
        itemBg: '',         // Background color for each item

        // Items
        itemsMargin: '10px 10px 10px 10px',     // Define margin for each item
        itemsPadding: '',    // Define padding for each item

        // Animation
        animationSpeed: 0.3,                    // The scroll animation speed in seconds
        
        // Custom buttons HTML
        buttons: {
            previous: {
                html: ''    // HTML for inside the "prev/backward" button (leave blank for default buttons)
            },
            next: {
                html: ''    // HTML for inside the "next/forward" button (leave blank for default buttons)
            }
        },
    },

    // "action" holds the type of action to trigger the slide e.g `next` `prev`
    // ...you could think of it as the "direction" (forward/backward)
    trigger: function(button, action) {
        // If triggered via Dot navigation
        if(action=='dot'){
            // Look left of dot for "current" dot
            if(button.classList.contains('current')){
                // First check if the dot itself is the current, if so do nothing]
            }else{
                var prevDot = button,
                    nextDot = button,
                    nextButton = null,
                    i = 0,
                    direction = '',
                    clicked = 0;
                while (prevDot = prevDot.previousElementSibling) {
                    i++;
                    if(prevDot.classList.contains('carouseljs-current')){
                        prevDot.classList.remove('carouseljs-current');
                        direction = 'right';
                        break;
                    }
                }
                // If no direction is known at this point it means that we did not found the current on the left side
                if(direction==''){
                    i = 0;
                    while (nextDot = nextDot.nextElementSibling) {
                        i++;
                        if(nextDot.classList.contains('carouseljs-current')){
                            nextDot.classList.remove('carouseljs-current');
                            direction = 'left';
                            break;
                        }
                    }
                }
                if(direction=='right'){
                    // If we need to slide right
                    nextButton = button.parentNode.parentNode.querySelector('.next');
                }else{
                    // If we need to slide left
                    nextButton = button.parentNode.parentNode.querySelector('.prev');
                }
                // Click the next or prev button X times
                while (clicked < i){
                    nextButton.click();
                    clicked++;
                }
                // After sliding update "carouseljs-current" class
                button.classList.add('carouseljs-current');
            }
        }else{
            this._setters(button, action);
            this.doSlide();
        }
    },

    // Setters
    _setters: function(node, action) {
        this._self = node.parentNode;
        this._action = action;
        this._containerWidth = this.itemWidth(this._self);
        this._carouselTrack = this._self.querySelector('.carouseljs-track');
        this._currentItem = this._carouselTrack.querySelector('.carouseljs-current');
        this._currentItemWidth = this.itemWidth(this._currentItem);
        this._totalScrolled = (this._carouselTrack.style.marginLeft !== '' ? parseFloat(this._carouselTrack.style.marginLeft) : 0);
        this._dotNav = this._self.querySelector('.carouseljs-dots');
        if(this._dotNav) this._currentDot = this._dotNav.querySelector('.carouseljs-current');
    },
    _self: null,                 // Reference
    _containerWidth: null,       // The total width of the container
    _nextItem: null,             // The next item is the first item that is not completely visible
    _nextItemWidth: null,        // This is the width of the "nextItem" that was found
    _currentItem: null,          // Returns the first visible item in the slider
    _currentItemWidth: null,     // Returns the width of "currentItem"
    _carouselTrack: null,        // Holds the "track" of all items, this is the element that we will be animating
    _totalScrolled: null,        // Current amount the carousel was scrolled
    _dotNav: null,               // Element that holds dots navigation items
    _currentDot: null,           // Current dot navigation item

    // Slide carousel forward or backward 
    doSlide: function() {
        var _ = this.settings,
            nextNode = this._currentItem,
            width = this._currentItemWidth;

        if (this._action == 'next') {
            if (this.overlapRight() > 0) {
                width = this.overlapRight();
            }
        }
        
        // Single step method
        if (_.method == 'single' && this._action == 'next') {
            while (nextNode = nextNode.nextElementSibling) {
                width += this.itemWidth(nextNode);
                if (width > this._containerWidth) {
                    this.slideCarousel(width-this._containerWidth); // Slide carousel
                    // Update current item only if current item is no longer visible
                    if (this.overlapRight(width-this._containerWidth) <= 0) {
                        this.updateCurrentItem(this._currentItem.nextElementSibling); // Update current item
                    }
                    break;
                }
            }
        }
        if (_.method == 'single' && this._action == 'prev') {
            if (this.overlapLeft() > 0) {
                this.slideCarousel(this.overlapLeft()); // Slide carousel
            } else {
                // Simply grab previous sibling width and scroll
                if (this._currentItem.previousElementSibling) {
                    this.updateCurrentItem(this._currentItem.previousElementSibling); // Update current item
                    this.slideCarousel(this.itemWidth(this._currentItem.previousElementSibling)); // Slide carousel
                }
            }
        }

        // Multi method
        if (_.method == 'multi' && this._action == 'next') {
            while (nextNode = nextNode.nextElementSibling) {
                width += this.itemWidth(nextNode);
                if (width > this._containerWidth) {
                    
                    // Before scrolling, check if next item + next siblings width does not exceed container width
                    // If this is the case we can simply scroll to the last item of the carousel
                    var nextSibling = nextNode;
                    var siblingsWidth = (this.itemWidth(nextNode) - (this.itemWidth(nextNode) - (width - this._containerWidth)));
                    while (nextSibling = nextSibling.nextElementSibling) {
                        siblingsWidth += this.itemWidth(nextSibling);
                    }
                    if (siblingsWidth < this._containerWidth) {
                        this.slideCarousel(siblingsWidth); // Slide carousel
                        this.updateCurrentItem(nextNode.previousElementSibling); // Update current item
                    } else {
                        this.slideCarousel(width-this.itemWidth(nextNode)); // Slide carousel
                        this.updateCurrentItem(nextNode); // Update current item
                    }
                    break;
                }
            }
        }
        if (_.method == 'multi' && this._action == 'prev') {
            // We are at the beginning of the carousel, no need to do anything
            if (this._totalScrolled >= 0) {
                // Silence is golden
            } else {
                var overlapLeft = this.overlapLeft();
                if (overlapLeft > 0) {
                    // In this case we will scroll the item to the far right of the container so that the item becomes fully visible
                    // and so that the other items next (previous items really) will also become visible as much as possible
                    while (nextNode = nextNode.nextElementSibling) {
                        width += this.itemWidth(nextNode);
                        if (width > this._containerWidth) {
                            // Before scrolling, check if next item + next siblings width does not exceed container width
                            // If this is the case we can simply scroll to the last item of the carousel
                            var nextSibling = this._currentItem;
                            var siblingsWidth = overlapLeft;
                            var firstNode = null;
                            while (nextSibling = nextSibling.previousElementSibling) {
                                siblingsWidth += this.itemWidth(nextSibling);
                                firstNode = nextSibling;
                            }
                            if (siblingsWidth < this._containerWidth) {
                                this.slideCarousel(siblingsWidth); // Slide carousel
                                this.updateCurrentItem(firstNode); // Update current item
                            } else {
                                this.slideCarousel(width-this._currentItemWidth); // Slide carousel
                                nextNode = this._currentItem;
                                width = this._currentItemWidth;
                                while (nextNode = nextNode.previousElementSibling) {
                                    width += this.itemWidth(nextNode);
                                    if (width > this._containerWidth) {
                                        this.updateCurrentItem(nextNode); // Update current item
                                        break;
                                    }
                                }
                            }
                            break;
                        }
                    }
                } else {
                    width = 0;
                    var firstNode = null;
                    while (nextNode = nextNode.previousElementSibling) {
                        firstNode = nextNode;
                        width += this.itemWidth(nextNode);
                        if (width >= this._containerWidth) {
                            this.updateCurrentItem(nextNode); // Update current item
                            this.slideCarousel(this._containerWidth); // Slide carousel
                            break;
                        }
                    }
                    if (width <= this._containerWidth) {
                        this.updateCurrentItem(firstNode); // Update current item
                        this.slideCarousel(width); // Slide carousel
                    }
                }
            }
        }
    },
    updateCurrentItem: function(next) {
        if(next){
            this._currentItem.classList.remove('carouseljs-current');
            next.classList.add('carouseljs-current');
        }
    },
    updateDots: function(){
        // Update dots
        if(this._currentDot) {
            this._currentDot.classList.remove('carouseljs-current');
            if(this._action=='next'){
                if(this._currentDot.nextElementSibling){
                    this._currentDot.nextElementSibling.classList.add('carouseljs-current');
                }
            }else{
                if(this._currentDot.previousElementSibling){
                    this._currentDot.previousElementSibling.classList.add('carouseljs-current');
                }
            }
        }
    },
    slideCarousel: function(amount, node=null) {
        if(!node){
            if(this._action=='next'){
                amount = this._totalScrolled - amount; // If sliding forward (next)
            }else{
                amount = this._totalScrolled + amount; // If sliding backward (previous)
            }
            this.updateDots();
            // Amount to slide can not be above 0, let's make sure of that
            if(amount>0) amount = 0;
            // Slide carousel track
            this._carouselTrack.style.marginLeft = amount + 'px';
        }else{
            // Aso reset current to the first item
            // We could also adjust the marginLeft property upon resizing the window
            // but this is just the easy way around, and it's not that important
            node.carousel.querySelector('.carouseljs-current').classList.remove('carouseljs-current');
            node.carousel.firstElementChild.classList.add('carouseljs-current');
            node.carousel.style.marginLeft = amount + 'px'; 

            // If reset to start, update dot navigation
            if(node.dots){
                if(node.dots.querySelector('.carouseljs-current')) node.dots.querySelector('.carouseljs-current').classList.remove('carouseljs-current');
                node.dots.firstElementChild.classList.add('carouseljs-current');
            }
        }
    },
    overlapLeft: function() {
        return this._currentItemWidth - this.overlapRight();
    },
    overlapRight: function(visible) {
        var node = this._currentItem,
            width = this._currentItemWidth;
        while (node = node.previousElementSibling) {
            width += this.itemWidth(node);
        }
        if(this.settings.method=='single'){
            if(typeof visible === 'undefined') visible = 0;
            return (this._totalScrolled-visible) + width;
        }else{
            return this._totalScrolled + width;
        }
        return overlapRight;
    },
    itemWidth: function(node){
        var style = window.getComputedStyle ? getComputedStyle(node, null) : node.currentStyle,
            marginLeft = parseFloat(style.marginLeft) || 0,
            marginRight = parseFloat(style.marginRight) || 0;
        if(node.classList.contains('carouseljs-wrapper')){
            var paddingLeft = parseFloat(style.paddingLeft) || 0,
                paddingRight = parseFloat(style.paddingRight) || 0;
            return node.offsetWidth+(marginLeft+marginRight)-(paddingLeft+paddingRight);
        } 
        return node.offsetWidth+(marginLeft+marginRight);
    },
    setMarginPadding: function(node){
        var _ = this.settings;
        if(_.itemsMargin!='') node.style.margin = _.itemsMargin;
        if(_.itemsPadding!='') node.style.padding = _.itemsPadding;
        // First get the window width
        // Based on this we will adjust the margin/paddings based on screen size
        var windowWidth = window.innerWidth;
        if(windowWidth<1000){
            node.style.marginLeft = ((parseFloat(node.style.marginLeft)/100)*(windowWidth/20));
            node.style.marginRight = ((parseFloat(node.style.marginRight)/100)*(windowWidth/20));
            node.style.paddingLeft = ((parseFloat(node.style.paddingLeft)/100)*(windowWidth/20));
            node.style.paddingRight = ((parseFloat(node.style.paddingRight)/100)*(windowWidth/20));
        }

    },

    // Redraw (resize carousel). Will make sure the carousel is responsiveness based on it's parent width
    // Will fire upon initializing, and upon window.resize event
    redraw: function(fn, _, node){

        // Merge with core settings
        _ = Object.assign(_, node.settings);
        this.slideCarousel(0, node);
        // Setup item width if `grid` layout is being used
        if(_.layout=='grid'){
            var itemWidth = Number(node.container.clientWidth / _.columns),
                columns = _.columns,
                nodes = node.carousel.children,
                len = nodes.length,
                style = null,
                i = 0,
                marginLeft, marginRight, paddingLeft, paddingRight;

            // @IMPORTANT:
            // To speed up the loop, make sure we put the margins and paddings into our cache
            // instead of calling `getComputedStyle` inside the loop on each item
            
            // First set the margin and paddings based on the settings for the first item
            fn.setMarginPadding(nodes[i]);
            // After we have set the item padding and margin, we can set it's width
            // We must substract the items margin in order to get a correct width
            style = window.getComputedStyle ? getComputedStyle(nodes[i], null) : nodes[i].currentStyle;
            marginLeft = parseFloat(style.marginLeft) || 0;
            marginRight = parseFloat(style.marginRight) || 0;
            paddingLeft = parseFloat(style.paddingLeft) || 0;
            paddingRight = parseFloat(style.paddingRight) || 0;
            
            // Set correct width
            var newItemWidth = Number(itemWidth-(marginLeft+marginRight)-(paddingLeft+paddingRight));
            // Check if item width is lower than `minwidth` setting
            while (newItemWidth < _.minwidth){
                columns--;
                // Columns may never be 0 or lower
                if(columns<=0) columns = 1;
                itemWidth = Number(node.container.clientWidth / columns),
                newItemWidth = Number(itemWidth-(marginLeft+marginRight)-(paddingLeft+paddingRight));
                if(columns==1) break;
            }

            nodes[i].style.width = newItemWidth+'px';
            // Now that we have our margin and padding loop over all other items
            for (var i = 1; i < len; i++) {
                // Set margin and paddings for the item
                fn.setMarginPadding(nodes[i]);
                // Set correct width
                nodes[i].style.width = newItemWidth+'px';
            }
            // Also update dots navigation
            if(node.dots){
                // Determine how many dots we need to display
                var newTotal = Math.ceil(node.carousel.children.length/columns); 
                var currentTotal = node.dots.children.length;
                // Find out the difference between the current amount of dots, and the amount required
                if(currentTotal < newTotal){
                    // Not enough dots, we must add some
                    var toBeAdded = newTotal-currentTotal;
                    var i = 0;
                    var html = '';
                    while(i < toBeAdded){
                         var dot = document.createElement('span');
                         dot.setAttribute("onclick", "CarouselJS.trigger(this, 'dot')");
                         node.dots.appendChild(dot);
                         i++;
                    }
                }
                if(currentTotal > newTotal){
                    // To many dots, we must remove some
                    var toBeDeleted = currentTotal-newTotal
                    var i = 1;
                    while(toBeDeleted+currentTotal > currentTotal){
                        node.dots.children[currentTotal-i].remove();
                        toBeDeleted--;
                        i++;
                    }
                }
                // Determine if we need to hide the dots or not
                // If so, make sure that we can see the prev/next buttons
                var dots = node.dots.children;
                var len = dots.length;
                var width = 0;
                for (var i = 1; i < len; i++) {
                    width += this.itemWidth(dots[i]);
                }
                if(this.itemWidth(node.container) < width){
                    node.dots.style.visibility = 'hidden';
                    node.wrapper.querySelector('.carouseljs-button.prev').style.display = 'block';
                    node.wrapper.querySelector('.carouseljs-button.next').style.display = 'block';
                }else{
                    node.dots.style.visibility = '';
                    if(_.navigation==false){
                        node.wrapper.querySelector('.carouseljs-button.prev').style.display = 'none';
                        node.wrapper.querySelector('.carouseljs-button.next').style.display = 'none';
                    }
                }
            }
        }
    },

    // Initialize CarouselJS
    init: function() {
        var fn = this; 
        var _ = fn.settings;
        // Search for DOM elements based on the selector
        if (typeof _.selector !== 'undefined' && _.selector !== '') {
            // Find and loop over all CarouselJS sliders
            var obj = document.querySelectorAll(_.selector);
            var containers = [];
            Object.keys(obj).forEach(function(key) {
                var carousel = obj[key];
                var firstElement = carousel.firstElementChild;
                // Before we do anything, check if we need to grab custom settings from the `<textarea>` element (if one exists)
                if(firstElement.tagName=='TEXTAREA'){
                    var customSettings = carousel.firstElementChild.value;
                    try {
                        customSettings = JSON.parse(customSettings);
                    } catch(e) {
                        alert(e);
                    }
                    // Merge with core settings
                    _ = Object.assign(_, customSettings);
                    // After successful merge, delete the element
                    firstElement.remove();
                }
                // Check if both navigation and dots navigations are disabled
                // If so, then we must enable at least one of the 2, in all cases we will enable the Prev/Next buttons by default
                if(_.navigation===false && _.dots===false) _.navigation = true;
                
                carousel.classList.remove('carouseljs');
                carousel.classList.add('carouseljs-track');
                carousel.firstElementChild.classList.add('carouseljs-current');
                if(_.trackBg!=='') carousel.style.backgroundColor = _.trackBg;
                // Set transitions
                carousel.style.WebkitTransition = "all " + Number(_.animationSpeed) + "s"; // Code for Safari 3.1 to 6.0
                carousel.style.transition = "all " + Number(_.animationSpeed) + "s"; // Standard syntax  
                // Set item class
                var items = carousel.children;
                for (var i = 0; i < items.length; i++) {
                    if(_.itemBg!=='') items[i].style.backgroundColor = _.itemBg;
                    items[i].classList.add('carouseljs-item');
                }
                // Create wrapper
                var wrapper = document.createElement('div');
                wrapper.classList.add('carouseljs-wrapper');
                wrapper.classList.add(_.customClass + '-wrapper');
                // Create container
                var container = document.createElement('div');
                container.classList.add('carouseljs-container');
                // Add "Previous" button
                var prevButton = document.createElement('div');
                prevButton.innerHTML = _.buttons.previous.html ? _.buttons.previous.html : '<i class="top-line"></i><i class="bottom-line"></i>';
                prevButton.setAttribute("onclick", "CarouselJS.trigger(this, 'prev')");
                prevButton.className = 'carouseljs-button prev';
                if (_.navigation === false) {
                    prevButton.style.display = 'none'; 
                }
                wrapper.appendChild(prevButton);
                // Add "Next" button
                var nextButton = document.createElement('div');
                nextButton.innerHTML = _.buttons.next.html ? _.buttons.next.html : '<i class="top-line"></i><i class="bottom-line"></i>';
                nextButton.setAttribute("onclick", "CarouselJS.trigger(this, 'next')");
                nextButton.className = 'carouseljs-button next';
                if (_.navigation === false) {
                    nextButton.style.display = 'none'; 
                }
                wrapper.appendChild(nextButton);
                // Add dots navigation if enabled
                if (_.dots === true) {
                     // Determine how many dots we need to display
                     var total = Math.ceil(carousel.children.length/_.columns), 
                         html = '<span class="carouseljs-current" onclick="CarouselJS.trigger(this, \'dot\')"></span>', // First slide is always the current one upon intialization
                         i=1;
                     while(i < total){
                         html += '<span onclick="CarouselJS.trigger(this, \'dot\')"></span>';
                         i++;
                     }
                     // Now create the dots navigation and append it to the wrapper
                     var dots = document.createElement('div');
                     dots.classList.add('carouseljs-dots');
                     dots.innerHTML = html;
                     wrapper.appendChild(dots); 

                }
                // Insert wrapper before carousel slider in the DOM tree
                carousel.parentNode.insertBefore(wrapper, carousel);
                // Move carousel slider into container
                container.appendChild(carousel);
                // Move container into wrapper
                wrapper.appendChild(container);
                // Add container to object
                containers.push({
                    wrapper: wrapper,
                    dots: dots,
                    container: container,
                    carousel: carousel,
                    settings: customSettings
                });
            });
            
            // Loop over all containers, and resize elements accordingly
            Object.keys(containers).forEach(function(key) {
                fn.redraw(fn, _, containers[key]);
                // Also redraw upon resizing window
                window.addEventListener("resize", function(){
                    fn.redraw(fn, _, containers[key]);
                });
            });

        } else {
            // Display error to the user about a missing option/setting
            alert('You forgot to define a selector in the CarouselJS options section!');
        }
    }
};
// Initialize CarouselJS
CarouselJS.init();
// source --> https://homelive.pt/wp-content/plugins/super-forms/assets/js/frontend/date-format.js?ver=6.3.312 
/* eslint-disable no-mixed-spaces-and-tabs */
/* eslint-disable no-useless-escape */
// jshint ignore: start
/**
 * @version: 1.0 Alpha-1
 * @author: Coolite Inc. http://www.coolite.com/
 * @date: 2008-05-13
 * @copyright: Copyright (c) 2006-2008, Coolite Inc. (http://www.coolite.com/). All rights reserved.
 * @license: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. 
 * @website: http://www.datejs.com/
 */
"use strict";
Date.CultureInfo = {
    name: "en-US",
    englishName: "English (United States)",
    nativeName: "English (United States)",
    dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
    abbreviatedDayNames: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
    shortestDayNames: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"],
    firstLetterDayNames: ["S", "M", "T", "W", "T", "F", "S"],
    monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
    abbreviatedMonthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
    amDesignator: "AM",
    pmDesignator: "PM",
    firstDayOfWeek: 0,
    twoDigitYearMax: 2029,
    dateElementOrder: "mdy",
    formatPatterns: {
        shortDate: "M/d/yyyy",
        longDate: "dddd, MMMM dd, yyyy",
        shortTime: "h:mm tt",
        longTime: "h:mm:ss tt",
        fullDateTime: "dddd, MMMM dd, yyyy h:mm:ss tt",
        sortableDateTime: "yyyy-MM-ddTHH:mm:ss",
        universalSortableDateTime: "yyyy-MM-dd HH:mm:ssZ",
        rfc1123: "ddd, dd MMM yyyy HH:mm:ss GMT",
        monthDay: "MMMM dd",
        yearMonth: "MMMM, yyyy"
    },
    regexPatterns: {
        jan: /^jan(uary)?/i,
        feb: /^feb(ruary)?/i,
        mar: /^mar(ch)?/i,
        apr: /^apr(il)?/i,
        may: /^may/i,
        jun: /^jun(e)?/i,
        jul: /^jul(y)?/i,
        aug: /^aug(ust)?/i,
        sep: /^sep(t(ember)?)?/i,
        oct: /^oct(ober)?/i,
        nov: /^nov(ember)?/i,
        dec: /^dec(ember)?/i,
        sun: /^su(n(day)?)?/i,
        mon: /^mo(n(day)?)?/i,
        tue: /^tu(e(s(day)?)?)?/i,
        wed: /^we(d(nesday)?)?/i,
        thu: /^th(u(r(s(day)?)?)?)?/i,
        fri: /^fr(i(day)?)?/i,
        sat: /^sa(t(urday)?)?/i,
        future: /^next/i,
        past: /^last|past|prev(ious)?/i,
        add: /^(\+|aft(er)?|from|hence)/i,
        subtract: /^(\-|bef(ore)?|ago)/i,
        yesterday: /^yes(terday)?/i,
        today: /^t(od(ay)?)?/i,
        tomorrow: /^tom(orrow)?/i,
        now: /^n(ow)?/i,
        millisecond: /^ms|milli(second)?s?/i,
        second: /^sec(ond)?s?/i,
        minute: /^mn|min(ute)?s?/i,
        hour: /^h(our)?s?/i,
        week: /^w(eek)?s?/i,
        month: /^m(onth)?s?/i,
        day: /^d(ay)?s?/i,
        year: /^y(ear)?s?/i,
        shortMeridian: /^(a|p)/i,
        longMeridian: /^(a\.?m?\.?|p\.?m?\.?)/i,
        timezone: /^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt|utc)/i,
        ordinalSuffix: /^\s*(st|nd|rd|th)/i,
        timeContext: /^\s*(\:|a(?!u|p)|p)/i
    },
    timezones: [{
        name: "UTC",
        offset: "-000"
    }, {
        name: "GMT",
        offset: "-000"
    }, {
        name: "EST",
        offset: "-0500"
    }, {
        name: "EDT",
        offset: "-0400"
    }, {
        name: "CST",
        offset: "-0600"
    }, {
        name: "CDT",
        offset: "-0500"
    }, {
        name: "MST",
        offset: "-0700"
    }, {
        name: "MDT",
        offset: "-0600"
    }, {
        name: "PST",
        offset: "-0800"
    }, {
        name: "PDT",
        offset: "-0700"
    }]
};
(function() {
    var $D = Date,
        $P = $D.prototype,
        $C = $D.CultureInfo,
        p = function(s, l) {
            if (!l) {
                l = 2;
            }
            return ("000" + s).slice(l * -1);
        };
    $P.clearTime = function() {
        this.setHours(0);
        this.setMinutes(0);
        this.setSeconds(0);
        this.setMilliseconds(0);
        return this;
    };
    $P.setTimeToNow = function() {
        var n = new Date();
        this.setHours(n.getHours());
        this.setMinutes(n.getMinutes());
        this.setSeconds(n.getSeconds());
        this.setMilliseconds(n.getMilliseconds());
        return this;
    };
    $D.today = function() {
        return new Date().clearTime();
    };
    $D.compare = function(date1, date2) {
        if (isNaN(date1) || isNaN(date2)) {
            throw new Error(date1 + " - " + date2);
        } else if (date1 instanceof Date && date2 instanceof Date) {
            return (date1 < date2) ? -1 : (date1 > date2) ? 1 : 0;
        } else {
            throw new TypeError(date1 + " - " + date2);
        }
    };
    $D.equals = function(date1, date2) {
        return (date1.compareTo(date2) === 0);
    };
    $D.getDayNumberFromName = function(name) {
        var n = $C.dayNames,
            m = $C.abbreviatedDayNames,
            o = $C.shortestDayNames,
            s = name.toLowerCase();
        for (var i = 0; i < n.length; i++) {
            if (n[i].toLowerCase() == s || m[i].toLowerCase() == s || o[i].toLowerCase() == s) {
                return i;
            }
        }
        return -1;
    };
    $D.getMonthNumberFromName = function(name) {
        var n = $C.monthNames,
            m = $C.abbreviatedMonthNames,
            s = name.toLowerCase();
        for (var i = 0; i < n.length; i++) {
            if (n[i].toLowerCase() == s || m[i].toLowerCase() == s) {
                return i;
            }
        }
        return -1;
    };
    $D.isLeapYear = function(year) {
        return ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);
    };
    $D.getDaysInMonth = function(year, month) {
        return [31, ($D.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
    };
    $D.getTimezoneAbbreviation = function(offset) {
        var z = $C.timezones;
        for (var i = 0; i < z.length; i++) {
            if (z[i].offset === offset) {
                return z[i].name;
            }
        }
        return null;
    };
    $D.getTimezoneOffset = function(name) {
        var z = $C.timezones;
        for (var i = 0; i < z.length; i++) {
            if (z[i].name === name.toUpperCase()) {
                return z[i].offset;
            }
        }
        return null;
    };
    $P.clone = function() {
        return new Date(this.getTime());
    };
    $P.compareTo = function(date) {
        return Date.compare(this, date);
    };
    $P.equals = function(date) {
        return Date.equals(this, date || new Date());
    };
    $P.between = function(start, end) {
        return this.getTime() >= start.getTime() && this.getTime() <= end.getTime();
    };
    $P.isAfter = function(date) {
        return this.compareTo(date || new Date()) === 1;
    };
    $P.isBefore = function(date) {
        return (this.compareTo(date || new Date()) === -1);
    };
    $P.isToday = function() {
        return this.isSameDay(new Date());
    };
    $P.isSameDay = function(date) {
        return this.clone().clearTime().equals(date.clone().clearTime());
    };
    $P.addMilliseconds = function(value) {
        this.setMilliseconds(this.getMilliseconds() + value);
        return this;
    };
    $P.addSeconds = function(value) {
        return this.addMilliseconds(value * 1000);
    };
    $P.addMinutes = function(value) {
        return this.addMilliseconds(value * 60000);
    };
    $P.addHours = function(value) {
        return this.addMilliseconds(value * 3600000);
    };
    $P.addDays = function(value) {
        this.setDate(this.getDate() + value);
        return this;
    };
    $P.addWeeks = function(value) {
        return this.addDays(value * 7);
    };
    $P.addMonths = function(value) {
        var n = this.getDate();
        this.setDate(1);
        this.setMonth(this.getMonth() + value);
        this.setDate(Math.min(n, $D.getDaysInMonth(this.getFullYear(), this.getMonth())));
        return this;
    };
    $P.addYears = function(value) {
        return this.addMonths(value * 12);
    };
    $P.add = function(config) {
        if (typeof config == "number") {
            this._orient = config;
            return this;
        }
        var x = config;
        if (x.milliseconds) {
            this.addMilliseconds(x.milliseconds);
        }
        if (x.seconds) {
            this.addSeconds(x.seconds);
        }
        if (x.minutes) {
            this.addMinutes(x.minutes);
        }
        if (x.hours) {
            this.addHours(x.hours);
        }
        if (x.weeks) {
            this.addWeeks(x.weeks);
        }
        if (x.months) {
            this.addMonths(x.months);
        }
        if (x.years) {
            this.addYears(x.years);
        }
        if (x.days) {
            this.addDays(x.days);
        }
        return this;
    };
    var $y, $m, $d;
    $P.getWeek = function() {
        var a, b, c, d, e, f, g, n, s, w;
        $y = (!$y) ? this.getFullYear() : $y;
        $m = (!$m) ? this.getMonth() + 1 : $m;
        $d = (!$d) ? this.getDate() : $d;
        if ($m <= 2) {
            a = $y - 1;
            b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0);
            c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0);
            s = b - c;
            e = 0;
            f = $d - 1 + (31 * ($m - 1));
        } else {
            a = $y;
            b = (a / 4 | 0) - (a / 100 | 0) + (a / 400 | 0);
            c = ((a - 1) / 4 | 0) - ((a - 1) / 100 | 0) + ((a - 1) / 400 | 0);
            s = b - c;
            e = s + 1;
            f = $d + ((153 * ($m - 3) + 2) / 5) + 58 + s;
        }
        g = (a + b) % 7;
        d = (f + g - e) % 7;
        n = (f + 3 - d) | 0;
        if (n < 0) {
            w = 53 - ((g - s) / 5 | 0);
        } else if (n > 364 + s) {
            w = 1;
        } else {
            w = (n / 7 | 0) + 1;
        }
        $y = $m = $d = null;
        return w;
    };
    $P.getISOWeek = function() {
        $y = this.getUTCFullYear();
        $m = this.getUTCMonth() + 1;
        $d = this.getUTCDate();
        return p(this.getWeek());
    };
    $P.setWeek = function(n) {
        return this.moveToDayOfWeek(1).addWeeks(n - this.getWeek());
    };
    $D._validate = function(n, min, max, name) {
        if (typeof n == "undefined") {
            return false;
        } else if (typeof n != "number") {
            throw new TypeError(n + " is not a Number.");
        } else if (n < min || n > max) {
            throw new RangeError(n + " is not a valid value for " + name + ".");
        }
        return true;
    };
    $D.validateMillisecond = function(value) {
        return $D._validate(value, 0, 999, "millisecond");
    };
    $D.validateSecond = function(value) {
        return $D._validate(value, 0, 59, "second");
    };
    $D.validateMinute = function(value) {
        return $D._validate(value, 0, 59, "minute");
    };
    $D.validateHour = function(value) {
        return $D._validate(value, 0, 23, "hour");
    };
    $D.validateDay = function(value, year, month) {
        return $D._validate(value, 1, $D.getDaysInMonth(year, month), "day");
    };
    $D.validateMonth = function(value) {
        return $D._validate(value, 0, 11, "month");
    };
    $D.validateYear = function(value) {
        return $D._validate(value, 0, 9999, "year");
    };
    $P.set = function(config) {
        if ($D.validateMillisecond(config.millisecond)) {
            this.addMilliseconds(config.millisecond - this.getMilliseconds());
        }
        if ($D.validateSecond(config.second)) {
            this.addSeconds(config.second - this.getSeconds());
        }
        if ($D.validateMinute(config.minute)) {
            this.addMinutes(config.minute - this.getMinutes());
        }
        if ($D.validateHour(config.hour)) {
            this.addHours(config.hour - this.getHours());
        }
        if ($D.validateMonth(config.month)) {
            this.addMonths(config.month - this.getMonth());
        }
        if ($D.validateYear(config.year)) {
            this.addYears(config.year - this.getFullYear());
        }
        if ($D.validateDay(config.day, this.getFullYear(), this.getMonth())) {
            this.addDays(config.day - this.getDate());
        }
        if (config.timezone) {
            this.setTimezone(config.timezone);
        }
        if (config.timezoneOffset) {
            this.setTimezoneOffset(config.timezoneOffset);
        }
        if (config.week && $D._validate(config.week, 0, 53, "week")) {
            this.setWeek(config.week);
        }
        return this;
    };
    $P.moveToFirstDayOfMonth = function() {
        return this.set({
            day: 1
        });
    };
    $P.moveToLastDayOfMonth = function() {
        return this.set({
            day: $D.getDaysInMonth(this.getFullYear(), this.getMonth())
        });
    };
    $P.moveToNthOccurrence = function(dayOfWeek, occurrence) {
        var shift = 0;
        if (occurrence > 0) {
            shift = occurrence - 1;
        } else if (occurrence === -1) {
            this.moveToLastDayOfMonth();
            if (this.getDay() !== dayOfWeek) {
                this.moveToDayOfWeek(dayOfWeek, -1);
            }
            return this;
        }
        return this.moveToFirstDayOfMonth().addDays(-1).moveToDayOfWeek(dayOfWeek, +1).addWeeks(shift);
    };
    $P.moveToDayOfWeek = function(dayOfWeek, orient) {
        var diff = (dayOfWeek - this.getDay() + 7 * (orient || +1)) % 7;
        return this.addDays((diff === 0) ? diff += 7 * (orient || +1) : diff);
    };
    $P.moveToMonth = function(month, orient) {
        var diff = (month - this.getMonth() + 12 * (orient || +1)) % 12;
        return this.addMonths((diff === 0) ? diff += 12 * (orient || +1) : diff);
    };
    $P.getOrdinalNumber = function() {
        return Math.ceil((this.clone().clearTime() - new Date(this.getFullYear(), 0, 1)) / 86400000) + 1;
    };
    $P.getTimezone = function() {
        return $D.getTimezoneAbbreviation(this.getUTCOffset());
    };
    $P.setTimezoneOffset = function(offset) {
        var here = this.getTimezoneOffset(),
            there = Number(offset) * -6 / 10;
        return this.addMinutes(there - here);
    };
    $P.setTimezone = function(offset) {
        return this.setTimezoneOffset($D.getTimezoneOffset(offset));
    };
    $P.hasDaylightSavingTime = function() {
        return (Date.today().set({
            month: 0,
            day: 1
        }).getTimezoneOffset() !== Date.today().set({
            month: 6,
            day: 1
        }).getTimezoneOffset());
    };
    $P.isDaylightSavingTime = function() {
        return (this.hasDaylightSavingTime() && new Date().getTimezoneOffset() === Date.today().set({
            month: 6,
            day: 1
        }).getTimezoneOffset());
    };
    $P.getUTCOffset = function() {
        var n = this.getTimezoneOffset() * -10 / 6,
            r;
        if (n < 0) {
            r = (n - 10000).toString();
            return r.charAt(0) + r.substr(2);
        } else {
            r = (n + 10000).toString();
            return "+" + r.substr(1);
        }
    };
    $P.getElapsed = function(date) {
        return (date || new Date()) - this;
    };
    if (!$P.toISOString) {
        $P.toISOString = function() {
            function f(n) {
                return n < 10 ? '0' + n : n;
            }
            return '"' + this.getUTCFullYear() + '-' +
                f(this.getUTCMonth() + 1) + '-' +
                f(this.getUTCDate()) + 'T' +
                f(this.getUTCHours()) + ':' +
                f(this.getUTCMinutes()) + ':' +
                f(this.getUTCSeconds()) + 'Z"';
        };
    }
    $P._toString = $P.toString;
    $P.toString = function(format) {
        var x = this;
        if (format && format.length == 1) {
            var c = $C.formatPatterns;
            x.t = x.toString;
            switch (format) {
                case "d":
                    return x.t(c.shortDate);
                case "D":
                    return x.t(c.longDate);
                case "F":
                    return x.t(c.fullDateTime);
                case "m":
                    return x.t(c.monthDay);
                case "r":
                    return x.t(c.rfc1123);
                case "s":
                    return x.t(c.sortableDateTime);
                case "t":
                    return x.t(c.shortTime);
                case "T":
                    return x.t(c.longTime);
                case "u":
                    return x.t(c.universalSortableDateTime);
                case "y":
                    return x.t(c.yearMonth);
            }
        }
        var ord = function(n) {
            switch (n * 1) {
                case 1:
                case 21:
                case 31:
                    return "st";
                case 2:
                case 22:
                    return "nd";
                case 3:
                case 23:
                    return "rd";
                default:
                    return "th";
            }
        };
        return format ? format.replace(/(\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|S)/g, function(m) {
            if (m.charAt(0) === "\\") {
                return m.replace("\\", "");
            }
            x.h = x.getHours;
            switch (m) {
                case "hh":
                    return p(x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12));
                case "h":
                    return x.h() < 13 ? (x.h() === 0 ? 12 : x.h()) : (x.h() - 12);
                case "HH":
                    return p(x.h());
                case "H":
                    return x.h();
                case "mm":
                    return p(x.getMinutes());
                case "m":
                    return x.getMinutes();
                case "ss":
                    return p(x.getSeconds());
                case "s":
                    return x.getSeconds();
                case "yyyy":
                    return p(x.getFullYear(), 4);
                case "yy":
                    return p(x.getFullYear());
                case "dddd":
                    return $C.dayNames[x.getDay()];
                case "ddd":
                    return $C.abbreviatedDayNames[x.getDay()];
                case "dd":
                    return p(x.getDate());
                case "d":
                    return x.getDate();
                case "MMMM":
                    return $C.monthNames[x.getMonth()];
                case "MMM":
                    return $C.abbreviatedMonthNames[x.getMonth()];
                case "MM":
                    return p((x.getMonth() + 1));
                case "M":
                    return x.getMonth() + 1;
                case "t":
                    return x.h() < 12 ? $C.amDesignator.substring(0, 1) : $C.pmDesignator.substring(0, 1);
                case "tt":
                    return x.h() < 12 ? $C.amDesignator : $C.pmDesignator;
                case "S":
                    return ord(x.getDate());
                default:
                    return m;
            }
        }) : this._toString();
    };
}());
(function() {
    var $D = Date,
        $P = $D.prototype,
        $C = $D.CultureInfo,
        $N = Number.prototype;
    $P._orient = +1;
    $P._nth = null;
    $P._is = false;
    $P._same = false;
    $P._isSecond = false;
    $N._dateElement = "day";
    $P.next = function() {
        this._orient = +1;
        return this;
    };
    $D.next = function() {
        return $D.today().next();
    };
    $P.last = $P.prev = $P.previous = function() {
        this._orient = -1;
        return this;
    };
    $D.last = $D.prev = $D.previous = function() {
        return $D.today().last();
    };
    $P.is = function() {
        this._is = true;
        return this;
    };
    $P.same = function() {
        this._same = true;
        this._isSecond = false;
        return this;
    };
    $P.today = function() {
        return this.same().day();
    };
    $P.weekday = function() {
        if (this._is) {
            this._is = false;
            return (!this.is().sat() && !this.is().sun());
        }
        return false;
    };
    $P.at = function(time) {
        return (typeof time === "string") ? $D.parse(this.toString("d") + " " + time) : this.set(time);
    };
    $N.fromNow = $N.after = function(date) {
        var c = {};
        if(typeof this !== 'undefined') c[this._dateElement] = this;
        return ((!date) ? new Date() : date.clone()).add(c);
    };
    $N.ago = $N.before = function(date) {
        var c = {};
        if(typeof this !== 'undefined') c[this._dateElement] = this * -1;
        return ((!date) ? new Date() : date.clone()).add(c);
    };
    var dx = ("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),
        mx = ("january february march april may june july august september october november december").split(/\s/),
        px = ("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),
        pxf = ("Milliseconds Seconds Minutes Hours Date Week Month FullYear").split(/\s/),
        nth = ("final first second third fourth fifth").split(/\s/),
        de;
    $P.toObject = function() {
        var o = {};
        for (var i = 0; i < px.length; i++) {
            o[px[i].toLowerCase()] = this["get" + pxf[i]]();
        }
        return o;
    };
    $D.fromObject = function(config) {
        config.week = null;
        return Date.today().set(config);
    };
    var df = function(n) {
        return function() {
            if (this._is) {
                this._is = false;
                return this.getDay() == n;
            }
            if (this._nth !== null) {
                if (this._isSecond) {
                    this.addSeconds(this._orient * -1);
                }
                this._isSecond = false;
                var ntemp = this._nth;
                this._nth = null;
                var temp = this.clone().moveToLastDayOfMonth();
                this.moveToNthOccurrence(n, ntemp);
                if (this > temp) {
                    throw new RangeError($D.getDayName(n) + " does not occur " + ntemp + " times in the month of " + $D.getMonthName(temp.getMonth()) + " " + temp.getFullYear() + ".");
                }
                return this;
            }
            return this.moveToDayOfWeek(n, this._orient);
        };
    };
    var sdf = function(n) {
        return function() {
            var t = $D.today(),
                shift = n - t.getDay();
            if (n === 0 && $C.firstDayOfWeek === 1 && t.getDay() !== 0) {
                shift = shift + 7;
            }
            return t.addDays(shift);
        };
    };
    for (var i = 0; i < dx.length; i++) {
        $D[dx[i].toUpperCase()] = $D[dx[i].toUpperCase().substring(0, 3)] = i;
        $D[dx[i]] = $D[dx[i].substring(0, 3)] = sdf(i);
        $P[dx[i]] = $P[dx[i].substring(0, 3)] = df(i);
    }
    var mf = function(n) {
        return function() {
            if (this._is) {
                this._is = false;
                return this.getMonth() === n;
            }
            return this.moveToMonth(n, this._orient);
        };
    };
    var smf = function(n) {
        return function() {
            return $D.today().set({
                month: n,
                day: 1
            });
        };
    };
    for (var j = 0; j < mx.length; j++) {
        $D[mx[j].toUpperCase()] = $D[mx[j].toUpperCase().substring(0, 3)] = j;
        $D[mx[j]] = $D[mx[j].substring(0, 3)] = smf(j);
        $P[mx[j]] = $P[mx[j].substring(0, 3)] = mf(j);
    }
    var ef = function(j) {
        return function() {
            if (this._isSecond) {
                this._isSecond = false;
                return this;
            }
            if (this._same) {
                this._same = this._is = false;
                var o1 = this.toObject(),
                    o2 = (arguments[0] || new Date()).toObject(),
                    v = "",
                    k = j.toLowerCase();
                for (var m = (px.length - 1); m > -1; m--) {
                    v = px[m].toLowerCase();
                    if (o1[v] != o2[v]) {
                        return false;
                    }
                    if (k == v) {
                        break;
                    }
                }
                return true;
            }
            if (j.substring(j.length - 1) != "s") {
                j += "s";
            }
            return this["add" + j](this._orient);
        };
    };
    var nf = function(n) {
        return function() {
            if(typeof this !== 'undefined') this._dateElement = n;
            return this;
        };
    };
    for (var k = 0; k < px.length; k++) {
        de = px[k].toLowerCase();
        $P[de] = $P[de + "s"] = ef(px[k]);
        $N[de] = $N[de + "s"] = nf(de);
    }
    $P._ss = ef("Second");
    var nthfn = function(n) {
        return function(dayOfWeek) {
            if (this._same) {
                return this._ss(arguments[0]);
            }
            if (dayOfWeek || dayOfWeek === 0) {
                return this.moveToNthOccurrence(dayOfWeek, n);
            }
            this._nth = n;
            if (n === 2 && (dayOfWeek === undefined || dayOfWeek === null)) {
                this._isSecond = true;
                return this.addSeconds(this._orient);
            }
            return this;
        };
    };
    for (var l = 0; l < nth.length; l++) {
        $P[nth[l]] = (l === 0) ? nthfn(-1) : nthfn(l);
    }
}());
(function() {
    Date.Parsing = {
        Exception: function(s) {
            this.message = "Parse error at '" + s.substring(0, 10) + " ...'";
        }
    };
    var $P = Date.Parsing;
    var _ = $P.Operators = {
        rtoken: function(r) {
            return function(s) {
                var mx = s.match(r);
                if (mx) {
                    return ([mx[0], s.substring(mx[0].length)]);
                } else {
                    throw new $P.Exception(s);
                }
            };
        },
        token: function() {
            return function(s) {
                return _.rtoken(new RegExp("^\s*" + s + "\s*"))(s);
            };
        },
        stoken: function(s) {
            return _.rtoken(new RegExp("^" + s));
        },
        until: function(p) {
            return function(s) {
                var qx = [],
                    rx = null;
                while (s.length) {
                    try {
                        rx = p.call(this, s);
                    } catch (e) {
                        qx.push(rx[0]);
                        s = rx[1];
                        continue;
                    }
                    break;
                }
                return [qx, s];
            };
        },
        many: function(p) {
            return function(s) {
                var rx = [],
                    r = null;
                while (s.length) {
                    try {
                        r = p.call(this, s);
                    } catch (e) {
                        return [rx, s];
                    }
                    rx.push(r[0]);
                    s = r[1];
                }
                return [rx, s];
            };
        },
        optional: function(p) {
            return function(s) {
                var r = null;
                try {
                    r = p.call(this, s);
                } catch (e) {
                    return [null, s];
                }
                return [r[0], r[1]];
            };
        },
        not: function(p) {
            return function(s) {
                try {
                    p.call(this, s);
                } catch (e) {
                    return [null, s];
                }
                throw new $P.Exception(s);
            };
        },
        ignore: function(p) {
            return p ? function(s) {
                var r = null;
                r = p.call(this, s);
                return [null, r[1]];
            } : null;
        },
        product: function() {
            var px = arguments[0],
                qx = Array.prototype.slice.call(arguments, 1),
                rx = [];
            for (var i = 0; i < px.length; i++) {
                rx.push(_.each(px[i], qx));
            }
            return rx;
        },
        cache: function(rule) {
            var cache = {},
                r = null;
            return function(s) {
                try {
                    r = cache[s] = (cache[s] || rule.call(this, s));
                } catch (e) {
                    r = cache[s] = e;
                }
                if (r instanceof $P.Exception) {
                    throw r;
                } else {
                    return r;
                }
            };
        },
        any: function() {
            var px = arguments;
            return function(s) {
                var r = null;
                for (var i = 0; i < px.length; i++) {
                    if (px[i] == null) {
                        continue;
                    }
                    try {
                        r = (px[i].call(this, s));
                    } catch (e) {
                        r = null;
                    }
                    if (r) {
                        return r;
                    }
                }
                throw new $P.Exception(s);
            };
        },
        each: function() {
            var px = arguments;
            return function(s) {
                var rx = [],
                    r = null;
                for (var i = 0; i < px.length; i++) {
                    if (px[i] == null) {
                        continue;
                    }
                    try {
                        r = (px[i].call(this, s));
                    } catch (e) {
                        throw new $P.Exception(s);
                    }
                    rx.push(r[0]);
                    s = r[1];
                }
                return [rx, s];
            };
        },
        all: function() {
            var px = arguments,
                _ = _;
            return _.each(_.optional(px));
        },
        sequence: function(px, d, c) {
            d = d || _.rtoken(/^\s*/);
            c = c || null;
            if (px.length == 1) {
                return px[0];
            }
            return function(s) {
                var r = null,
                    q = null;
                var rx = [];
                for (var i = 0; i < px.length; i++) {
                    try {
                        r = px[i].call(this, s);
                    } catch (e) {
                        break;
                    }
                    rx.push(r[0]);
                    try {
                        q = d.call(this, r[1]);
                    } catch (ex) {
                        q = null;
                        break;
                    }
                    s = q[1];
                }
                if (!r) {
                    throw new $P.Exception(s);
                }
                if (q) {
                    throw new $P.Exception(q[1]);
                }
                if (c) {
                    try {
                        r = c.call(this, r[1]);
                    } catch (ey) {
                        throw new $P.Exception(r[1]);
                    }
                }
                return [rx, (r ? r[1] : s)];
            };
        },
        between: function(d1, p, d2) {
            d2 = d2 || d1;
            var _fn = _.each(_.ignore(d1), p, _.ignore(d2));
            return function(s) {
                var rx = _fn.call(this, s);
                return [
                    [rx[0][0], rx[0][2]], rx[1]
                ];
            };
        },
        list: function(p, d, c) {
            d = d || _.rtoken(/^\s*/);
            c = c || null;
            return (p instanceof Array ? _.each(_.product(p.slice(0, -1), _.ignore(d)), p.slice(-1), _.ignore(c)) : _.each(_.many(_.each(p, _.ignore(d))), p, _.ignore(c)));
        },
        set: function(px, d, c) {
            d = d || _.rtoken(/^\s*/);
            c = c || null;
            return function(s) {
                var r = null,
                    p = null,
                    q = null,
                    rx = null,
                    best = [
                        [], s
                    ],
                    last = false;
                for (var i = 0; i < px.length; i++) {
                    q = null;
                    p = null;
                    r = null;
                    last = (px.length == 1);
                    try {
                        r = px[i].call(this, s);
                    } catch (e) {
                        continue;
                    }
                    rx = [
                        [r[0]], r[1]
                    ];
                    if (r[1].length > 0 && !last) {
                        try {
                            q = d.call(this, r[1]);
                        } catch (ex) {
                            last = true;
                        }
                    } else {
                        last = true;
                    }
                    if (!last && q[1].length === 0) {
                        last = true;
                    }
                    if (!last) {
                        var qx = [];
                        for (var j = 0; j < px.length; j++) {
                            if (i != j) {
                                qx.push(px[j]);
                            }
                        }
                        p = _.set(qx, d).call(this, q[1]);
                        if (p[0].length > 0) {
                            rx[0] = rx[0].concat(p[0]);
                            rx[1] = p[1];
                        }
                    }
                    if (rx[1].length < best[1].length) {
                        best = rx;
                    }
                    if (best[1].length === 0) {
                        break;
                    }
                }
                if (best[0].length === 0) {
                    return best;
                }
                if (c) {
                    try {
                        q = c.call(this, best[1]);
                    } catch (ey) {
                        throw new $P.Exception(best[1]);
                    }
                    best[1] = q[1];
                }
                return best;
            };
        },
        forward: function(gr, fname) {
            return function(s) {
                return gr[fname].call(this, s);
            };
        },
        replace: function(rule, repl) {
            return function(s) {
                var r = rule.call(this, s);
                return [repl, r[1]];
            };
        },
        process: function(rule, fn) {
            return function(s) {
                var r = rule.call(this, s);
                return [fn.call(this, r[0]), r[1]];
            };
        },
        min: function(min, rule) {
            return function(s) {
                var rx = rule.call(this, s);
                if (rx[0].length < min) {
                    throw new $P.Exception(s);
                }
                return rx;
            };
        }
    };
    var _generator = function(op) {
        return function() {
            var args = null,
                rx = [];
            if (arguments.length > 1) {
                args = Array.prototype.slice.call(arguments);
            } else if (arguments[0] instanceof Array) {
                args = arguments[0];
            }
            if (args) {
                for (var i = 0, px = args.shift(); i < px.length; i++) {
                    args.unshift(px[i]);
                    rx.push(op.apply(null, args));
                    args.shift();
                    return rx;
                }
            } else {
                return op.apply(null, arguments);
            }
        };
    };
    var gx = "optional not ignore cache".split(/\s/);
    for (var i = 0; i < gx.length; i++) {
        _[gx[i]] = _generator(_[gx[i]]);
    }
    var _vector = function(op) {
        return function() {
            if (arguments[0] instanceof Array) {
                return op.apply(null, arguments[0]);
            } else {
                return op.apply(null, arguments);
            }
        };
    };
    var vx = "each any all".split(/\s/);
    for (var j = 0; j < vx.length; j++) {
        _[vx[j]] = _vector(_[vx[j]]);
    }
}());
(function() {
    var $D = Date,
        $C = $D.CultureInfo;
    var flattenAndCompact = function(ax) {
        var rx = [];
        for (var i = 0; i < ax.length; i++) {
            if (ax[i] instanceof Array) {
                rx = rx.concat(flattenAndCompact(ax[i]));
            } else {
                if (ax[i]) {
                    rx.push(ax[i]);
                }
            }
        }
        return rx;
    };
    $D.Grammar = {};
    $D.Translator = {
        hour: function(s) {
            return function() {
                this.hour = Number(s);
            };
        },
        minute: function(s) {
            return function() {
                this.minute = Number(s);
            };
        },
        second: function(s) {
            return function() {
                this.second = Number(s);
            };
        },
        meridian: function(s) {
            return function() {
                this.meridian = s.slice(0, 1).toLowerCase();
            };
        },
        timezone: function(s) {
            return function() {
                var n = s.replace(/[^\d\+\-]/g, "");
                if (n.length) {
                    this.timezoneOffset = Number(n);
                } else {
                    this.timezone = s.toLowerCase();
                }
            };
        },
        day: function(x) {
            var s = x[0];
            return function() {
                this.day = Number(s.match(/\d+/)[0]);
            };
        },
        month: function(s) {
            return function() {
                this.month = (s.length == 3) ? "jan feb mar apr may jun jul aug sep oct nov dec".indexOf(s) / 4 : Number(s) - 1;
            };
        },
        year: function(s) {
            return function() {
                var n = Number(s);
                this.year = ((s.length > 2) ? n : (n + (((n + 2000) < $C.twoDigitYearMax) ? 2000 : 1900)));
            };
        },
        rday: function(s) {
            return function() {
                switch (s) {
                    case "yesterday":
                        this.days = -1;
                        break;
                    case "tomorrow":
                        this.days = 1;
                        break;
                    case "today":
                        this.days = 0;
                        break;
                    case "now":
                        this.days = 0;
                        this.now = true;
                        break;
                }
            };
        },
        finishExact: function(x) {
            x = (x instanceof Array) ? x : [x];
            for (var i = 0; i < x.length; i++) {
                if (x[i]) {
                    x[i].call(this);
                }
            }
            var now = new Date();
            if ((this.hour || this.minute) && (!this.month && !this.year && !this.day)) {
                this.day = now.getDate();
            }
            if (!this.year) {
                this.year = now.getFullYear();
            }
            if (!this.month && this.month !== 0) {
                this.month = now.getMonth();
            }
            if (!this.day) {
                this.day = 1;
            }
            if (!this.hour) {
                this.hour = 0;
            }
            if (!this.minute) {
                this.minute = 0;
            }
            if (!this.second) {
                this.second = 0;
            }
            if (this.meridian && this.hour) {
                if (this.meridian == "p" && this.hour < 12) {
                    this.hour = this.hour + 12;
                } else if (this.meridian == "a" && this.hour == 12) {
                    this.hour = 0;
                }
            }
            if (this.day > $D.getDaysInMonth(this.year, this.month)) {
                throw new RangeError(this.day + " is not a valid value for days.");
            }
            var r = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second);
            if (this.timezone) {
                r.set({
                    timezone: this.timezone
                });
            } else if (this.timezoneOffset) {
                r.set({
                    timezoneOffset: this.timezoneOffset
                });
            }
            return r;
        },
        finish: function(x) {
            x = (x instanceof Array) ? flattenAndCompact(x) : [x];
            if (x.length === 0) {
                return null;
            }
            for (var i = 0; i < x.length; i++) {
                if (typeof x[i] == "function") {
                    x[i].call(this);
                }
            }
            var today = $D.today();
            if (this.now && !this.unit && !this.operator) {
                return new Date();
            } else if (this.now) {
                today = new Date();
            }
            var temp;
            var expression = !!(this.days && this.days !== null || this.orient || this.operator);
            var gap, mod, orient;
            orient = ((this.orient == "past" || this.operator == "subtract") ? -1 : 1);
            if (!this.now && "hour minute second".indexOf(this.unit) != -1) {
                today.setTimeToNow();
            }
            if (this.month || this.month === 0) {
                if ("year day hour minute second".indexOf(this.unit) != -1) {
                    this.value = this.month + 1;
                    this.month = null;
                    expression = true;
                }
            }
            if (!expression && this.weekday && !this.day && !this.days) {
                temp = Date[this.weekday]();
                this.day = temp.getDate();
                if (!this.month) {
                    this.month = temp.getMonth();
                }
                this.year = temp.getFullYear();
            }
            if (expression && this.weekday && this.unit != "month") {
                this.unit = "day";
                gap = ($D.getDayNumberFromName(this.weekday) - today.getDay());
                mod = 7;
                this.days = gap ? ((gap + (orient * mod)) % mod) : (orient * mod);
            }
            if (this.month && this.unit == "day" && this.operator) {
                this.value = (this.month + 1);
                this.month = null;
            }
            if (this.value != null && this.month != null && this.year != null) {
                this.day = this.value * 1;
            }
            if (this.month && !this.day && this.value) {
                today.set({
                    day: this.value * 1
                });
                if (!expression) {
                    this.day = this.value * 1;
                }
            }
            if (!this.month && this.value && this.unit == "month" && !this.now) {
                this.month = this.value;
                expression = true;
            }
            if (expression && (this.month || this.month === 0) && this.unit != "year") {
                this.unit = "month";
                gap = (this.month - today.getMonth());
                mod = 12;
                this.months = gap ? ((gap + (orient * mod)) % mod) : (orient * mod);
                this.month = null;
            }
            if (!this.unit) {
                this.unit = "day";
            }
            if (!this.value && this.operator && this.operator !== null && this[this.unit + "s"] && this[this.unit + "s"] !== null) {
                this[this.unit + "s"] = this[this.unit + "s"] + ((this.operator == "add") ? 1 : -1) + (this.value || 0) * orient;
            } else if (this[this.unit + "s"] == null || this.operator != null) {
                if (!this.value) {
                    this.value = 1;
                }
                this[this.unit + "s"] = this.value * orient;
            }
            if (this.meridian && this.hour) {
                if (this.meridian == "p" && this.hour < 12) {
                    this.hour = this.hour + 12;
                } else if (this.meridian == "a" && this.hour == 12) {
                    this.hour = 0;
                }
            }
            if (this.weekday && !this.day && !this.days) {
                temp = Date[this.weekday]();
                this.day = temp.getDate();
                if (temp.getMonth() !== today.getMonth()) {
                    this.month = temp.getMonth();
                }
            }
            if ((this.month || this.month === 0) && !this.day) {
                this.day = 1;
            }
            if (!this.orient && !this.operator && this.unit == "week" && this.value && !this.day && !this.month) {
                return Date.today().setWeek(this.value);
            }
            if (expression && this.timezone && this.day && this.days) {
                this.day = this.days;
            }
            return (expression) ? today.add(this) : today.set(this);
        }
    };
    var _ = $D.Parsing.Operators,
        g = $D.Grammar,
        t = $D.Translator,
        _fn;
    g.datePartDelimiter = _.rtoken(/^([\s\-\.\,\/\x27]+)/);
    g.timePartDelimiter = _.stoken(":");
    g.whiteSpace = _.rtoken(/^\s*/);
    g.generalDelimiter = _.rtoken(/^(([\s\,]|at|@|on)+)/);
    var _C = {};
    g.ctoken = function(keys) {
        var fn = _C[keys];
        if (!fn) {
            var c = $C.regexPatterns;
            var kx = keys.split(/\s+/),
                px = [];
            for (var i = 0; i < kx.length; i++) {
                px.push(_.replace(_.rtoken(c[kx[i]]), kx[i]));
            }
            fn = _C[keys] = _.any.apply(null, px);
        }
        return fn;
    };
    g.ctoken2 = function(key) {
        return _.rtoken($C.regexPatterns[key]);
    };
    g.h = _.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/), t.hour));
    g.hh = _.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/), t.hour));
    g.H = _.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/), t.hour));
    g.HH = _.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/), t.hour));
    g.m = _.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/), t.minute));
    g.mm = _.cache(_.process(_.rtoken(/^[0-5][0-9]/), t.minute));
    g.s = _.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/), t.second));
    g.ss = _.cache(_.process(_.rtoken(/^[0-5][0-9]/), t.second));
    g.hms = _.cache(_.sequence([g.H, g.m, g.s], g.timePartDelimiter));
    g.t = _.cache(_.process(g.ctoken2("shortMeridian"), t.meridian));
    g.tt = _.cache(_.process(g.ctoken2("longMeridian"), t.meridian));
    g.z = _.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/), t.timezone));
    g.zz = _.cache(_.process(_.rtoken(/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/), t.timezone));
    g.zzz = _.cache(_.process(g.ctoken2("timezone"), t.timezone));
    g.timeSuffix = _.each(_.ignore(g.whiteSpace), _.set([g.tt, g.zzz]));
    g.time = _.each(_.optional(_.ignore(_.stoken("T"))), g.hms, g.timeSuffix);
    g.d = _.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/), _.optional(g.ctoken2("ordinalSuffix"))), t.day));
    g.dd = _.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/), _.optional(g.ctoken2("ordinalSuffix"))), t.day));
    g.ddd = g.dddd = _.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"), function(s) {
        return function() {
            this.weekday = s;
        };
    }));
    g.M = _.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/), t.month));
    g.MM = _.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/), t.month));
    g.MMM = g.MMMM = _.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"), t.month));
    g.y = _.cache(_.process(_.rtoken(/^(\d\d?)/), t.year));
    g.yy = _.cache(_.process(_.rtoken(/^(\d\d)/), t.year));
    g.yyy = _.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/), t.year));
    g.yyyy = _.cache(_.process(_.rtoken(/^(\d\d\d\d)/), t.year));
    _fn = function() {
        return _.each(_.any.apply(null, arguments), _.not(g.ctoken2("timeContext")));
    };
    g.day = _fn(g.d, g.dd);
    g.month = _fn(g.M, g.MMM);
    g.year = _fn(g.yyyy, g.yy);
    g.orientation = _.process(g.ctoken("past future"), function(s) {
        return function() {
            this.orient = s;
        };
    });
    g.operator = _.process(g.ctoken("add subtract"), function(s) {
        return function() {
            this.operator = s;
        };
    });
    g.rday = _.process(g.ctoken("yesterday tomorrow today now"), t.rday);
    g.unit = _.process(g.ctoken("second minute hour day week month year"), function(s) {
        return function() {
            this.unit = s;
        };
    });
    g.value = _.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/), function(s) {
        return function() {
            this.value = s.replace(/\D/g, "");
        };
    });
    g.expression = _.set([g.rday, g.operator, g.value, g.unit, g.orientation, g.ddd, g.MMM]);
    _fn = function() {
        return _.set(arguments, g.datePartDelimiter);
    };
    g.mdy = _fn(g.ddd, g.month, g.day, g.year);
    g.ymd = _fn(g.ddd, g.year, g.month, g.day);
    g.dmy = _fn(g.ddd, g.day, g.month, g.year);
    g.date = function(s) {
        return ((g[$C.dateElementOrder] || g.mdy).call(this, s));
    };
    g.format = _.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/), function(fmt) {
        if (g[fmt]) {
            return g[fmt];
        } else {
            throw $D.Parsing.Exception(fmt);
        }
    }), _.process(_.rtoken(/^[^dMyhHmstz]+/), function(s) {
        return _.ignore(_.stoken(s));
    }))), function(rules) {
        return _.process(_.each.apply(null, rules), t.finishExact);
    });
    var _F = {};
    var _get = function(f) {
    	 _F[f] = (_F[f] || g.format(f)[0]);
        return _F[f];
    };
    g.formats = function(fx) {
        if (fx instanceof Array) {
            var rx = [];
            for (var i = 0; i < fx.length; i++) {
                rx.push(_get(fx[i]));
            }
            return _.any.apply(null, rx);
        } else {
            return _get(fx);
        }
    };
    g._formats = g.formats(["\"yyyy-MM-ddTHH:mm:ssZ\"", "yyyy-MM-ddTHH:mm:ssZ", "yyyy-MM-ddTHH:mm:ssz", "yyyy-MM-ddTHH:mm:ss", "yyyy-MM-ddTHH:mmZ", "yyyy-MM-ddTHH:mmz", "yyyy-MM-ddTHH:mm", "ddd, MMM dd, yyyy H:mm:ss tt", "ddd MMM d yyyy HH:mm:ss zzz", "MMddyyyy", "ddMMyyyy", "Mddyyyy", "ddMyyyy", "Mdyyyy", "dMyyyy", "yyyy", "Mdyy", "dMyy", "d"]);
    g._start = _.process(_.set([g.date, g.time, g.expression], g.generalDelimiter, g.whiteSpace), t.finish);
    g.start = function(s) {
        try {
            var r = g._formats.call({}, s);
            if (r[1].length === 0) {
                return r;
            }
        } catch (e) {
            // continue regardless of error
        }
        return g._start.call({}, s);
    };
    $D._parse = $D.parse;
    $D.parse = function(s) {
        var r = null;
        if (!s) {
            return null;
        }
        if (s instanceof Date) {
            return s;
        }
        try {
            r = $D.Grammar.start.call({}, s.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1"));
        } catch (e) {
            return null;
        }
        return ((r[1].length === 0) ? r[0] : null);
    };
    $D.getParseFunction = function(fx) {
        var fn = $D.Grammar.formats(fx);
        return function(s) {
            var r = null;
            try {
                r = fn.call({}, s);
            } catch (e) {
                return null;
            }
            return ((r[1].length === 0) ? r[0] : null);
        };
    };
    $D.parseExact = function(s, fx) {
        return $D.getParseFunction(fx)(s);
    };
}());
// source --> https://homelive.pt/wp-content/plugins/super-forms/assets/js/frontend/timepicker.js?ver=6.3.312 
/* eslint-disable no-useless-escape */
/* eslint-disable no-undef */
// jshint ignore: start
/*!
 * jquery-timepicker v1.11.15 - A jQuery timepicker plugin inspired by Google Calendar. It supports both mouse and keyboard navigation.
 * Copyright (c) 2015 Jon Thornton - http://jonthornton.github.com/jquery-timepicker/
 * License: MIT
 */

(function(factory) {
  "use strict";
  if (
    typeof exports === "object" &&
    exports &&
    typeof module === "object" &&
    module &&
    module.exports === exports
  ) {
    // Browserify. Attach to jQuery module.
    factory(require("jquery"));
  } else if (typeof define === "function" && define.amd) {
    // AMD. Register as an anonymous module.
    define(["jquery"], factory);
  } else {
    // Browser globals
    factory(jQuery);
  }
})(function($) {
  "use strict";
  var _ONE_DAY = 86400;
  var _lang = {
    am: "am",
    pm: "pm",
    AM: "AM",
    PM: "PM",
    decimal: ".",
    mins: "mins",
    hr: "hr",
    hrs: "hrs"
  };

  var _DEFAULTS = {
    appendTo: "body",
    className: null,
    closeOnWindowScroll: false,
    disableTextInput: false,
    disableTimeRanges: [],
    disableTouchKeyboard: false,
    durationTime: null,
    forceRoundTime: false,
    maxTime: null,
    minTime: null,
    noneOption: false,
    orientation: "l",
    roundingFunction: function(seconds, settings) {
      if (seconds === null) {
        return null;
      } else if (typeof settings.step !== "number") {
        // TODO: nearest fit irregular steps
        return seconds;
      } else {
        var offset = seconds % (settings.step * 60); // step is in minutes

        var start = settings.minTime || 0;

        // adjust offset by start mod step so that the offset is aligned not to 00:00 but to the start
        offset -= start % (settings.step * 60);

        if (offset >= settings.step * 30) {
          // if offset is larger than a half step, round up
          seconds += settings.step * 60 - offset;
        } else {
          // round down
          seconds -= offset;
        }

        return _moduloSeconds(seconds, settings);
      }
    },
    scrollDefault: null,
    selectOnBlur: false,
    show2400: false,
    showDuration: false,
    showOn: ["click", "focus"],
    showOnFocus: true,
    step: 30,
    stopScrollPropagation: false,
    timeFormat: "g:ia",
    typeaheadHighlight: true,
    useSelect: false,
    wrapHours: true
  };

  var methods = {
    init: function(options) {
      return this.each(function() {
        var self = $(this);

        // pick up settings from data attributes
        var attributeOptions = [];
        for (var key in _DEFAULTS) {
          if (self.data(key)) {
            attributeOptions[key] = self.data(key);
          }
        }

        var settings = $.extend({}, _DEFAULTS, options, attributeOptions);

        if (settings.lang) {
          _lang = $.extend(_lang, settings.lang);
        }

        settings = _parseSettings(settings);
        self.data("timepicker-settings", settings);
        self.addClass("ui-timepicker-input");

        if (settings.useSelect) {
          _render(self);
        } else {
          self.prop("autocomplete", "off");
          if (settings.showOn) {
            for (var i in settings.showOn) {
              self.on(settings.showOn[i] + ".timepicker", methods.show);
            }
          }
          self.on("change.timepicker", FormatValue);
          self.on("keydown.timepicker", KeydownHandler);
          self.on("keyup.timepicker", KeyupHandler);
          if (settings.disableTextInput) {
            self.on("keydown.timepicker", _disableTextInputHandler);
          }
          self.on("cut.timepicker", KeyupHandler);
          self.on("paste.timepicker", KeyupHandler);

          FormatValue.call(self.get(0), null, "initial");
        }
      });
    },

    show: function(e) {
      var self = $(this);
      var settings = self.data("timepicker-settings");

      if (e) {
        e.preventDefault();
      }

      if (settings.useSelect) {
        self.data("timepicker-list").focus();
        return;
      }

      if (_hideKeyboard(self)) {
        // block the keyboard on mobile devices
        self.blur();
      }

      var list = self.data("timepicker-list");

      // check if input is readonly
      if (self.prop("readonly")) {
        return;
      }

      // check if list needs to be rendered
      if (
        !list ||
        list.length === 0 ||
        typeof settings.durationTime === "function"
      ) {
        _render(self);
        list = self.data("timepicker-list");
      }

      if (_isVisible(list)) {
        return;
      }

      self.data("ui-timepicker-value", self.val());
      _setSelected(self, list);

      // make sure other pickers are hidden
      methods.hide();

      // position the dropdown relative to the input
      list.show();
      var listOffset = {};

      if (settings.orientation.match(/r/)) {
        // right-align the dropdown
        listOffset.left =
          self.offset().left +
          self.outerWidth() -
          list.outerWidth() +
          parseInt(list.css("marginLeft").replace("px", ""), 10);
      } else {
        // left-align the dropdown
        listOffset.left =
          self.offset().left +
          parseInt(list.css("marginLeft").replace("px", ""), 10);
      }

      var verticalOrientation;
      if (settings.orientation.match(/t/)) {
        verticalOrientation = "t";
      } else if (settings.orientation.match(/b/)) {
        verticalOrientation = "b";
      } else if (
        self.offset().top + self.outerHeight(true) + list.outerHeight() >
        $(window).height() + $(window).scrollTop()
      ) {
        verticalOrientation = "t";
      } else {
        verticalOrientation = "b";
      }

      if (verticalOrientation == "t") {
        // position the dropdown on top
        list.addClass("ui-timepicker-positioned-top");
        listOffset.top =
          self.offset().top -
          list.outerHeight() +
          parseInt(list.css("marginTop").replace("px", ""), 10);
      } else {
        // put it under the input
        list.removeClass("ui-timepicker-positioned-top");
        listOffset.top =
          self.offset().top +
          self.outerHeight() +
          parseInt(list.css("marginTop").replace("px", ""), 10);
      }

      list.offset(listOffset);

      // position scrolling
      var selected = list.find(".ui-timepicker-selected");

      if (!selected.length) {
        var timeInt = _time2int(_getTimeValue(self));
        if (timeInt !== null) {
          selected = _findRow(self, list, timeInt);
        } else if (settings.scrollDefault) {
          selected = _findRow(self, list, settings.scrollDefault());
        }
      }

      // if not found or disabled, intelligently find first selectable element
      if (!selected.length || selected.hasClass("ui-timepicker-disabled")) {
        selected = list.find("li:not(.ui-timepicker-disabled):first");
      }

      if (selected && selected.length) {
        var topOffset =
          list.scrollTop() + selected.position().top - selected.outerHeight();
        list.scrollTop(topOffset);
      } else {
        list.scrollTop(0);
      }

      // prevent scroll propagation
      if (settings.stopScrollPropagation) {
        $(
          document
        ).on("wheel.ui-timepicker", ".ui-timepicker-wrapper", function(e) {
          e.preventDefault();
          var currentScroll = $(this).scrollTop();
          $(this).scrollTop(currentScroll + e.originalEvent.deltaY);
        });
      }

      // attach close handlers
      $(document).on(
        "touchstart.ui-timepicker mousedown.ui-timepicker",
        _closeHandler
      );
      $(window).on("resize.ui-timepicker", _closeHandler);
      if (settings.closeOnWindowScroll) {
        $(document).on("scroll.ui-timepicker", _closeHandler);
      }

      self.trigger("showTimepicker");

      return this;
    },

    hide: function() {
      var self = $(this);
      var settings = self.data("timepicker-settings");

      if (settings && settings.useSelect) {
        self.blur();
      }

      $(".ui-timepicker-wrapper").each(function() {
        var list = $(this);
        if (!_isVisible(list)) {
          return;
        }

        var self = list.data("timepicker-input");
        var settings = self.data("timepicker-settings");

        if (settings && settings.selectOnBlur) {
          _selectValue(self);
        }

        list.hide();
        self.trigger("hideTimepicker");
      });

      return this;
    },

    option: function(key, value) {
      if (typeof key == "string" && typeof value == "undefined") {
        return $(this).data("timepicker-settings")[key];
      }

      return this.each(function() {
        var self = $(this);
        var settings = self.data("timepicker-settings");
        var list = self.data("timepicker-list");

        if (typeof key == "object") {
          settings = $.extend(settings, key);
        } else if (typeof key == "string") {
          settings[key] = value;
        }

        settings = _parseSettings(settings);

        self.data("timepicker-settings", settings);

        FormatValue.call(self.get(0), { type: "change" }, "initial");

        if (list) {
          list.remove();
          self.data("timepicker-list", false);
        }

        if (settings.useSelect) {
          _render(self);
        }
      });
    },

    getSecondsFromMidnight: function() {
      return _time2int(_getTimeValue(this));
    },

    getTime: function(relative_date) {
      var self = this;

      var time_string = _getTimeValue(self);
      if (!time_string) {
        return null;
      }

      var offset = _time2int(time_string);
      if (offset === null) {
        return null;
      }

      if (!relative_date) {
        relative_date = new Date();
      }

      // construct a Date from relative date, and offset's time
      var time = new Date(relative_date);
      time.setHours(offset / 3600);
      time.setMinutes((offset % 3600) / 60);
      time.setSeconds(offset % 60);
      time.setMilliseconds(0);

      return time;
    },

    isVisible: function() {
      var self = this;
      var list = self.data("timepicker-list");
      return !!(list && _isVisible(list));
    },

    setTime: function(value) {
      var prettyTime;
      var self = this;
      var settings = self.data("timepicker-settings");

      if (settings.forceRoundTime) {
        prettyTime = _roundAndFormatTime(_time2int(value), settings);
      } else {
        prettyTime = _int2time(_time2int(value), settings);
      }

      if (value && prettyTime === null && settings.noneOption) {
        prettyTime = value;
      }

      _setTimeValue(self, prettyTime, "initial");
      FormatValue.call(self.get(0), { type: "change" }, "initial");

      if (self.data("timepicker-list")) {
        _setSelected(self, self.data("timepicker-list"));
      }

      return this;
    },

    remove: function() {
      var self = this;

      // check if this element is a timepicker
      if (!self.hasClass("ui-timepicker-input")) {
        return;
      }

      var settings = self.data("timepicker-settings");
      self.removeAttr("autocomplete", "off");
      self.removeClass("ui-timepicker-input");
      self.removeData("timepicker-settings");
      self.off(".timepicker");

      // timepicker-list won't be present unless the user has interacted with this timepicker
      if (self.data("timepicker-list")) {
        self.data("timepicker-list").remove();
      }

      if (settings.useSelect) {
        self.show();
      }

      self.removeData("timepicker-list");

      return this;
    }
  };

  // private methods

  function _isVisible(elem) {
    var el = elem[0];
    return el.offsetWidth > 0 && el.offsetHeight > 0;
  }

  function _parseSettings(settings) {
    var i;
    if (settings.minTime) {
      settings.minTime = _time2int(settings.minTime);
    }

    if (settings.maxTime) {
      settings.maxTime = _time2int(settings.maxTime);
    }

    if (settings.durationTime && typeof settings.durationTime !== "function") {
      settings.durationTime = _time2int(settings.durationTime);
    }

    if (settings.scrollDefault == "now") {
      settings.scrollDefault = function() {
        return settings.roundingFunction(_time2int(new Date()), settings);
      };
    } else if (
      settings.scrollDefault &&
      typeof settings.scrollDefault != "function"
    ) {
      var val = settings.scrollDefault;
      settings.scrollDefault = function() {
        return settings.roundingFunction(_time2int(val), settings);
      };
    } else if (settings.minTime) {
      settings.scrollDefault = function() {
        return settings.roundingFunction(settings.minTime, settings);
      };
    }

    if (
      $.type(settings.timeFormat) === "string" &&
      settings.timeFormat.match(/[gh]/)
    ) {
      settings._twelveHourTime = true;
    }

    if (
      settings.showOnFocus === false &&
      settings.showOn.indexOf("focus") != -1
    ) {
      settings.showOn.splice(settings.showOn.indexOf("focus"), 1);
    }

    if (settings.disableTimeRanges.length > 0) {
      // convert string times to integers
      for (i in settings.disableTimeRanges) {
        settings.disableTimeRanges[i] = [
          _time2int(settings.disableTimeRanges[i][0]),
          _time2int(settings.disableTimeRanges[i][1])
        ];
      }

      // sort by starting time
      settings.disableTimeRanges = settings.disableTimeRanges.sort(function(
        a,
        b
      ) {
        return a[0] - b[0];
      });

      // merge any overlapping ranges
      for (i = settings.disableTimeRanges.length - 1; i > 0; i--) {
        if (
          settings.disableTimeRanges[i][0] <=
          settings.disableTimeRanges[i - 1][1]
        ) {
          settings.disableTimeRanges[i - 1] = [
            Math.min(
              settings.disableTimeRanges[i][0],
              settings.disableTimeRanges[i - 1][0]
            ),
            Math.max(
              settings.disableTimeRanges[i][1],
              settings.disableTimeRanges[i - 1][1]
            )
          ];
          settings.disableTimeRanges.splice(i, 1);
        }
      }
    }

    return settings;
  }

  function _render(self) {
    var row;
    var i;
    var j;
    var noneElement;
    var wrapped_list;
    var settings = self.data("timepicker-settings");
    var list = self.data("timepicker-list");

    if (list && list.length) {
      list.remove();
      self.data("timepicker-list", false);
    }

    if (settings.useSelect) {
      list = $("<select />", { class: "ui-timepicker-select" });
      if (self.attr('name')) {
        list.attr('name', 'ui-timepicker-' + self.attr('name'));
      }
      wrapped_list = list;
    } else {
      list = $("<ul />", { class: "ui-timepicker-list" });

      wrapped_list = $("<div />", {
        class: "ui-timepicker-wrapper",
        tabindex: -1
      });
      wrapped_list.css({ display: "none", position: "absolute" }).append(list);
    }

    if (settings.noneOption) {
      if (settings.noneOption === true) {
        settings.noneOption = settings.useSelect ? "Time..." : "None";
      }

      if ($.isArray(settings.noneOption)) {
        for (i in settings.noneOption) {
          if (parseInt(i, 10) == i) {
            noneElement = _generateNoneElement(
              settings.noneOption[i],
              settings.useSelect
            );
            list.append(noneElement);
          }
        }
      } else {
        noneElement = _generateNoneElement(
          settings.noneOption,
          settings.useSelect
        );
        list.append(noneElement);
      }
    }

    if (settings.className) {
      wrapped_list.addClass(settings.className);
    }

    if (
      (settings.minTime !== null || settings.durationTime !== null) &&
      settings.showDuration
    ) {
      wrapped_list.addClass("ui-timepicker-with-duration");
      wrapped_list.addClass("ui-timepicker-step-" + settings.step);
    }

    var durStart = settings.minTime;
    if (typeof settings.durationTime === "function") {
      durStart = _time2int(settings.durationTime());
    } else if (settings.durationTime !== null) {
      durStart = settings.durationTime;
    }
    var start = settings.minTime !== null ? settings.minTime : 0;
    var end =
      settings.maxTime !== null ? settings.maxTime : start + _ONE_DAY - 1;

    if (end < start) {
      // make sure the end time is greater than start time, otherwise there will be no list to show
      end += _ONE_DAY;
    }

    if (
      end === _ONE_DAY - 1 &&
      $.type(settings.timeFormat) === "string" &&
      settings.show2400
    ) {
      // show a 24:00 option when using military time
      end = _ONE_DAY;
    }

    var dr = settings.disableTimeRanges;
    var drCur = 0;
    var drLen = dr.length;

    var stepFunc = settings.step;
    if (typeof stepFunc != "function") {
      stepFunc = function() {
        return settings.step;
      };
    }

    for (i = start, j = 0; i <= end; j++, i += stepFunc(j) * 60) {
      var timeInt = i;
      var timeString = _int2time(timeInt, settings);

      if (settings.useSelect) {
        row = $("<option />", { value: timeString });
        row.text(timeString);
      } else {
        row = $("<li />");
        row.addClass(
          timeInt % _ONE_DAY < _ONE_DAY / 2 ? "ui-timepicker-am" : "ui-timepicker-pm"
        );
        row.data("time", _moduloSeconds(timeInt, settings));
        row.text(timeString);
      }

      if (
        (settings.minTime !== null || settings.durationTime !== null) &&
        settings.showDuration
      ) {
        var durationString = _int2duration(i - durStart, settings.step);
        if (settings.useSelect) {
          row.text(row.text() + " (" + durationString + ")");
        } else {
          var duration = $("<span />", { class: "ui-timepicker-duration" });
          duration.text(" (" + durationString + ")");
          row.append(duration);
        }
      }

      if (drCur < drLen) {
        if (timeInt >= dr[drCur][1]) {
          drCur += 1;
        }

        if (dr[drCur] && timeInt >= dr[drCur][0] && timeInt < dr[drCur][1]) {
          if (settings.useSelect) {
            row.prop("disabled", true);
          } else {
            row.addClass("ui-timepicker-disabled");
          }
        }
      }

      list.append(row);
    }

    wrapped_list.data("timepicker-input", self);
    self.data("timepicker-list", wrapped_list);

    if (settings.useSelect) {
      if (self.val()) {
        list.val(_roundAndFormatTime(_time2int(self.val()), settings));
      }

      list.on("focus", function() {
        $(this)
          .data("timepicker-input")
          .trigger("showTimepicker");
      });
      list.on("blur", function() {
        $(this)
          .data("timepicker-input")
          .trigger("hideTimepicker");
      });
      list.on("change", function() {
        _setTimeValue(self, $(this).val(), "select");
      });

      _setTimeValue(self, list.val(), "initial");
      self.hide().after(list);
    } else {
      var appendTo = settings.appendTo;
      if (typeof appendTo === "string") {
        appendTo = $(appendTo);
      } else if (typeof appendTo === "function") {
        appendTo = appendTo(self);
      }
      appendTo.append(wrapped_list);
      _setSelected(self, list);

      list.on("mousedown click", "li", function() {
        // hack: temporarily disable the focus handler
        // to deal with the fact that IE fires 'focus'
        // events asynchronously
        self.off("focus.timepicker");
        self.on("focus.timepicker-ie-hack", function() {
          self.off("focus.timepicker-ie-hack");
          self.on("focus.timepicker", methods.show);
        });

        if (!_hideKeyboard(self)) {
          self[0].focus();
        }

        // make sure only the clicked row is selected
        list.find("li").removeClass("ui-timepicker-selected");
        $(this).addClass("ui-timepicker-selected");

        if (_selectValue(self)) {
          self.trigger("hideTimepicker");

          list.on("mouseup.timepicker click.timepicker", "li", function() {
            list.off("mouseup.timepicker click.timepicker");
            wrapped_list.hide();
          });
        }
      });
    }
  }

  function _generateNoneElement(optionValue, useSelect) {
    var label, className, value;

    if (typeof optionValue == "object") {
      label = optionValue.label;
      className = optionValue.className;
      value = optionValue.value;
    } else if (typeof optionValue == "string") {
      label = optionValue;
      value = '';
    } else {
      $.error("Invalid noneOption value");
    }

    if (useSelect) {
      return $("<option />", {
        value: value,
        class: className,
        text: label
      });
    } else {
      return $("<li />", {
        class: className,
        text: label
      }).data("time", String(value));
    }
  }

  function _roundAndFormatTime(seconds, settings) {
    seconds = settings.roundingFunction(seconds, settings);
    if (seconds !== null) {
      return _int2time(seconds, settings);
    }
  }

  // event handler to decide whether to close timepicker
  function _closeHandler(e) {
    if (e.target == window) {
      // mobile Chrome fires focus events against window for some reason
      return;
    }

    var target = $(e.target);

    if (
      target.closest(".ui-timepicker-input").length ||
      target.closest(".ui-timepicker-wrapper").length
    ) {
      // active timepicker was focused. ignore
      return;
    }

    methods.hide();
    $(document).unbind(".ui-timepicker");
    $(window).unbind(".ui-timepicker");
  }

  function _hideKeyboard(self) {
    var settings = self.data("timepicker-settings");
    return (
      (window.navigator.msMaxTouchPoints || "ontouchstart" in document) &&
      settings.disableTouchKeyboard
    );
  }

  function _findRow(self, list, value) {
    if (!value && value !== 0) {
      return false;
    }

    var settings = self.data("timepicker-settings");
    var out = false;
    value = settings.roundingFunction(value, settings);

    // loop through the menu items
    list.find("li").each(function(i, obj) {
      var jObj = $(obj);
      if (typeof jObj.data("time") != "number") {
        return;
      }

      if (jObj.data("time") == value) {
        out = jObj;
        return false;
      }
    });

    return out;
  }

  function _setSelected(self, list) {
    list.find("li").removeClass("ui-timepicker-selected");

    var settings = self.data("timepicker-settings");
    var timeValue = _time2int(_getTimeValue(self), settings);
    if (timeValue === null) {
      return;
    }

    var selected = _findRow(self, list, timeValue);
    if (selected) {
      var topDelta = selected.offset().top - list.offset().top;

      if (
        topDelta + selected.outerHeight() > list.outerHeight() ||
        topDelta < 0
      ) {
        list.scrollTop(
          list.scrollTop() + selected.position().top - selected.outerHeight()
        );
      }

      if (settings.forceRoundTime || selected.data("time") === timeValue) {
        selected.addClass("ui-timepicker-selected");
      }
    }
  }

  function FormatValue(e, origin) {
    if (origin == "timepicker") {
      return;
    }

    var self = $(this);

    if (this.value === "") {
      _setTimeValue(self, null, origin);
      return;
    }

    if (self.is(":focus") && (!e || e.type != "change")) {
      return;
    }

    var settings = self.data("timepicker-settings");
    var seconds = _time2int(this.value, settings);

    if (seconds === null) {
      self.trigger("timeFormatError");
      return;
    }

    var rangeError = false;
    // check that the time in within bounds
    if (
      settings.minTime !== null &&
      settings.maxTime !== null &&
      (seconds < settings.minTime || seconds > settings.maxTime)
    ) {
      rangeError = true;
    }

    // check that time isn't within disabled time ranges
    $.each(settings.disableTimeRanges, function() {
      if (seconds >= this[0] && seconds < this[1]) {
        rangeError = true;
        return false;
      }
    });

    if (settings.forceRoundTime) {
      var roundSeconds = settings.roundingFunction(seconds, settings);
      if (roundSeconds != seconds) {
        seconds = roundSeconds;
        origin = null;
      }
    }

    var prettyTime = _int2time(seconds, settings);

    if (rangeError) {
      if (
        _setTimeValue(self, prettyTime, "error") ||
        (e && e.type == "change")
      ) {
        self.trigger("timeRangeError");
      }
    } else {
      _setTimeValue(self, prettyTime, origin);
    }
  }

  function _getTimeValue(self) {
    if (self.is("input")) {
      return self.val();
    } else {
      // use the element's data attributes to store values
      return self.data("ui-timepicker-value");
    }
  }

  function _setTimeValue(self, value, source) {
    if (self.is("input")) {
      self.val(value);

      var settings = self.data("timepicker-settings");
      if (settings.useSelect && source != "select" && self.data("timepicker-list")) {
        self
          .data("timepicker-list")
          .val(_roundAndFormatTime(_time2int(value), settings));
      }
    }

    if (self.data("ui-timepicker-value") != value) {
      self.data("ui-timepicker-value", value);
      if (source == "select") {
        self
          .trigger("selectTime")
          .trigger("changeTime")
          .trigger("change", "timepicker");
      } else if (["error", "initial"].indexOf(source) == -1) {
        self.trigger("changeTime");
      }

      return true;
    } else {
      if (["error", "initial"].indexOf(source) == -1) {
        self.trigger("selectTime");
      }
      return false;
    }
  }

  /*
    *  Filter freeform input
    */
  function _disableTextInputHandler(e) {
    switch (e.keyCode) {
      case 13: // return
      case 9: //tab
        return;

      default:
        e.preventDefault();
    }
  }

  /*
    *  Keyboard navigation via arrow keys
    */
  function KeydownHandler(e) {
    var self = $(this);
    var list = self.data("timepicker-list");

    if (!list || !_isVisible(list)) {
      if (e.keyCode == 40) {
        // show the list!
        methods.show.call(self.get(0));
        list = self.data("timepicker-list");
        if (!_hideKeyboard(self)) {
          self.focus();
        }
      } else {
        return true;
      }
    }

    switch (e.keyCode) {
      case 13: // return
        if (_selectValue(self)) {
          FormatValue.call(self.get(0), { type: "change" });
          methods.hide.apply(this);
        }

        e.preventDefault();
        return false;

      case 38: // up
        var selected = list.find(".ui-timepicker-selected");

        if (!selected.length) {
          list.find("li").each(function(i, obj) {
            if ($(obj).position().top > 0) {
              selected = $(obj);
              return false;
            }
          });
          selected.addClass("ui-timepicker-selected");
        } else if (!selected.is(":first-child")) {
          selected.removeClass("ui-timepicker-selected");
          selected.prev().addClass("ui-timepicker-selected");

          if (selected.prev().position().top < selected.outerHeight()) {
            list.scrollTop(list.scrollTop() - selected.outerHeight());
          }
        }

        return false;

      case 40: // down
        selected = list.find(".ui-timepicker-selected");

        if (selected.length === 0) {
          list.find("li").each(function(i, obj) {
            if ($(obj).position().top > 0) {
              selected = $(obj);
              return false;
            }
          });

          selected.addClass("ui-timepicker-selected");
        } else if (!selected.is(":last-child")) {
          selected.removeClass("ui-timepicker-selected");
          selected.next().addClass("ui-timepicker-selected");

          if (
            selected.next().position().top + 2 * selected.outerHeight() >
            list.outerHeight()
          ) {
            list.scrollTop(list.scrollTop() + selected.outerHeight());
          }
        }

        return false;

      case 27: // escape
        list.find("li").removeClass("ui-timepicker-selected");
        methods.hide();
        break;

      case 9: //tab
        methods.hide();
        break;

      default:
        return true;
    }
  }

  /*
    *   Time typeahead
    */
  function KeyupHandler(e) {
    var self = $(this);
    var list = self.data("timepicker-list");
    var settings = self.data("timepicker-settings");

    if (!list || !_isVisible(list) || settings.disableTextInput) {
      return true;
    }

    if (e.type === "paste" || e.type === "cut") {
      setTimeout(function() {
        if (settings.typeaheadHighlight) {
          _setSelected(self, list);
        } else {
          list.hide();
        }
      }, 0);
      return;
    }

    switch (e.keyCode) {
      case 96: // numpad numerals
      case 97:
      case 98:
      case 99:
      case 100:
      case 101:
      case 102:
      case 103:
      case 104:
      case 105:
      case 48: // numerals
      case 49:
      case 50:
      case 51:
      case 52:
      case 53:
      case 54:
      case 55:
      case 56:
      case 57:
      case 65: // a
      case 77: // m
      case 80: // p
      case 186: // colon
      case 8: // backspace
      case 46: // delete
        if (settings.typeaheadHighlight) {
          _setSelected(self, list);
        } else {
          list.hide();
        }
        break;
    }
  }

  function _selectValue(self) {
    var settings = self.data("timepicker-settings");
    var list = self.data("timepicker-list");
    var timeValue = null;

    var cursor = list.find(".ui-timepicker-selected");

    if (cursor.hasClass("ui-timepicker-disabled")) {
      return false;
    }

    if (cursor.length) {
      // selected value found
      timeValue = cursor.data("time");
    }

    if (timeValue !== null) {
      if (typeof timeValue != "string") {
        timeValue = _int2time(timeValue, settings);
      }

      _setTimeValue(self, timeValue, "select");
    }

    return true;
  }

  function _int2duration(seconds, step) {
    seconds = Math.abs(seconds);
    var minutes = Math.round(seconds / 60),
      duration = [],
      hours,
      mins;

    if (minutes < 60) {
      // Only show (x mins) under 1 hour
      duration = [minutes, _lang.mins];
    } else {
      hours = Math.floor(minutes / 60);
      mins = minutes % 60;

      // Show decimal notation (eg: 1.5 hrs) for 30 minute steps
      if (step == 30 && mins == 30) {
        hours += _lang.decimal + 5;
      }

      duration.push(hours);
      duration.push(hours == 1 ? _lang.hr : _lang.hrs);

      // Show remainder minutes notation (eg: 1 hr 15 mins) for non-30 minute steps
      // and only if there are remainder minutes to show
      if (step != 30 && mins) {
        duration.push(mins);
        duration.push(_lang.mins);
      }
    }

    return duration.join(" ");
  }

  function _int2time(timeInt, settings) {
    if (typeof timeInt != "number") {
      return null;
    }

    var seconds = parseInt(timeInt % 60, 10),
    minutes = parseInt((timeInt / 60) % 60, 10),
    hours = parseInt((timeInt / (60 * 60)) % 24, 10);

    var time = new Date(1970, 0, 2, hours, minutes, seconds, 0);

    if (isNaN(time.getTime())) {
      return null;
    }

    if ($.type(settings.timeFormat) === "function") {
      return settings.timeFormat(time);
    }

    var output = "";
    var hour, code;
    for (var i = 0; i < settings.timeFormat.length; i++) {
      code = settings.timeFormat.charAt(i);
      switch (code) {
        case "a":
          output += time.getHours() > 11 ? _lang.pm : _lang.am;
          break;

        case "A":
          output += time.getHours() > 11 ? _lang.PM : _lang.AM;
          break;

        case "g":
          hour = time.getHours() % 12;
          output += hour === 0 ? "12" : hour;
          break;

        case "G":
          hour = time.getHours();
          if (timeInt === _ONE_DAY) hour = settings.show2400 ? 24 : 0;
          output += hour;
          break;

        case "h":
          hour = time.getHours() % 12;

          if (hour !== 0 && hour < 10) {
            hour = "0" + hour;
          }

          output += hour === 0 ? "12" : hour;
          break;

        case "H":
          hour = time.getHours();
          if (timeInt === _ONE_DAY) hour = settings.show2400 ? 24 : 0;
          output += hour > 9 ? hour : "0" + hour;
          break;

        case "i":
          minutes = time.getMinutes();
          output += minutes > 9 ? minutes : "0" + minutes;
          break;

        case "s":
          seconds = time.getSeconds();
          output += seconds > 9 ? seconds : "0" + seconds;
          break;

        case "\\":
          // escape character; add the next character and skip ahead
          i++;
          output += settings.timeFormat.charAt(i);
          break;

        default:
          output += code;
      }
    }

    return output;
  }

  function _time2int(timeString, settings) {
    if (timeString === "" || timeString === null) return null;
    if (typeof timeString == "object") {
      return (
        timeString.getHours() * 3600 +
        timeString.getMinutes() * 60 +
        timeString.getSeconds()
      );
    }
    if (typeof timeString != "string") {
      return timeString;
    }

    timeString = timeString.toLowerCase().replace(/[\s\.]/g, "");

    // if the last character is an "a" or "p", add the "m"
    if (timeString.slice(-1) == "a" || timeString.slice(-1) == "p") {
      timeString += "m";
    }

    var ampmRegex =
      "(" +
      _lang.am.replace(".", "") +
      "|" +
      _lang.pm.replace(".", "") +
      "|" +
      _lang.AM.replace(".", "") +
      "|" +
      _lang.PM.replace(".", "") +
      ")?";

    // try to parse time input
    var pattern = new RegExp(
      "^" +
        ampmRegex +
        "([0-9]?[0-9])\\W?([0-5][0-9])?\\W?([0-5][0-9])?" +
        ampmRegex +
        "$"
    );

    var time = timeString.match(pattern);
    if (!time) {
      return null;
    }

    var hour = parseInt(time[2] * 1, 10);
    var ampm = time[1] || time[5];
    var hours = hour;
    var minutes = time[3] * 1 || 0;
    var seconds = time[4] * 1 || 0;

    if (hour <= 12 && ampm) {
      var isPm = ampm == _lang.pm || ampm == _lang.PM;

      if (hour == 12) {
        hours = isPm ? 12 : 0;
      } else {
        hours = hour + (isPm ? 12 : 0);
      }
    } else if (settings) {
      var t = hour * 3600 + minutes * 60 + seconds;
      if (t >= _ONE_DAY + (settings.show2400 ? 1 : 0)) {
        if (settings.wrapHours === false) {
          return null;
        }

        hours = hour % 24;
      }
    }

    var timeInt = hours * 3600 + minutes * 60 + seconds;

    // if no am/pm provided, intelligently guess based on the scrollDefault
    if (
      hour < 12 &&
      !ampm &&
      settings &&
      settings._twelveHourTime &&
      settings.scrollDefault
    ) {
      var delta = timeInt - settings.scrollDefault();
      if (delta < 0 && delta >= _ONE_DAY / -2) {
        timeInt = (timeInt + _ONE_DAY / 2) % _ONE_DAY;
      }
    }

    return timeInt;
  }

  function _moduloSeconds(seconds, settings) {
    if (seconds == _ONE_DAY && settings.show2400) {
      return seconds;
    }

    return seconds % _ONE_DAY;
  }

  // Plugin entry
  $.fn.timepicker = function(method) {
    if (!this.length) return this;
    if (methods[method]) {
      // check if this element is a timepicker
      if (!this.hasClass("ui-timepicker-input")) {
        return this;
      }
      return methods[method].apply(
        this,
        Array.prototype.slice.call(arguments, 1)
      );
    } else if (typeof method === "object" || !method) {
      return methods.init.apply(this, arguments);
    } else {
      $.error("Method " + method + " does not exist on jQuery.timepicker");
    }
  };
});