{"version":3,"sources":["../vendor/jquery/dist/jquery.js","../vendor/jquery-ui/ui/minified/jquery-ui.min.js","../vendor/angular/angular.js","../vendor/angular-bootstrap/ui-bootstrap-tpls.js","../vendor/select2/select2.js","../vendor/messageformat/messageformat.js","../vendor/fotorama/fotorama.js","../vendor/angular-ui-router/release/angular-ui-router.js","config.js","../vendor/underscore/underscore.js","../vendor/momentjs/moment.js","../vendor/raven-js/dist/raven.min.js","../vendor/not-bower/source-map.js","modules/common/local-storage-service.js","modules/common/permissions-service.js","text!modules/appointment/appointment-search-typeahead-grid-directive/appointment-search-typeahead-grid.tpl.html","modules/common/enums-service.js","modules/resources/company-setting.js","modules/resources/contact.js","../vendor/angular-sanitize/angular-sanitize.js","../vendor/not-bower/fullcalendar_resource/fullcalendar.js","modules/appointment/search/search-ctrl.js","../vendor/not-bower/dymo/DYMO.Label.Framework.3.0.js","modules/contact/sms-service.js","modules/calendar/fitting-room/fitting-room.js","modules/common/directives.js","modules/common/avery-label-helper-service.js","../vendor/not-bower/tinymce/tinymce.min.js","modules/common/toggle-switch-directive.js","modules/contact/modals/request-payment-information-ctrl.js","modules/dashboard/attention-items-ctrl.js","modules/resources/appointment-block.js","modules/settings/fitting-room/events/setup-event-blocks-ctrl.js","modules/settings/fitting-room/blocks/add-block-modal-ctrl.js","modules/resources/reports.js","modules/notifications/index.js","modules/contact-modal/wedding-registry-ctrl.js","../vendor/angular-multi-select/angular-multi-select.js","modules/item/favorited-by/favorited-by-ctrl.js","modules/item/search/search-ctrl.js","modules/item/config.js","modules/marketplace/download/matches-popover-directive.js","modules/prom-registry-modal/register-to-prom-ctrl.js","modules/resources/purchase-order.js","modules/purchase-order/purchase-order-ctrl.js","text!modules/item/item-search-typeahead-grid-directive/items-search-typeahead-grid.tpl.html","modules/quote/details/quote-details-ctrl.js","modules/quote/details/modals/ship-to-customer-ctrl.js","modules/quote/search/search-ctrl.js","modules/reports/common-ctrl.js","../vendor/chart.js/dist/Chart.js","modules/reports/appointment-count-by-month/index.js","modules/reports/favorite-items-summary/index.js","modules/reports/sales-by-month/index.js","modules/reports/payment-journal/index.js","modules/reports/email-history-log/index.js","modules/reports/funding-report/index.js","modules/referrals/module.js","modules/settings/calendar-black-out-dates/index.js","modules/settings/client-portal-preferences/index.js","modules/settings/payment-plans/index.js","modules/settings/commissions/index.js","modules/settings/quickbooks/qbo-helper-service.js","modules/settings/role/index.js","modules/settings/smart-flow/index.js","modules/settings/fiskaly/index.js","modules/settings/enhanced-web-forms/appointment-scheduler/index.js","modules/settings/enhanced-web-forms/enhanced-lead/index.js","modules/task/module.js","modules/transaction/details/modals/sign-sales-agreement-ctrl.js","modules/transaction/details/modals/request-signature-ctrl.js","modules/transaction/details/transaction-details-ctrl.js","modules/transaction/line-item-address-info-popover/line-item-address-info-popover-directive.js","modules/payment-plans/modals/view-payment-plan/view-payment-plan-modal-ctrl.js","modules/transaction/search/search-ctrl.js","modules/vendor/search-ctrl.js","modules/wait-list/module.js","modules/wait-list/modal/edit-wait-list-ctrl.js"],"names":["descriptor","expando","unlock","Animation","extend","data_priv","doAnimation","empty","queue","$httpProvider","stopQueue","stop","DEBUG","defaults","useXDomain","containerCache","left","this","containers","attr","s","prev","r","debugInfoEnabled","datepicker","$animateProvider","a","duration","_clickOffset","top","call","obj","key","int","exec","ngRepeat","createComment","match","module","tab","active","ƕ","bind","nl*","reportFailures","_html","html","es-mx*","Yd","*","transactionRequired","group","nav","window","navigator","browserLanguagePropertyKeys","fn","i","isSetup","sourceRoot","localStorage","setItem","JSON","DELETE_CONTACTS","id","groupName","PERMISSION_TO_APPROVE_REQUESTED_PAYMENT_UPDATES","language","length","regexp","test","description","POS_COPY_LINE_ITEM_NOTES_DEFAULT","POS_UNISSUED_SOS_NON_INV","completeBMRegistriesWOPO","buildQueryParameters","seg","$translateProvider","checkedIn","define","arguments","Vd","U","paramName","url","responseXML","getElementsByTagName","urlParts","objectURL","getUrl","$on","labelTemplate","t","attributesForced","removeEmptyAttrs","h","n","selectedRange","explicitRange","nodeType","A","R","e","parents","hasChildNodes","firstChild","resize","onResizeStart","restrict","$scope","request","promises","getAppointmentBlockTypes","onAppointmentTypeChange","log","exports","isValid","appointmentTypeId","types","fittingRoomId","salesPerformanceExport","Error","factory","w","element","global","sizeGroups","size_groups","vendorItemAddOns","changeSearch","INVENTORY_ITEM_NO_BARCODE_NO_PRICE","arr","slice","concat","$compile","controller","status","indexOf","post","addOn","readonly","toString","class2type","markSignSalesAgreementGreen","hasOwnProperty","shippingTaxCodeId","enumStatuses","criteria","departmentIds","formValues","selectedDepartments","ghostwhite","jQuery","gold","selector","goldenrod","custom","dataset","getDataset","lineElementOptions","options","line","me","chart","mouseX","mouseY","addEvent","angleLines","pointLabels","jquery","version","instant","filterObject","query","label","templateUrl","num","results","without","blackOutDate","editMode","blackOut","pushStack","elems","showDescription","ret","showFirstInstallmentDate","currencySymbol","prevObject","qbCogsSaleId","blDept","modifiedByUser","username","pluck","apptTypeVisible","FiskalySettings","defaultErrorHandler","pushError","map","callback","leadForm","enhancedSettings","LEADS","cache","settings","elem","lastSignature","message","optedErrors","pushSuccess","transaction","showPopover","eq","isOpening","Enums","trxTypes","adaptList","employees","showConfirmation","name","len","j","$stateProvider","dateTimes","push","times","startTime","Date"],"mappings":"YA47GAA,OAAAC,gBAAAC,WAuiGAC,OAAAC,qBAGAC,gBAAA,mBAIAC,mBAEAC,2BACAD,QACAE,SAAAA,EAEAC,EACAC,EACAC,EACAA,EAIAC,GCn/MA,UACAH,GAAAI,SAAAC,WAAA,WACAC,GAAAA,SAAAC,QAAAC,OAAAC,mBACAD,GAAAE,sBAAA,4BAAAC,OAAAC,YACAC,GAAAC,iBAAAC,EACAC,GAAAC,gBAAAC,kFACAC,GAAAC,sBCwTAC,SAAAC,gBA2kKAC,SAGA,SA8vUAC,GAAAC,+BA8yQAC,GACAC,+BAEA,KAAAC,KAAAA,KAAA,KAAA,KAAA,KAAA,UCxnvBAC,MAAA,KA45EAC,MAAAC,KC/nFAC,MAAA,KAm6DAxB,MAAAyB,KC36BAC,MAAAC,KCzlCAC,MAAAC,KACAC,SAAAC,QCooIAC,IAAA,MCxuGAC,GACAC,2BAAA,WA4iBA,GAAAC,GAAAC,OAAAC,SClaA,IACAC,IACA,WAAAxB,kBAAA3B,iBAMA,eCo0BAoD,IACAC,ECv3DA,IAAAC,ECy1CAC,IAAAA,GACA,sCCtyCAC,IAAAA,QAAAC,QAAAC,EAAAA,WAAA/B,CC6CAgC,IAAAA,EAAAA,EAAAA,EAAAC,EAAAA,UAAAD,OAAAA,IAAAE,CAyOAC,EAAAA,EAAAA,UAAAA,ECxUA,IAAAC,GAAAA,EAAAC,QAAAC,EAAAC,KAAAH,GAAA,CCqWAI,MAAAJ,KCIAK,IAAAA,EAAAA,EAAAA,EAAAA,EAAAJ,OAAAX,IACAgB,CC7JAC,EAAAtB,EAAAG,EACAoB,GCIA,IAAAR,GAAAA,EAAAC,QAAAC,EAAAC,KAAAH,GACA,CC88EAC,MACAQ,MCtrEAC,GAGAC,sBChfAC,QAAArD,oCAAAsD,WA6DA,GAAAC,IAmEAC,YACA,SAAAC,EAAAC,GC8MAC,GAAAC,EC1CAlB,IAAAA,KCmpBA,IAAAmB,IAAAC,GACArE,EAAAsE,UAGAC,MAAA,ICx5BAC,KAAAA,EAAA,GAAA,CC7BAC,MAAAlE,GAGAmE,GAAAA,GAAAC,EAAAC,GAAA3B,MAAAA,KAAA,EACAX,GAAAuC,MAAAC,KAAAA,QAAAC,SAAAA,GACAC,EAAAA,EAAAC,MAAAC,IAEAC,IAAAC,EAAAA,KAAApB,EAAA,CACAqB,EAAAA,mBAAA/C,EAAAgD,MAUAC,OAAAC,ICtBAC,SAAA,WCgBA,MACAC,UAAAC,MC+FA1C,OACA2C,MCrBAC,SAAAA,EAAAA,GC2CAC,SAAAA,UAAA,gBACAC,QAAAC,UAGAN,SAAAO,CCpFA9E,OAAA6E,QACAE,EAAAA,SAAAC,EAAAlD,EAAAJ,MACAuD,SAAAA,GC6hBAC,IAAAA,EAAAA,SAAA,CCrlBA,KAAA,IAAAC,OAAA,4CC2SA,MAAAC,GAAAC,QC8RAC,CClkBAF,EAAAG,YCqSAC,UACAC,YACAC,OAAAA,KAAAA,SAIAC,EAAAA,GCYAC,GAAAA,KAyyBAnD,IAAAA,GAAAoD,EAAAC,KC7lCA,IAAAC,GACAF,EAAAG,MChBA,IAEAhG,GAAAiG,EAAAA,ICoDAC,IAAAC,GAGAC,EAAAA,OCu7BAC,IACAC,KC/+BA7D,IAAA8D,GAAAC,EAAAD,QCoZAE,IAAAA,GAAAA,EAAAC,cCvHAC,IAAAA,GAAAA,GAAAjF,IC/QAkF,IAAAA,KCqBAC,IAAAC,GAAAA,EAAAC,SAAAC,EAAAA,QAAAA,EAAA,SAGAzC,EAAAwC,GCm/CAE,MAAA,IAAAC,GACAC,GAAAA,KAAAC,EACAC,IA8yDAC,EACAC,QAAAC,EACAC,eAAAC,EAAAC,SACAC,EAAAC,GAovEAC,MACAC,GAIAC,cAgsLAC,GAAAA,GACAf,EAAAgB,WC/tWAC,SAAAC,EC0BAC,cAAAnB,EC7CAoB,WAAApC,GCGAqC,SAAAD,ECoDArG,UAAAoG,WC6BAG,MAAA1C,GAAAtG,KAAAb,OCxFA8J,MAAA,SAAAC,GCiLAC,MAAAC,IAAAA,KAAAC,EAKAC,EAAAA,KAAAJ,EAAA/J,KACAoK,QAAAD,KAAAA,GAEAhD,EAAAgD,KAAAA,OCwsCAE,YAEAhE,SACAiE,GCtrCAC,GAAAC,GACAC,EAAAA,MAAAA,KAAAA,cACAC,EClBAF,GAAAG,WAAA3K,ICgCA4K,GAAAA,QAGA5K,KACA6K,OCzDAC,OAAAC,IC2JAC,OAAA,SACAC,EAAAA,GCoIAC,MAAAC,GAAAA,KAAAA,KAAA5D,EACA6D,ICzbAC,MAAA,SAAAC,GCGAC,MAAAA,MAAAC,UAEAD,EAAAE,IAAAA,KAIAC,SACAC,EAAAnJ,GCVA,MAAA8I,GAAAzK,KAAA+K,EAAApJ,EAAAoJ,OCcAC,QAAAA,WCkNAC,MAAAC,MAAAA,UAAAD,EAAAA,MAAAA,KAGAE,aC63CAC,QAAAA,WC/lDAC,MAAAA,MACAC,GAAAC,ICqHAC,OAAAC,WClEAC,MAAAvM,MAAAmM,IAAAK,ICZAL,KAGAM,SAAAA,GCpDAC,GACAC,GAAA3M,KAAAmD,OAAAyJ,GAAApK,GAAAkK,EAAA,EAAAC,EAGAE,ECuPAC,OAAAC,MACAhK,UAAAiK,GAAA,GACAC,EAAAA,GAAAjN,KAAAkN","file":"main.client-portal.js","sourcesContent":["/*!\n * jQuery JavaScript Library v2.1.0\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-01-23T21:10Z\n */\n\n(function( global, factory ) {\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\t\t// For CommonJS and CommonJS-like environments where a proper window is present,\n\t\t// execute the factory and get jQuery\n\t\t// For environments that do not inherently posses a window with a document\n\t\t// (such as Node.js), expose a jQuery-making factory as module.exports\n\t\t// This accentuates the need for the creation of a real window\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n}(typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Can't do this because several apps including ASP.NET trace\n// the stack via arguments.caller.callee and Firefox dies if\n// you try to trace through \"use strict\" call chains. (#13335)\n// Support: Firefox 18+\n//\n\nvar arr = [];\n\nvar slice = arr.slice;\n\nvar concat = arr.concat;\n\nvar push = arr.push;\n\nvar indexOf = arr.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar trim = \"\".trim;\n\nvar support = {};\n\n\n\nvar\n\t// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\n\n\tversion = \"2.1.0\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\treturn new jQuery.fn.init( selector, context );\n\t},\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([\\da-z])/gi,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t};\n\njQuery.fn = jQuery.prototype = {\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num != null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\t( num < 0 ? this[ num + this.length ] : this[ num ] ) :\n\n\t\t\t// Return just the object\n\t\t\tslice.call( this );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\t\tret.context = this.context;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: arr.sort,\n\tsplice: arr.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\t// Unique for each copy of jQuery on the page\n\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// Assume jQuery is ready without the ready module\n\tisReady: true,\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tnoop: function() {},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray,\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\t// parseFloat NaNs numeric-cast false positives (null|true|false|\"\")\n\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t// subtraction forces infinities to NaN\n\t\treturn obj - parseFloat( obj ) >= 0;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Not plain objects:\n\t\t// - Any object or value whose internal [[Class]] property is not \"[object Object]\"\n\t\t// - DOM nodes\n\t\t// - window\n\t\tif ( jQuery.type( obj ) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Support: Firefox <20\n\t\t// The try/catch suppresses exceptions thrown when attempting to access\n\t\t// the \"constructor\" property of certain host objects, ie. |window.location|\n\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=814622\n\t\ttry {\n\t\t\tif ( obj.constructor &&\n\t\t\t\t\t!hasOwn.call( obj.constructor.prototype, \"isPrototypeOf\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If the function hasn't returned already, we're confident that\n\t\t// |obj| is a plain object, created by {} or constructed with new Object\n\t\treturn true;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn obj + \"\";\n\t\t}\n\t\t// Support: Android < 4.0, iOS < 6 (functionish RegExp)\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ toString.call(obj) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\t// Evaluates a script in a global context\n\tglobalEval: function( code ) {\n\t\tvar script,\n\t\t\tindirect = eval;\n\n\t\tcode = jQuery.trim( code );\n\n\t\tif ( code ) {\n\t\t\t// If the code includes a valid, prologue position\n\t\t\t// strict mode pragma, execute code by injecting a\n\t\t\t// script tag into the document.\n\t\t\tif ( code.indexOf(\"use strict\") === 1 ) {\n\t\t\t\tscript = document.createElement(\"script\");\n\t\t\t\tscript.text = code;\n\t\t\t\tdocument.head.appendChild( script ).parentNode.removeChild( script );\n\t\t\t} else {\n\t\t\t// Otherwise, avoid the DOM node creation, insertion\n\t\t\t// and removal by using an indirect global eval\n\t\t\t\tindirect( code );\n\t\t\t}\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( obj, callback, args ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = obj.length,\n\t\t\tisArray = isArraylike( obj );\n\n\t\tif ( args ) {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\ttrim: function( text ) {\n\t\treturn text == null ? \"\" : trim.call( text );\n\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArraylike( Object(arr) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpush.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\treturn arr == null ? -1 : indexOf.call( arr, elem, i );\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\tfor ( ; j < len; j++ ) {\n\t\t\tfirst[ i++ ] = second[ j ];\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, invert ) {\n\t\tvar callbackInverse,\n\t\t\tmatches = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tcallbackExpect = !invert;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tisArray = isArraylike( elems ),\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar tmp, args, proxy;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\tnow: Date.now,\n\n\t// jQuery.support is not used in Core but other projects attach their\n\t// properties to it so it needs to exist.\n\tsupport: support\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nfunction isArraylike( obj ) {\n\tvar length = obj.length,\n\t\ttype = jQuery.type( obj );\n\n\tif ( type === \"function\" || jQuery.isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\tif ( obj.nodeType === 1 && length ) {\n\t\treturn true;\n\t}\n\n\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\nvar Sizzle =\n/*!\n * Sizzle CSS Selector Engine v1.10.16\n * http://sizzlejs.com/\n *\n * Copyright 2013 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-01-13\n */\n(function( window ) {\n\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\tcompile,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + -(new Date()),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// General-purpose constants\n\tstrundefined = typeof undefined,\n\tMAX_NEGATIVE = 1 << 31,\n\n\t// Instance methods\n\thasOwn = ({}).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpush_native = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf if we can't use a native one\n\tindexOf = arr.indexOf || function( elem ) {\n\t\tvar i = 0,\n\t\t\tlen = this.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( this[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\t// http://www.w3.org/TR/css3-syntax/#characters\n\tcharacterEncoding = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n\t// Loosely modeled on CSS identifier characters\n\t// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors\n\t// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n\t// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")\" + whitespace +\n\t\t\"*(?:([*^$|!~]?=)\" + whitespace + \"*(?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(\" + identifier + \")|)|)\" + whitespace + \"*\\\\]\",\n\n\t// Prefer arguments quoted,\n\t// then not containing pseudos/brackets,\n\t// then attribute selectors/non-parenthetical expressions,\n\t// then anything else\n\t// These preferences are here to reduce the number of selectors\n\t// needing tokenize in the PSEUDO preFilter\n\tpseudos = \":(\" + characterEncoding + \")(?:\\\\(((['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes.replace( 3, 8 ) + \")*)|.*)\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n\trattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\n\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trsibling = /[+~]/,\n\trescape = /'|\\\\/g,\n\n\t// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\t// Support: Firefox\n\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\treturn high !== high || escapedWhitespace ?\n\t\t\tescaped :\n\t\t\thigh < 0 ?\n\t\t\t\t// BMP codepoint\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t};\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\tpreferredDoc.childNodes\n\t);\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar match, elem, m, nodeType,\n\t\t// QSA vars\n\t\ti, groups, old, nid, newContext, newSelector;\n\n\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\n\tcontext = context || document;\n\tresults = results || [];\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tif ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( documentIsHTML && !seed ) {\n\n\t\t// Shortcuts\n\t\tif ( (match = rquickExpr.exec( selector )) ) {\n\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\tif ( (m = match[1]) ) {\n\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\telem = context.getElementById( m );\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document (jQuery #6963)\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE, Opera, and Webkit return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Context is not a document\n\t\t\t\t\tif ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n\t\t\t\t\t\tcontains( context, elem ) && elem.id === m ) {\n\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t} else if ( match[2] ) {\n\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\treturn results;\n\n\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {\n\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\treturn results;\n\t\t\t}\n\t\t}\n\n\t\t// QSA path\n\t\tif ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\t\t\tnid = old = expando;\n\t\t\tnewContext = context;\n\t\t\tnewSelector = nodeType === 9 && selector;\n\n\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t// IE 8 doesn't work on object elements\n\t\t\tif ( nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\tgroups = tokenize( selector );\n\n\t\t\t\tif ( (old = context.getAttribute(\"id\")) ) {\n\t\t\t\t\tnid = old.replace( rescape, \"\\\\$&\" );\n\t\t\t\t} else {\n\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t}\n\t\t\t\tnid = \"[id='\" + nid + \"'] \";\n\n\t\t\t\ti = groups.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tgroups[i] = nid + toSelector( groups[i] );\n\t\t\t\t}\n\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;\n\t\t\t\tnewSelector = groups.join(\",\");\n\t\t\t}\n\n\t\t\tif ( newSelector ) {\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t);\n\t\t\t\t\treturn results;\n\t\t\t\t} catch(qsaError) {\n\t\t\t\t} finally {\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.removeAttribute(\"id\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {Function(string, Object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar keys = [];\n\n\tfunction cache( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key + \" \" ] = value);\n\t}\n\treturn cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created div and expects a boolean result\n */\nfunction assert( fn ) {\n\tvar div = document.createElement(\"div\");\n\n\ttry {\n\t\treturn !!fn( div );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// Remove from its parent by default\n\t\tif ( div.parentNode ) {\n\t\t\tdiv.parentNode.removeChild( div );\n\t\t}\n\t\t// release memory in IE\n\t\tdiv = null;\n\t}\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n\tvar arr = attrs.split(\"|\"),\n\t\ti = attrs.length;\n\n\twhile ( i-- ) {\n\t\tExpr.attrHandle[ arr[i] ] = handler;\n\t}\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\t( ~b.sourceIndex || MAX_NEGATIVE ) -\n\t\t\t( ~a.sourceIndex || MAX_NEGATIVE );\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== strundefined && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc,\n\t\tparent = doc.defaultView;\n\n\t// If no document and documentElement is available, return\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Set our document\n\tdocument = doc;\n\tdocElem = doc.documentElement;\n\n\t// Support tests\n\tdocumentIsHTML = !isXML( doc );\n\n\t// Support: IE>8\n\t// If iframe document is assigned to \"document\" variable and if iframe has been reloaded,\n\t// IE will throw \"permission denied\" error when accessing \"document\" variable, see jQuery #13936\n\t// IE6-8 do not support the defaultView property so parent will be undefined\n\tif ( parent && parent !== parent.top ) {\n\t\t// IE11 does not have attachEvent, so all must suffer\n\t\tif ( parent.addEventListener ) {\n\t\t\tparent.addEventListener( \"unload\", function() {\n\t\t\t\tsetDocument();\n\t\t\t}, false );\n\t\t} else if ( parent.attachEvent ) {\n\t\t\tparent.attachEvent( \"onunload\", function() {\n\t\t\t\tsetDocument();\n\t\t\t});\n\t\t}\n\t}\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)\n\tsupport.attributes = assert(function( div ) {\n\t\tdiv.className = \"i\";\n\t\treturn !div.getAttribute(\"className\");\n\t});\n\n\t/* getElement(s)By*\n\t---------------------------------------------------------------------- */\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.getElementsByTagName = assert(function( div ) {\n\t\tdiv.appendChild( doc.createComment(\"\") );\n\t\treturn !div.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Check if getElementsByClassName can be trusted\n\tsupport.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {\n\t\tdiv.innerHTML = \"
\";\n\n\t\t// Support: Safari<4\n\t\t// Catch class over-caching\n\t\tdiv.firstChild.className = \"i\";\n\t\t// Support: Opera<10\n\t\t// Catch gEBCN failure to find non-leading classes\n\t\treturn div.getElementsByClassName(\"i\").length === 2;\n\t});\n\n\t// Support: IE<10\n\t// Check if getElementById returns elements by name\n\t// The broken getElementById methods don't pick up programatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert(function( div ) {\n\t\tdocElem.appendChild( div ).id = expando;\n\t\treturn !doc.getElementsByName || !doc.getElementsByName( expando ).length;\n\t});\n\n\t// ID find and filter\n\tif ( support.getById ) {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== strundefined && documentIsHTML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t} else {\n\t\t// Support: IE6/7\n\t\t// getElementById is not reliable as a find shortcut\n\t\tdelete Expr.find[\"ID\"];\n\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.getElementsByTagName ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== strundefined ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\t\t\t}\n\t\t} :\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t/* QSA/matchesSelector\n\t---------------------------------------------------------------------- */\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21)\n\t// We allow this because of a bug in IE8/9 that throws an error\n\t// whenever `document.activeElement` is accessed on an iframe\n\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t// See http://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( div ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// http://bugs.jquery.com/ticket/12359\n\t\t\tdiv.innerHTML = \"\";\n\n\t\t\t// Support: IE8, Opera 10-12\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\tif ( div.querySelectorAll(\"[t^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !div.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( div ) {\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = doc.createElement(\"input\");\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tdiv.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( div.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":enabled\").length ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tdiv.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( div ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( div, \"div\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( div, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully does not implement inclusive descendent\n\t// As in, an element does not contain itself\n\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = hasCompare ?\n\tfunction( a, b ) {\n\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\tif ( compare ) {\n\t\t\treturn compare;\n\t\t}\n\n\t\t// Calculate position if both inputs belong to the same document\n\t\tcompare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t// Otherwise we know they are disconnected\n\t\t\t1;\n\n\t\t// Disconnected nodes\n\t\tif ( compare & 1 ||\n\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t// Choose the first element that is related to our preferred document\n\t\t\tif ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// Maintain original order\n\t\t\treturn sortInput ?\n\t\t\t\t( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :\n\t\t\t\t0;\n\t\t}\n\n\t\treturn compare & 4 ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\tif ( !aup || !bup ) {\n\t\t\treturn a === doc ? -1 :\n\t\t\t\tb === doc ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\tsortInput ?\n\t\t\t\t( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\treturn doc;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\t// Make sure that attribute selectors are quoted\n\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\tif ( support.matchesSelector && documentIsHTML &&\n\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {\n\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch(e) {}\n\t}\n\n\treturn Sizzle( expr, document, null, [elem] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\tundefined;\n\n\treturn val !== undefined ?\n\t\tval :\n\t\tsupport.attributes || !documentIsHTML ?\n\t\t\telem.getAttribute( name ) :\n\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\tnull;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\tj = 0,\n\t\ti = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tsortInput = !support.sortStable && results.slice( 0 );\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\twhile ( (elem = results[i++]) ) {\n\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\t// Clear input after sorting to release objects\n\t// See https://github.com/jquery/sizzle/pull/225\n\tsortInput = null;\n\n\treturn results;\n};\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\twhile ( (node = elem[i++]) ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tattrHandle: {},\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[5] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[3] && match[4] !== undefined ) {\n\t\t\t\tmatch[2] = match[4];\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\tfunction() { return true; } :\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute(\"class\") || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, outerCache, node, diff, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\t\t\t\t\t\t\touterCache = parent[ expando ] || (parent[ expando ] = {});\n\t\t\t\t\t\t\tcache = outerCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[0] === dirruns && cache[1];\n\t\t\t\t\t\t\tdiff = cache[0] === dirruns && cache[2];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\touterCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {\n\t\t\t\t\t\t\tdiff = cache[1];\n\n\t\t\t\t\t\t// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\tif ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {\n\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf.call( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifier\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": function( elem ) {\n\t\t\treturn elem.disabled === false;\n\t\t},\n\n\t\t\"disabled\": function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t// but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\nfunction tokenize( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( (tokens = []) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push({\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t});\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push({\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t});\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n}\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tcheckNonElements = base && dir === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, outerCache,\n\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\t\t\t\t\t\tif ( (oldCache = outerCache[ dir ]) &&\n\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\treturn (newCache[ 2 ] = oldCache[ 2 ]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\touterCache[ dir ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf.call( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\treturn ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context !== document && context;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Keep `i` a string if there are no elements so `matchedCount` will be \"00\" below\n\t\t\t// Support: IE<9, Safari\n\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: ) matching elements by id\n\t\t\tfor ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\tmatchedCount += i;\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !group ) {\n\t\t\tgroup = tokenize( selector );\n\t\t}\n\t\ti = group.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( group[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\t}\n\treturn cached;\n};\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction select( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tmatch = tokenize( selector );\n\n\tif ( !seed ) {\n\t\t// Try to minimize operations if there is only one group\n\t\tif ( match.length === 1 ) {\n\n\t\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t\ttokens = match[0] = match[0].slice( 0 );\n\t\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\t\tsupport.getById && context.nodeType === 9 && documentIsHTML &&\n\t\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n\n\t\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\t\tif ( !context ) {\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\t\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t\t}\n\n\t\t\t// Fetch a seed set for right-to-left matching\n\t\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\ttoken = tokens[i];\n\n\t\t\t\t// Abort if we hit a combinator\n\t\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\t\tif ( (seed = find(\n\t\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t\t)) ) {\n\n\t\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\tcompile( selector, match )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\trsibling.test( selector ) && testContext( context.parentNode ) || context\n\t);\n\treturn results;\n}\n\n// One-time assignments\n\n// Sort stability\nsupport.sortStable = expando.split(\"\").sort( sortOrder ).join(\"\") === expando;\n\n// Support: Chrome<14\n// Always assume duplicates if they aren't passed to the comparison function\nsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\nsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\nsupport.sortDetached = assert(function( div1 ) {\n\t// Should return 1, but returns 4 (following)\n\treturn div1.compareDocumentPosition( document.createElement(\"div\") ) & 1;\n});\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert(function( div ) {\n\tdiv.innerHTML = \"\";\n\treturn div.firstChild.getAttribute(\"href\") === \"#\" ;\n}) ) {\n\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\tif ( !isXML ) {\n\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\nif ( !support.attributes || !assert(function( div ) {\n\tdiv.innerHTML = \"\";\n\tdiv.firstChild.setAttribute( \"value\", \"\" );\n\treturn div.firstChild.getAttribute( \"value\" ) === \"\";\n}) ) {\n\taddHandle( \"value\", function( elem, name, isXML ) {\n\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\treturn elem.defaultValue;\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\nif ( !assert(function( div ) {\n\treturn div.getAttribute(\"disabled\") == null;\n}) ) {\n\taddHandle( booleans, function( elem, name, isXML ) {\n\t\tvar val;\n\t\tif ( !isXML ) {\n\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t\t(val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\tnull;\n\t\t}\n\t});\n}\n\nreturn Sizzle;\n\n})( window );\n\n\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.pseudos;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n\nvar rneedsContext = jQuery.expr.match.needsContext;\n\nvar rsingleTag = (/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/);\n\n\n\nvar risSimple = /^.[^:#\\[\\.,]*$/;\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, not ) {\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\t/* jshint -W018 */\n\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t});\n\n\t}\n\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t});\n\n\t}\n\n\tif ( typeof qualifier === \"string\" ) {\n\t\tif ( risSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter( qualifier, elements, not );\n\t\t}\n\n\t\tqualifier = jQuery.filter( qualifier, elements );\n\t}\n\n\treturn jQuery.grep( elements, function( elem ) {\n\t\treturn ( indexOf.call( qualifier, elem ) >= 0 ) !== not;\n\t});\n}\n\njQuery.filter = function( expr, elems, not ) {\n\tvar elem = elems[ 0 ];\n\n\tif ( not ) {\n\t\texpr = \":not(\" + expr + \")\";\n\t}\n\n\treturn elems.length === 1 && elem.nodeType === 1 ?\n\t\tjQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :\n\t\tjQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t}));\n};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar i,\n\t\t\tlen = this.length,\n\t\t\tret = [],\n\t\t\tself = this;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn this.pushStack( jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}) );\n\t\t}\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\t// Needed because $( selector, context ) becomes $( context ).find( selector )\n\t\tret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );\n\t\tret.selector = this.selector ? this.selector + \" \" + selector : selector;\n\t\treturn ret;\n\t},\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], false) );\n\t},\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], true) );\n\t},\n\tis: function( selector ) {\n\t\treturn !!winnow(\n\t\t\tthis,\n\n\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\tfalse\n\t\t).length;\n\t}\n});\n\n\n// Initialize a jQuery object\n\n\n// A central reference to the root jQuery(document)\nvar rootjQuery,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,\n\n\tinit = jQuery.fn.init = function( selector, context ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector[0] === \"<\" && selector[ selector.length - 1 ] === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\n\t\t\t\t\t// scripts is true for back-compat\n\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[1],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn typeof rootjQuery.ready !== \"undefined\" ?\n\t\t\t\trootjQuery.ready( selector ) :\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t};\n\n// Give the init function the jQuery prototype for later instantiation\ninit.prototype = jQuery.fn;\n\n// Initialize central reference\nrootjQuery = jQuery( document );\n\n\nvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.extend({\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\ttruncate = until !== undefined;\n\n\t\twhile ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmatched.push( elem );\n\t\t\t}\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar matched = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tmatched.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn matched;\n\t}\n});\n\njQuery.fn.extend({\n\thas: function( target ) {\n\t\tvar targets = jQuery( target, this ),\n\t\t\tl = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tmatched = [],\n\t\t\tpos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tfor ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {\n\t\t\t\t// Always skip document fragments\n\t\t\t\tif ( cur.nodeType < 11 && (pos ?\n\t\t\t\t\tpos.index(cur) > -1 :\n\n\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\tjQuery.find.matchesSelector(cur, selectors)) ) {\n\n\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn indexOf.call( this,\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t);\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.unique(\n\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t)\n\t\t);\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter(selector)\n\t\t);\n\t}\n});\n\nfunction sibling( cur, dir ) {\n\twhile ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}\n\treturn cur;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn elem.contentDocument || jQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.unique( matched );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tmatched.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched );\n\t};\n});\nvar rnotwhite = (/\\S+/g);\n\n\n\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n\tvar object = optionsCache[ options ] = {};\n\tjQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t});\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\t( optionsCache[ options ] || createOptions( options ) ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\n\t\t\t\t\t(function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== \"string\" ) {\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t})( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\tfiringLength = 0;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( list && ( !fired || stack ) ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\t\t\t\t// action, add listener, listener list, final state\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), \"rejected\" ],\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks(\"memory\") ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tthen: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\t\t\tvar fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n\t\t\t\t\t\t\t// deferred[ done | fail | progress ] for forwarding actions to newDefer\n\t\t\t\t\t\t\tdeferred[ tuple[1] ](function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Keep pipe for back-compat\n\t\tpromise.pipe = promise.then;\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 3 ];\n\n\t\t\t// promise[ done | fail | progress ] = list.add\n\t\t\tpromise[ tuple[1] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(function() {\n\t\t\t\t\t// state = [ resolved | rejected ]\n\t\t\t\t\tstate = stateString;\n\n\t\t\t\t// [ reject_list | resolve_list ].disable; progress_list.lock\n\t\t\t\t}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n\t\t\t}\n\n\t\t\t// deferred[ resolve | reject | notify ]\n\t\t\tdeferred[ tuple[0] ] = function() {\n\t\t\t\tdeferred[ tuple[0] + \"With\" ]( this === deferred ? promise : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\t\t\tdeferred[ tuple[0] + \"With\" ] = list.fireWith;\n\t\t});\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( subordinate /* , ..., subordinateN */ ) {\n\t\tvar i = 0,\n\t\t\tresolveValues = slice.call( arguments ),\n\t\t\tlength = resolveValues.length,\n\n\t\t\t// the count of uncompleted subordinates\n\t\t\tremaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n\t\t\tdeferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n\t\t\t// Update function for both resolve and progress values\n\t\t\tupdateFunc = function( i, contexts, values ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tcontexts[ i ] = this;\n\t\t\t\t\tvalues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( values === progressValues ) {\n\t\t\t\t\t\tdeferred.notifyWith( contexts, values );\n\t\t\t\t\t} else if ( !( --remaining ) ) {\n\t\t\t\t\t\tdeferred.resolveWith( contexts, values );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tprogressValues, progressContexts, resolveContexts;\n\n\t\t// add listeners to Deferred subordinates; treat others as resolved\n\t\tif ( length > 1 ) {\n\t\t\tprogressValues = new Array( length );\n\t\t\tprogressContexts = new Array( length );\n\t\t\tresolveContexts = new Array( length );\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n\t\t\t\t\tresolveValues[ i ].promise()\n\t\t\t\t\t\t.done( updateFunc( i, resolveContexts, resolveValues ) )\n\t\t\t\t\t\t.fail( deferred.reject )\n\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) );\n\t\t\t\t} else {\n\t\t\t\t\t--remaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if we're not waiting on anything, resolve the master\n\t\tif ( !remaining ) {\n\t\t\tdeferred.resolveWith( resolveContexts, resolveValues );\n\t\t}\n\n\t\treturn deferred.promise();\n\t}\n});\n\n\n// The deferred used on DOM ready\nvar readyList;\n\njQuery.fn.ready = function( fn ) {\n\t// Add the callback\n\tjQuery.ready.promise().done( fn );\n\n\treturn this;\n};\n\njQuery.extend({\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t// Trigger any bound ready events\n\t\tif ( jQuery.fn.trigger ) {\n\t\t\tjQuery( document ).trigger(\"ready\").off(\"ready\");\n\t\t}\n\t}\n});\n\n/**\n * The ready event handler and self cleanup method\n */\nfunction completed() {\n\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\twindow.removeEventListener( \"load\", completed, false );\n\tjQuery.ready();\n}\n\njQuery.ready.promise = function( obj ) {\n\tif ( !readyList ) {\n\n\t\treadyList = jQuery.Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the browser event has already occurred.\n\t\t// we once tried to use readyState \"interactive\" here, but it caused issues like the one\n\t\t// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\tsetTimeout( jQuery.ready );\n\n\t\t} else {\n\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed, false );\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n// Kick off the DOM ready check even if the user does not\njQuery.ready.promise();\n\n\n\n\n// Multifunctional method to get and set values of a collection\n// The value/s can optionally be executed if it's a function\nvar access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlen = elems.length,\n\t\tbulk = key == null;\n\n\t// Sets many values\n\tif ( jQuery.type( key ) === \"object\" ) {\n\t\tchainable = true;\n\t\tfor ( i in key ) {\n\t\t\tjQuery.access( elems, fn, i, key[i], true, emptyGet, raw );\n\t\t}\n\n\t// Sets one value\n\t} else if ( value !== undefined ) {\n\t\tchainable = true;\n\n\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\traw = true;\n\t\t}\n\n\t\tif ( bulk ) {\n\t\t\t// Bulk operations run against the entire set\n\t\t\tif ( raw ) {\n\t\t\t\tfn.call( elems, value );\n\t\t\t\tfn = null;\n\n\t\t\t// ...except when executing function values\n\t\t\t} else {\n\t\t\t\tbulk = fn;\n\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\tfn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn chainable ?\n\t\telems :\n\n\t\t// Gets\n\t\tbulk ?\n\t\t\tfn.call( elems ) :\n\t\t\tlen ? fn( elems[0], key ) : emptyGet;\n};\n\n\n/**\n * Determines whether an object can have data\n */\njQuery.acceptData = function( owner ) {\n\t// Accepts only:\n\t// - Node\n\t// - Node.ELEMENT_NODE\n\t// - Node.DOCUMENT_NODE\n\t// - Object\n\t// - Any\n\t/* jshint -W018 */\n\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n};\n\n\nfunction Data() {\n\t// Support: Android < 4,\n\t// Old WebKit does not have Object.preventExtensions/freeze method,\n\t// return new empty object instead with no [[set]] accessor\n\tObject.defineProperty( this.cache = {}, 0, {\n\t\tget: function() {\n\t\t\treturn {};\n\t\t}\n\t});\n\n\tthis.expando = jQuery.expando + Math.random();\n}\n\nData.uid = 1;\nData.accepts = jQuery.acceptData;\n\nData.prototype = {\n\tkey: function( owner ) {\n\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t// but we should not, see #8335.\n\t\t// Always return the key for a frozen object.\n\t\tif ( !Data.accepts( owner ) ) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar descriptor = {},\n\t\t\t// Check if the owner object already has a cache key\n\t\t\tunlock = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !unlock ) {\n\t\t\tunlock = Data.uid++;\n\n\t\t\t// Secure it in a non-enumerable, non-writable property\n\t\t\ttry {\n\t\t\t\tdescriptor[ this.expando ] = { value: unlock };\n\t\t\t\tObject.defineProperties( owner, descriptor );\n\n\t\t\t// Support: Android < 4\n\t\t\t// Fallback to a less secure definition\n\t\t\t} catch ( e ) {\n\t\t\t\tdescriptor[ this.expando ] = unlock;\n\t\t\t\tjQuery.extend( owner, descriptor );\n\t\t\t}\n\t\t}\n\n\t\t// Ensure the cache object\n\t\tif ( !this.cache[ unlock ] ) {\n\t\t\tthis.cache[ unlock ] = {};\n\t\t}\n\n\t\treturn unlock;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\t// There may be an unlock assigned to this node,\n\t\t\t// if there is no entry for this \"owner\", create one inline\n\t\t\t// and set the unlock as though an owner entry had always existed\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\t// Handle: [ owner, key, value ] args\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ data ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\t\t\t// Fresh assignments by object are shallow copied\n\t\t\tif ( jQuery.isEmptyObject( cache ) ) {\n\t\t\t\tjQuery.extend( this.cache[ unlock ], data );\n\t\t\t// Otherwise, copy the properties one-by-one to the cache object\n\t\t\t} else {\n\t\t\t\tfor ( prop in data ) {\n\t\t\t\t\tcache[ prop ] = data[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\t// Either a valid cache is found, or will be created.\n\t\t// New caches will be created and the unlock returned,\n\t\t// allowing direct access to the newly created\n\t\t// empty data object. A valid owner object must be provided.\n\t\tvar cache = this.cache[ this.key( owner ) ];\n\n\t\treturn key === undefined ?\n\t\t\tcache : cache[ key ];\n\t},\n\taccess: function( owner, key, value ) {\n\t\tvar stored;\n\t\t// In cases where either:\n\t\t//\n\t\t// 1. No key was specified\n\t\t// 2. A string key was specified, but no value provided\n\t\t//\n\t\t// Take the \"read\" path and allow the get method to determine\n\t\t// which value to return, respectively either:\n\t\t//\n\t\t// 1. The entire cache object\n\t\t// 2. The data stored at the key\n\t\t//\n\t\tif ( key === undefined ||\n\t\t\t\t((key && typeof key === \"string\") && value === undefined) ) {\n\n\t\t\tstored = this.get( owner, key );\n\n\t\t\treturn stored !== undefined ?\n\t\t\t\tstored : this.get( owner, jQuery.camelCase(key) );\n\t\t}\n\n\t\t// [*]When the key is not a string, or both a key and value\n\t\t// are specified, set or extend (existing objects) with either:\n\t\t//\n\t\t// 1. An object of properties\n\t\t// 2. A key and value\n\t\t//\n\t\tthis.set( owner, key, value );\n\n\t\t// Since the \"set\" path can have two possible entry points\n\t\t// return the expected data based on which path was taken[*]\n\t\treturn value !== undefined ? value : key;\n\t},\n\tremove: function( owner, key ) {\n\t\tvar i, name, camel,\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\tif ( key === undefined ) {\n\t\t\tthis.cache[ unlock ] = {};\n\n\t\t} else {\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( jQuery.isArray( key ) ) {\n\t\t\t\t// If \"name\" is an array of keys...\n\t\t\t\t// When data is initially created, via (\"key\", \"val\") signature,\n\t\t\t\t// keys will be converted to camelCase.\n\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n\t\t\t\t// both plain key and camelCase key. #12786\n\t\t\t\t// This will only penalize the array argument path.\n\t\t\t\tname = key.concat( key.map( jQuery.camelCase ) );\n\t\t\t} else {\n\t\t\t\tcamel = jQuery.camelCase( key );\n\t\t\t\t// Try the string as a key before any manipulation\n\t\t\t\tif ( key in cache ) {\n\t\t\t\t\tname = [ key, camel ];\n\t\t\t\t} else {\n\t\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\t\tname = camel;\n\t\t\t\t\tname = name in cache ?\n\t\t\t\t\t\t[ name ] : ( name.match( rnotwhite ) || [] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ti = name.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ name[ i ] ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\treturn !jQuery.isEmptyObject(\n\t\t\tthis.cache[ owner[ this.expando ] ] || {}\n\t\t);\n\t},\n\tdiscard: function( owner ) {\n\t\tif ( owner[ this.expando ] ) {\n\t\t\tdelete this.cache[ owner[ this.expando ] ];\n\t\t}\n\t}\n};\nvar data_priv = new Data();\n\nvar data_user = new Data();\n\n\n\n/*\n\tImplementation Summary\n\n\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n\t2. Improve the module's maintainability by reducing the storage\n\t\tpaths to a single mechanism.\n\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n*/\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction dataAttr( elem, key, data ) {\n\tvar name;\n\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tname = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tdata_user.set( elem, key, data );\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\treturn data;\n}\n\njQuery.extend({\n\thasData: function( elem ) {\n\t\treturn data_user.hasData( elem ) || data_priv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn data_user.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdata_user.remove( elem, name );\n\t},\n\n\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t// with direct calls to data_priv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn data_priv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdata_priv.remove( elem, name );\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar i, name, data,\n\t\t\telem = this[ 0 ],\n\t\t\tattrs = elem && elem.attributes;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = data_user.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !data_priv.get( elem, \"hasDataAttrs\" ) ) {\n\t\t\t\t\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tname = attrs[ i ].name;\n\n\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice(5) );\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdata_priv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tdata_user.set( this, key );\n\t\t\t});\n\t\t}\n\n\t\treturn access( this, function( value ) {\n\t\t\tvar data,\n\t\t\t\tcamelKey = jQuery.camelCase( key );\n\n\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\tif ( elem && value === undefined ) {\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key as-is\n\t\t\t\tdata = data_user.get( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key camelized\n\t\t\t\tdata = data_user.get( elem, camelKey );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( elem, camelKey, undefined );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the data...\n\t\t\tthis.each(function() {\n\t\t\t\t// First, attempt to store a copy or reference of any\n\t\t\t\t// data that might've been store with a camelCased key.\n\t\t\t\tvar data = data_user.get( this, camelKey );\n\n\t\t\t\t// For HTML5 data-* attribute interop, we have to\n\t\t\t\t// store property names with dashes in a camelCase form.\n\t\t\t\t// This might not apply to all properties...*\n\t\t\t\tdata_user.set( this, camelKey, value );\n\n\t\t\t\t// *... In the case of properties that might _actually_\n\t\t\t\t// have dashes, we need to also store a copy of that\n\t\t\t\t// unchanged property.\n\t\t\t\tif ( key.indexOf(\"-\") !== -1 && data !== undefined ) {\n\t\t\t\t\tdata_user.set( this, key, value );\n\t\t\t\t}\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tdata_user.remove( this, key );\n\t\t});\n\t}\n});\n\n\njQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = data_priv.get( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray( data ) ) {\n\t\t\t\t\tqueue = data_priv.access( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// not intended for public consumption - generates a queueHooks object, or returns the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn data_priv.get( elem, key ) || data_priv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tdata_priv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t})\n\t\t});\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile ( i-- ) {\n\t\t\ttmp = data_priv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n});\nvar pnum = (/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/).source;\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar isHidden = function( elem, el ) {\n\t\t// isHidden might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\t\treturn jQuery.css( elem, \"display\" ) === \"none\" || !jQuery.contains( elem.ownerDocument, elem );\n\t};\n\nvar rcheckableType = (/^(?:checkbox|radio)$/i);\n\n\n\n(function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\tdiv = fragment.appendChild( document.createElement( \"div\" ) );\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tdiv.innerHTML = \"\";\n\n\t// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3\n\t// old WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\t// Support: IE9-IE11+\n\tdiv.innerHTML = \"\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n})();\nvar strundefined = typeof undefined;\n\n\n\nsupport.focusinBubbles = \"onfocusin\" in window;\n\n\nvar\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)$/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.get( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !(events = elemData.events) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !(eventHandle = elemData.handle) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?\n\t\t\t\t\tjQuery.event.dispatch.apply( elem, arguments ) : undefined;\n\t\t\t};\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\tif ( !type ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !(handlers = events[ type ]) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar j, origCount, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.hasData( elem ) && data_priv.get( elem );\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[2] && new RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdelete elemData.handle;\n\t\t\tdata_priv.remove( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\tvar i, cur, tmp, bubbleType, ontype, handle, special,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split(\".\") : [];\n\n\t\tcur = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf(\":\") < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === (elem.ownerDocument || document) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {\n\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( data_priv.get( cur, \"events\" ) || {} )[ event.type ] && data_priv.get( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && handle.apply && jQuery.acceptData( cur ) ) {\n\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&\n\t\t\t\tjQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event );\n\n\t\tvar i, j, ret, matched, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\targs = slice.call( arguments ),\n\t\t\thandlers = ( data_priv.get( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( (event.result = ret) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar i, matches, sel, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG instance trees (#13180)\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== \"click\") ) {\n\n\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.disabled !== true || event.type !== \"click\" ) {\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matches[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, handlers: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop, copy,\n\t\t\ttype = event.type,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = this.fixHooks[ type ];\n\n\t\tif ( !fixHook ) {\n\t\t\tthis.fixHooks[ type ] = fixHook =\n\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n\t\t\t\t{};\n\t\t}\n\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = new jQuery.Event( originalEvent );\n\n\t\ti = copy.length;\n\t\twhile ( i-- ) {\n\t\t\tprop = copy[ i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Support: Cordova 2.5 (WebKit) (#13255)\n\t\t// All events should have a target; Cordova deviceready doesn't\n\t\tif ( !event.target ) {\n\t\t\tevent.target = document;\n\t\t}\n\n\t\t// Support: Safari 6.0+, Chrome < 28\n\t\t// Target should not be a text node (#504, #13143)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\treturn fixHook.filter ? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tfocus: {\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n\t\t\t\t\tthis.focus();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\t\tclick: {\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this.type === \"checkbox\" && this.click && jQuery.nodeName( this, \"input\" ) ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, don't fire native .click() on links\n\t\t\t_default: function( event ) {\n\t\t\t\treturn jQuery.nodeName( event.target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = function( elem, type, handle ) {\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle, false );\n\t}\n};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\t// Support: Android < 4.0\n\t\t\t\tsrc.defaultPrevented === undefined &&\n\t\t\t\tsrc.getPreventDefault && src.getPreventDefault() ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tif ( e && e.preventDefault ) {\n\t\t\te.preventDefault();\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// Support: Chrome 15+\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// Create \"bubbling\" focus and blur events\n// Support: Firefox, Chrome, Safari\nif ( !support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\tvar handler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = data_priv.access( doc, fix );\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t\tdata_priv.access( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = data_priv.access( doc, fix ) - 1;\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\tdata_priv.remove( doc, fix );\n\n\t\t\t\t} else {\n\t\t\t\t\tdata_priv.access( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event ) dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[0];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n});\n\n\nvar\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /^$|\\/(?:java|ecma)script/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*\\s*$/g,\n\n\t// We have to close these tags to support XHTML (#13200)\n\twrapMap = {\n\n\t\t// Support: IE 9\n\t\toption: [ 1, \"\" ],\n\n\t\tthead: [ 1, \"\", \"
\" ],\n\t\tcol: [ 2, \"\", \"
\" ],\n\t\ttr: [ 2, \"\", \"
\" ],\n\t\ttd: [ 3, \"\", \"
\" ],\n\n\t\t_default: [ 0, \"\", \"\" ]\n\t};\n\n// Support: IE 9\nwrapMap.optgroup = wrapMap.option;\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// Support: 1.x compatibility\n// Manipulating tables requires a tbody\nfunction manipulationTarget( elem, content ) {\n\treturn jQuery.nodeName( elem, \"table\" ) &&\n\t\tjQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ?\n\n\t\telem.getElementsByTagName(\"tbody\")[0] ||\n\t\t\telem.appendChild( elem.ownerDocument.createElement(\"tbody\") ) :\n\t\telem;\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\telem.type = (elem.getAttribute(\"type\") !== null) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\n\tif ( match ) {\n\t\telem.type = match[ 1 ];\n\t} else {\n\t\telem.removeAttribute(\"type\");\n\t}\n\n\treturn elem;\n}\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar i = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\tdata_priv.set(\n\t\t\telems[ i ], \"globalEval\", !refElements || data_priv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// 1. Copy private data: events, handlers, etc.\n\tif ( data_priv.hasData( src ) ) {\n\t\tpdataOld = data_priv.access( src );\n\t\tpdataCur = data_priv.set( dest, pdataOld );\n\t\tevents = pdataOld.events;\n\n\t\tif ( events ) {\n\t\t\tdelete pdataCur.handle;\n\t\t\tpdataCur.events = {};\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Copy user data\n\tif ( data_user.hasData( src ) ) {\n\t\tudataOld = data_user.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdata_user.set( dest, udataCur );\n\t}\n}\n\nfunction getAll( context, tag ) {\n\tvar ret = context.getElementsByTagName ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\tcontext.querySelectorAll ? context.querySelectorAll( tag || \"*\" ) :\n\t\t\t[];\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], ret ) :\n\t\tret;\n}\n\n// Support: IE >= 9\nfunction fixInput( src, dest ) {\n\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\tif ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\tdest.checked = src.checked;\n\n\t// Fails to return the selected option to the default selected state when cloning options\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar i, l, srcElements, destElements,\n\t\t\tclone = elem.cloneNode( true ),\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t// Support: IE >= 9\n\t\t// Fix Cloning issues\n\t\tif ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&\n\t\t\t\t!jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tbuildFragment: function( elems, context, scripts, selection ) {\n\t\tvar elem, tmp, tag, wrap, contains, j,\n\t\t\tfragment = context.createDocumentFragment(),\n\t\t\tnodes = [],\n\t\t\ti = 0,\n\t\t\tl = elems.length;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\t\t// Support: QtWebKit\n\t\t\t\t\t// jQuery.merge because push.apply(_, arraylike) throws\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement(\"div\") );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\t\ttmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, \"<$1>\" ) + wrap[ 2 ];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[ 0 ];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: QtWebKit\n\t\t\t\t\t// jQuery.merge because push.apply(_, arraylike) throws\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Remember the top-level container\n\t\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t\t// Fixes #12346\n\t\t\t\t\t// Support: Webkit, IE\n\t\t\t\t\ttmp.textContent = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove wrapper from fragment\n\t\tfragment.textContent = \"\";\n\n\t\ti = 0;\n\t\twhile ( (elem = nodes[ i++ ]) ) {\n\n\t\t\t// #4087 - If origin and destination elements are the same, and this is\n\t\t\t// that element, do not do anything\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn fragment;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, elem, events, type, key, j,\n\t\t\tspecial = jQuery.event.special,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[ i ]) !== undefined; i++ ) {\n\t\t\tif ( jQuery.acceptData( elem ) ) {\n\t\t\t\tkey = elem[ data_priv.expando ];\n\n\t\t\t\tif ( key && (data = data_priv.cache[ key ]) ) {\n\t\t\t\t\tevents = Object.keys( data.events || {} );\n\t\t\t\t\tif ( events.length ) {\n\t\t\t\t\t\tfor ( j = 0; (type = events[j]) !== undefined; j++ ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( data_priv.cache[ key ] ) {\n\t\t\t\t\t\t// Discard any remaining `private` data\n\t\t\t\t\t\tdelete data_priv.cache[ key ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Discard any remaining `user` data\n\t\t\tdelete data_user.cache[ elem[ data_user.expando ] ];\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().each(function() {\n\t\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\t\tthis.textContent = value;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t});\n\t},\n\n\tafter: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t});\n\t},\n\n\tremove: function( selector, keepData /* Internal Use Only */ ) {\n\t\tvar elem,\n\t\t\telems = selector ? jQuery.filter( selector, this ) : this,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem ) );\n\t\t\t}\n\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\t\tsetGlobalEval( getAll( elem, \"script\" ) );\n\t\t\t\t}\n\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t// Prevent memory leaks\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t// Remove any remaining nodes\n\t\t\t\telem.textContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map(function() {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined && elem.nodeType === 1 ) {\n\t\t\t\treturn elem.innerHTML;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch( e ) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar arg = arguments[ 0 ];\n\n\t\t// Make the changes, replacing each context element with the new content\n\t\tthis.domManip( arguments, function( elem ) {\n\t\t\targ = this.parentNode;\n\n\t\t\tjQuery.cleanData( getAll( this ) );\n\n\t\t\tif ( arg ) {\n\t\t\t\targ.replaceChild( elem, this );\n\t\t\t}\n\t\t});\n\n\t\t// Force removal if there was no new content (e.g., from empty arguments)\n\t\treturn arg && (arg.length || arg.nodeType) ? this : this.remove();\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, callback ) {\n\n\t\t// Flatten any nested arrays\n\t\targs = concat.apply( [], args );\n\n\t\tvar fragment, first, scripts, hasScripts, node, doc,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tset = this,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[ 0 ],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction ||\n\t\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\t\treturn this.each(function( index ) {\n\t\t\t\tvar self = set.eq( index );\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t\t}\n\t\t\t\tself.domManip( args, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );\n\t\t\tfirst = fragment.firstChild;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfragment = first;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\t\thasScripts = scripts.length;\n\n\t\t\t\t// Use the original fragment for the last item instead of the first because it can end up\n\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tnode = fragment;\n\n\t\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\t\t\t// Support: QtWebKit\n\t\t\t\t\t\t\t// jQuery.merge because push.apply(_, arraylike) throws\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call( this[ i ], node, i );\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!data_priv.access( node, \"globalEval\" ) && jQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\t\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\t\tif ( jQuery._evalUrl ) {\n\t\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.globalEval( node.textContent.replace( rcleanScript, \"\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1,\n\t\t\ti = 0;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone( true );\n\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t// Support: QtWebKit\n\t\t\t// .get() because push.apply(_, arraylike) throws\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\n\nvar iframe,\n\telemdisplay = {};\n\n/**\n * Retrieve the actual display of a element\n * @param {String} name nodeName of the element\n * @param {Object} doc Document object\n */\n// Called only from within defaultDisplay\nfunction actualDisplay( name, doc ) {\n\tvar elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n\n\t\t// getDefaultComputedStyle might be reliably used only on attached element\n\t\tdisplay = window.getDefaultComputedStyle ?\n\n\t\t\t// Use of this method is a temporary fix (more like optmization) until something better comes along,\n\t\t\t// since it was removed from specification and supported only in FF\n\t\t\twindow.getDefaultComputedStyle( elem[ 0 ] ).display : jQuery.css( elem[ 0 ], \"display\" );\n\n\t// We don't have any data stored on the element,\n\t// so use \"detach\" method as fast way to get rid of the element\n\telem.detach();\n\n\treturn display;\n}\n\n/**\n * Try to determine the default display value of an element\n * @param {String} nodeName\n */\nfunction defaultDisplay( nodeName ) {\n\tvar doc = document,\n\t\tdisplay = elemdisplay[ nodeName ];\n\n\tif ( !display ) {\n\t\tdisplay = actualDisplay( nodeName, doc );\n\n\t\t// If the simple way fails, read from inside an iframe\n\t\tif ( display === \"none\" || !display ) {\n\n\t\t\t// Use the already-created iframe if possible\n\t\t\tiframe = (iframe || jQuery( \"'},d(function(){d(\".\"+bb+':not([data-auto=\"false\"])').fotorama()})}(window,document,location,\"undefined\"!=typeof jQuery&&jQuery);\ndefine(\"fotorama\", [\"jquery\"], function(){});\n\n","/**\n * State-based routing for AngularJS\n * @version v0.2.13\n * @link http://angular-ui.github.com/\n * @license MIT License, http://www.opensource.org/licenses/MIT\n */\n\n/* commonjs package manager support (eg componentjs) */\nif (typeof module !== \"undefined\" && typeof exports !== \"undefined\" && module.exports === exports){\n module.exports = 'ui.router';\n}\n\n(function (window, angular, undefined) {\n/*jshint globalstrict:true*/\n/*global angular:false*/\n'use strict';\n\nvar isDefined = angular.isDefined,\n isFunction = angular.isFunction,\n isString = angular.isString,\n isObject = angular.isObject,\n isArray = angular.isArray,\n forEach = angular.forEach,\n extend = angular.extend,\n copy = angular.copy;\n\nfunction inherit(parent, extra) {\n return extend(new (extend(function() {}, { prototype: parent }))(), extra);\n}\n\nfunction merge(dst) {\n forEach(arguments, function(obj) {\n if (obj !== dst) {\n forEach(obj, function(value, key) {\n if (!dst.hasOwnProperty(key)) dst[key] = value;\n });\n }\n });\n return dst;\n}\n\n/**\n * Finds the common ancestor path between two states.\n *\n * @param {Object} first The first state.\n * @param {Object} second The second state.\n * @return {Array} Returns an array of state names in descending order, not including the root.\n */\nfunction ancestors(first, second) {\n var path = [];\n\n for (var n in first.path) {\n if (first.path[n] !== second.path[n]) break;\n path.push(first.path[n]);\n }\n return path;\n}\n\n/**\n * IE8-safe wrapper for `Object.keys()`.\n *\n * @param {Object} object A JavaScript object.\n * @return {Array} Returns the keys of the object as an array.\n */\nfunction objectKeys(object) {\n if (Object.keys) {\n return Object.keys(object);\n }\n var result = [];\n\n angular.forEach(object, function(val, key) {\n result.push(key);\n });\n return result;\n}\n\n/**\n * IE8-safe wrapper for `Array.prototype.indexOf()`.\n *\n * @param {Array} array A JavaScript array.\n * @param {*} value A value to search the array for.\n * @return {Number} Returns the array index value of `value`, or `-1` if not present.\n */\nfunction indexOf(array, value) {\n if (Array.prototype.indexOf) {\n return array.indexOf(value, Number(arguments[2]) || 0);\n }\n var len = array.length >>> 0, from = Number(arguments[2]) || 0;\n from = (from < 0) ? Math.ceil(from) : Math.floor(from);\n\n if (from < 0) from += len;\n\n for (; from < len; from++) {\n if (from in array && array[from] === value) return from;\n }\n return -1;\n}\n\n/**\n * Merges a set of parameters with all parameters inherited between the common parents of the\n * current state and a given destination state.\n *\n * @param {Object} currentParams The value of the current state parameters ($stateParams).\n * @param {Object} newParams The set of parameters which will be composited with inherited params.\n * @param {Object} $current Internal definition of object representing the current state.\n * @param {Object} $to Internal definition of object representing state to transition to.\n */\nfunction inheritParams(currentParams, newParams, $current, $to) {\n var parents = ancestors($current, $to), parentParams, inherited = {}, inheritList = [];\n\n for (var i in parents) {\n if (!parents[i].params) continue;\n parentParams = objectKeys(parents[i].params);\n if (!parentParams.length) continue;\n\n for (var j in parentParams) {\n if (indexOf(inheritList, parentParams[j]) >= 0) continue;\n inheritList.push(parentParams[j]);\n inherited[parentParams[j]] = currentParams[parentParams[j]];\n }\n }\n return extend({}, inherited, newParams);\n}\n\n/**\n * Performs a non-strict comparison of the subset of two objects, defined by a list of keys.\n *\n * @param {Object} a The first object.\n * @param {Object} b The second object.\n * @param {Array} keys The list of keys within each object to compare. If the list is empty or not specified,\n * it defaults to the list of keys in `a`.\n * @return {Boolean} Returns `true` if the keys match, otherwise `false`.\n */\nfunction equalForKeys(a, b, keys) {\n if (!keys) {\n keys = [];\n for (var n in a) keys.push(n); // Used instead of Object.keys() for IE8 compatibility\n }\n\n for (var i=0; i\n * \n * \n * \n * \n * \n * \n * \n * \n * \n * \n * \n * \n */\nangular.module('ui.router', ['ui.router.state']);\n\nangular.module('ui.router.compat', ['ui.router']);\n\n/**\n * @ngdoc object\n * @name ui.router.util.$resolve\n *\n * @requires $q\n * @requires $injector\n *\n * @description\n * Manages resolution of (acyclic) graphs of promises.\n */\n$Resolve.$inject = ['$q', '$injector'];\nfunction $Resolve( $q, $injector) {\n \n var VISIT_IN_PROGRESS = 1,\n VISIT_DONE = 2,\n NOTHING = {},\n NO_DEPENDENCIES = [],\n NO_LOCALS = NOTHING,\n NO_PARENT = extend($q.when(NOTHING), { $$promises: NOTHING, $$values: NOTHING });\n \n\n /**\n * @ngdoc function\n * @name ui.router.util.$resolve#study\n * @methodOf ui.router.util.$resolve\n *\n * @description\n * Studies a set of invocables that are likely to be used multiple times.\n *
\n   * $resolve.study(invocables)(locals, parent, self)\n   * 
\n * is equivalent to\n *
\n   * $resolve.resolve(invocables, locals, parent, self)\n   * 
\n * but the former is more efficient (in fact `resolve` just calls `study` \n * internally).\n *\n * @param {object} invocables Invocable objects\n * @return {function} a function to pass in locals, parent and self\n */\n this.study = function (invocables) {\n if (!isObject(invocables)) throw new Error(\"'invocables' must be an object\");\n var invocableKeys = objectKeys(invocables || {});\n \n // Perform a topological sort of invocables to build an ordered plan\n var plan = [], cycle = [], visited = {};\n function visit(value, key) {\n if (visited[key] === VISIT_DONE) return;\n \n cycle.push(key);\n if (visited[key] === VISIT_IN_PROGRESS) {\n cycle.splice(0, indexOf(cycle, key));\n throw new Error(\"Cyclic dependency: \" + cycle.join(\" -> \"));\n }\n visited[key] = VISIT_IN_PROGRESS;\n \n if (isString(value)) {\n plan.push(key, [ function() { return $injector.get(value); }], NO_DEPENDENCIES);\n } else {\n var params = $injector.annotate(value);\n forEach(params, function (param) {\n if (param !== key && invocables.hasOwnProperty(param)) visit(invocables[param], param);\n });\n plan.push(key, value, params);\n }\n \n cycle.pop();\n visited[key] = VISIT_DONE;\n }\n forEach(invocables, visit);\n invocables = cycle = visited = null; // plan is all that's required\n \n function isResolve(value) {\n return isObject(value) && value.then && value.$$promises;\n }\n \n return function (locals, parent, self) {\n if (isResolve(locals) && self === undefined) {\n self = parent; parent = locals; locals = null;\n }\n if (!locals) locals = NO_LOCALS;\n else if (!isObject(locals)) {\n throw new Error(\"'locals' must be an object\");\n } \n if (!parent) parent = NO_PARENT;\n else if (!isResolve(parent)) {\n throw new Error(\"'parent' must be a promise returned by $resolve.resolve()\");\n }\n \n // To complete the overall resolution, we have to wait for the parent\n // promise and for the promise for each invokable in our plan.\n var resolution = $q.defer(),\n result = resolution.promise,\n promises = result.$$promises = {},\n values = extend({}, locals),\n wait = 1 + plan.length/3,\n merged = false;\n \n function done() {\n // Merge parent values we haven't got yet and publish our own $$values\n if (!--wait) {\n if (!merged) merge(values, parent.$$values); \n result.$$values = values;\n result.$$promises = result.$$promises || true; // keep for isResolve()\n delete result.$$inheritedValues;\n resolution.resolve(values);\n }\n }\n \n function fail(reason) {\n result.$$failure = reason;\n resolution.reject(reason);\n }\n\n // Short-circuit if parent has already failed\n if (isDefined(parent.$$failure)) {\n fail(parent.$$failure);\n return result;\n }\n \n if (parent.$$inheritedValues) {\n merge(values, omit(parent.$$inheritedValues, invocableKeys));\n }\n\n // Merge parent values if the parent has already resolved, or merge\n // parent promises and wait if the parent resolve is still in progress.\n extend(promises, parent.$$promises);\n if (parent.$$values) {\n merged = merge(values, omit(parent.$$values, invocableKeys));\n result.$$inheritedValues = omit(parent.$$values, invocableKeys);\n done();\n } else {\n if (parent.$$inheritedValues) {\n result.$$inheritedValues = omit(parent.$$inheritedValues, invocableKeys);\n } \n parent.then(done, fail);\n }\n \n // Process each invocable in the plan, but ignore any where a local of the same name exists.\n for (var i=0, ii=plan.length; i} The template html as a string, or a promise \n * for that string.\n */\n this.fromUrl = function (url, params) {\n if (isFunction(url)) url = url(params);\n if (url == null) return null;\n else return $http\n .get(url, { cache: $templateCache, headers: { Accept: 'text/html' }})\n .then(function(response) { return response.data; });\n };\n\n /**\n * @ngdoc function\n * @name ui.router.util.$templateFactory#fromProvider\n * @methodOf ui.router.util.$templateFactory\n *\n * @description\n * Creates a template by invoking an injectable provider function.\n *\n * @param {Function} provider Function to invoke via `$injector.invoke`\n * @param {Object} params Parameters for the template.\n * @param {Object} locals Locals to pass to `invoke`. Defaults to \n * `{ params: params }`.\n * @return {string|Promise.} The template html as a string, or a promise \n * for that string.\n */\n this.fromProvider = function (provider, params, locals) {\n return $injector.invoke(provider, null, locals || { params: params });\n };\n}\n\nangular.module('ui.router.util').service('$templateFactory', $TemplateFactory);\n\nvar $$UMFP; // reference to $UrlMatcherFactoryProvider\n\n/**\n * @ngdoc object\n * @name ui.router.util.type:UrlMatcher\n *\n * @description\n * Matches URLs against patterns and extracts named parameters from the path or the search\n * part of the URL. A URL pattern consists of a path pattern, optionally followed by '?' and a list\n * of search parameters. Multiple search parameter names are separated by '&'. Search parameters\n * do not influence whether or not a URL is matched, but their values are passed through into\n * the matched parameters returned by {@link ui.router.util.type:UrlMatcher#methods_exec exec}.\n * \n * Path parameter placeholders can be specified using simple colon/catch-all syntax or curly brace\n * syntax, which optionally allows a regular expression for the parameter to be specified:\n *\n * * `':'` name - colon placeholder\n * * `'*'` name - catch-all placeholder\n * * `'{' name '}'` - curly placeholder\n * * `'{' name ':' regexp|type '}'` - curly placeholder with regexp or type name. Should the\n * regexp itself contain curly braces, they must be in matched pairs or escaped with a backslash.\n *\n * Parameter names may contain only word characters (latin letters, digits, and underscore) and\n * must be unique within the pattern (across both path and search parameters). For colon \n * placeholders or curly placeholders without an explicit regexp, a path parameter matches any\n * number of characters other than '/'. For catch-all placeholders the path parameter matches\n * any number of characters.\n * \n * Examples:\n * \n * * `'/hello/'` - Matches only if the path is exactly '/hello/'. There is no special treatment for\n * trailing slashes, and patterns have to match the entire path, not just a prefix.\n * * `'/user/:id'` - Matches '/user/bob' or '/user/1234!!!' or even '/user/' but not '/user' or\n * '/user/bob/details'. The second path segment will be captured as the parameter 'id'.\n * * `'/user/{id}'` - Same as the previous example, but using curly brace syntax.\n * * `'/user/{id:[^/]*}'` - Same as the previous example.\n * * `'/user/{id:[0-9a-fA-F]{1,8}}'` - Similar to the previous example, but only matches if the id\n * parameter consists of 1 to 8 hex digits.\n * * `'/files/{path:.*}'` - Matches any URL starting with '/files/' and captures the rest of the\n * path into the parameter 'path'.\n * * `'/files/*path'` - ditto.\n * * `'/calendar/{start:date}'` - Matches \"/calendar/2014-11-12\" (because the pattern defined\n * in the built-in `date` Type matches `2014-11-12`) and provides a Date object in $stateParams.start\n *\n * @param {string} pattern The pattern to compile into a matcher.\n * @param {Object} config A configuration object hash:\n * @param {Object=} parentMatcher Used to concatenate the pattern/config onto\n * an existing UrlMatcher\n *\n * * `caseInsensitive` - `true` if URL matching should be case insensitive, otherwise `false`, the default value (for backward compatibility) is `false`.\n * * `strict` - `false` if matching against a URL with a trailing slash should be treated as equivalent to a URL without a trailing slash, the default value is `true`.\n *\n * @property {string} prefix A static prefix of this pattern. The matcher guarantees that any\n * URL matching this matcher (i.e. any string for which {@link ui.router.util.type:UrlMatcher#methods_exec exec()} returns\n * non-null) will start with this prefix.\n *\n * @property {string} source The pattern that was passed into the constructor\n *\n * @property {string} sourcePath The path portion of the source property\n *\n * @property {string} sourceSearch The search portion of the source property\n *\n * @property {string} regex The constructed regex that will be used to match against the url when \n * it is time to determine which url will match.\n *\n * @returns {Object} New `UrlMatcher` object\n */\nfunction UrlMatcher(pattern, config, parentMatcher) {\n config = extend({ params: {} }, isObject(config) ? config : {});\n\n // Find all placeholders and create a compiled pattern, using either classic or curly syntax:\n // '*' name\n // ':' name\n // '{' name '}'\n // '{' name ':' regexp '}'\n // The regular expression is somewhat complicated due to the need to allow curly braces\n // inside the regular expression. The placeholder regexp breaks down as follows:\n // ([:*])([\\w\\[\\]]+) - classic placeholder ($1 / $2) (search version has - for snake-case)\n // \\{([\\w\\[\\]]+)(?:\\:( ... ))?\\} - curly brace placeholder ($3) with optional regexp/type ... ($4) (search version has - for snake-case\n // (?: ... | ... | ... )+ - the regexp consists of any number of atoms, an atom being either\n // [^{}\\\\]+ - anything other than curly braces or backslash\n // \\\\. - a backslash escape\n // \\{(?:[^{}\\\\]+|\\\\.)*\\} - a matched set of curly braces containing other atoms\n var placeholder = /([:*])([\\w\\[\\]]+)|\\{([\\w\\[\\]]+)(?:\\:((?:[^{}\\\\]+|\\\\.|\\{(?:[^{}\\\\]+|\\\\.)*\\})+))?\\}/g,\n searchPlaceholder = /([:]?)([\\w\\[\\]-]+)|\\{([\\w\\[\\]-]+)(?:\\:((?:[^{}\\\\]+|\\\\.|\\{(?:[^{}\\\\]+|\\\\.)*\\})+))?\\}/g,\n compiled = '^', last = 0, m,\n segments = this.segments = [],\n parentParams = parentMatcher ? parentMatcher.params : {},\n params = this.params = parentMatcher ? parentMatcher.params.$$new() : new $$UMFP.ParamSet(),\n paramNames = [];\n\n function addParameter(id, type, config, location) {\n paramNames.push(id);\n if (parentParams[id]) return parentParams[id];\n if (!/^\\w+(-+\\w+)*(?:\\[\\])?$/.test(id)) throw new Error(\"Invalid parameter name '\" + id + \"' in pattern '\" + pattern + \"'\");\n if (params[id]) throw new Error(\"Duplicate parameter name '\" + id + \"' in pattern '\" + pattern + \"'\");\n params[id] = new $$UMFP.Param(id, type, config, location);\n return params[id];\n }\n\n function quoteRegExp(string, pattern, squash) {\n var surroundPattern = ['',''], result = string.replace(/[\\\\\\[\\]\\^$*+?.()|{}]/g, \"\\\\$&\");\n if (!pattern) return result;\n switch(squash) {\n case false: surroundPattern = ['(', ')']; break;\n case true: surroundPattern = ['?(', ')?']; break;\n default: surroundPattern = ['(' + squash + \"|\", ')?']; break;\n }\n return result + surroundPattern[0] + pattern + surroundPattern[1];\n }\n\n this.source = pattern;\n\n // Split into static segments separated by path parameter placeholders.\n // The number of segments is always 1 more than the number of parameters.\n function matchDetails(m, isSearch) {\n var id, regexp, segment, type, cfg, arrayMode;\n id = m[2] || m[3]; // IE[78] returns '' for unmatched groups instead of null\n cfg = config.params[id];\n segment = pattern.substring(last, m.index);\n regexp = isSearch ? m[4] : m[4] || (m[1] == '*' ? '.*' : null);\n type = $$UMFP.type(regexp || \"string\") || inherit($$UMFP.type(\"string\"), { pattern: new RegExp(regexp) });\n return {\n id: id, regexp: regexp, segment: segment, type: type, cfg: cfg\n };\n }\n\n var p, param, segment;\n while ((m = placeholder.exec(pattern))) {\n p = matchDetails(m, false);\n if (p.segment.indexOf('?') >= 0) break; // we're into the search part\n\n param = addParameter(p.id, p.type, p.cfg, \"path\");\n compiled += quoteRegExp(p.segment, param.type.pattern.source, param.squash);\n segments.push(p.segment);\n last = placeholder.lastIndex;\n }\n segment = pattern.substring(last);\n\n // Find any search parameter names and remove them from the last segment\n var i = segment.indexOf('?');\n\n if (i >= 0) {\n var search = this.sourceSearch = segment.substring(i);\n segment = segment.substring(0, i);\n this.sourcePath = pattern.substring(0, last + i);\n\n if (search.length > 0) {\n last = 0;\n while ((m = searchPlaceholder.exec(search))) {\n p = matchDetails(m, true);\n param = addParameter(p.id, p.type, p.cfg, \"search\");\n last = placeholder.lastIndex;\n // check if ?&\n }\n }\n } else {\n this.sourcePath = pattern;\n this.sourceSearch = '';\n }\n\n compiled += quoteRegExp(segment) + (config.strict === false ? '\\/?' : '') + '$';\n segments.push(segment);\n\n this.regexp = new RegExp(compiled, config.caseInsensitive ? 'i' : undefined);\n this.prefix = segments[0];\n this.$$paramNames = paramNames;\n}\n\n/**\n * @ngdoc function\n * @name ui.router.util.type:UrlMatcher#concat\n * @methodOf ui.router.util.type:UrlMatcher\n *\n * @description\n * Returns a new matcher for a pattern constructed by appending the path part and adding the\n * search parameters of the specified pattern to this pattern. The current pattern is not\n * modified. This can be understood as creating a pattern for URLs that are relative to (or\n * suffixes of) the current pattern.\n *\n * @example\n * The following two matchers are equivalent:\n *
\n * new UrlMatcher('/user/{id}?q').concat('/details?date');\n * new UrlMatcher('/user/{id}/details?q&date');\n * 
\n *\n * @param {string} pattern The pattern to append.\n * @param {Object} config An object hash of the configuration for the matcher.\n * @returns {UrlMatcher} A matcher for the concatenated pattern.\n */\nUrlMatcher.prototype.concat = function (pattern, config) {\n // Because order of search parameters is irrelevant, we can add our own search\n // parameters to the end of the new pattern. Parse the new pattern by itself\n // and then join the bits together, but it's much easier to do this on a string level.\n var defaultConfig = {\n caseInsensitive: $$UMFP.caseInsensitive(),\n strict: $$UMFP.strictMode(),\n squash: $$UMFP.defaultSquashPolicy()\n };\n return new UrlMatcher(this.sourcePath + pattern + this.sourceSearch, extend(defaultConfig, config), this);\n};\n\nUrlMatcher.prototype.toString = function () {\n return this.source;\n};\n\n/**\n * @ngdoc function\n * @name ui.router.util.type:UrlMatcher#exec\n * @methodOf ui.router.util.type:UrlMatcher\n *\n * @description\n * Tests the specified path against this matcher, and returns an object containing the captured\n * parameter values, or null if the path does not match. The returned object contains the values\n * of any search parameters that are mentioned in the pattern, but their value may be null if\n * they are not present in `searchParams`. This means that search parameters are always treated\n * as optional.\n *\n * @example\n *
\n * new UrlMatcher('/user/{id}?q&r').exec('/user/bob', {\n *   x: '1', q: 'hello'\n * });\n * // returns { id: 'bob', q: 'hello', r: null }\n * 
\n *\n * @param {string} path The URL path to match, e.g. `$location.path()`.\n * @param {Object} searchParams URL search parameters, e.g. `$location.search()`.\n * @returns {Object} The captured parameter values.\n */\nUrlMatcher.prototype.exec = function (path, searchParams) {\n var m = this.regexp.exec(path);\n if (!m) return null;\n searchParams = searchParams || {};\n\n var paramNames = this.parameters(), nTotal = paramNames.length,\n nPath = this.segments.length - 1,\n values = {}, i, j, cfg, paramName;\n\n if (nPath !== m.length - 1) throw new Error(\"Unbalanced capture group in route '\" + this.source + \"'\");\n\n function decodePathArray(string) {\n function reverseString(str) { return str.split(\"\").reverse().join(\"\"); }\n function unquoteDashes(str) { return str.replace(/\\\\-/, \"-\"); }\n\n var split = reverseString(string).split(/-(?!\\\\)/);\n var allReversed = map(split, reverseString);\n return map(allReversed, unquoteDashes).reverse();\n }\n\n for (i = 0; i < nPath; i++) {\n paramName = paramNames[i];\n var param = this.params[paramName];\n var paramVal = m[i+1];\n // if the param value matches a pre-replace pair, replace the value before decoding.\n for (j = 0; j < param.replace; j++) {\n if (param.replace[j].from === paramVal) paramVal = param.replace[j].to;\n }\n if (paramVal && param.array === true) paramVal = decodePathArray(paramVal);\n values[paramName] = param.value(paramVal);\n }\n for (/**/; i < nTotal; i++) {\n paramName = paramNames[i];\n values[paramName] = this.params[paramName].value(searchParams[paramName]);\n }\n\n return values;\n};\n\n/**\n * @ngdoc function\n * @name ui.router.util.type:UrlMatcher#parameters\n * @methodOf ui.router.util.type:UrlMatcher\n *\n * @description\n * Returns the names of all path and search parameters of this pattern in an unspecified order.\n * \n * @returns {Array.} An array of parameter names. Must be treated as read-only. If the\n * pattern has no parameters, an empty array is returned.\n */\nUrlMatcher.prototype.parameters = function (param) {\n if (!isDefined(param)) return this.$$paramNames;\n return this.params[param] || null;\n};\n\n/**\n * @ngdoc function\n * @name ui.router.util.type:UrlMatcher#validate\n * @methodOf ui.router.util.type:UrlMatcher\n *\n * @description\n * Checks an object hash of parameters to validate their correctness according to the parameter\n * types of this `UrlMatcher`.\n *\n * @param {Object} params The object hash of parameters to validate.\n * @returns {boolean} Returns `true` if `params` validates, otherwise `false`.\n */\nUrlMatcher.prototype.validates = function (params) {\n return this.params.$$validates(params);\n};\n\n/**\n * @ngdoc function\n * @name ui.router.util.type:UrlMatcher#format\n * @methodOf ui.router.util.type:UrlMatcher\n *\n * @description\n * Creates a URL that matches this pattern by substituting the specified values\n * for the path and search parameters. Null values for path parameters are\n * treated as empty strings.\n *\n * @example\n *
\n * new UrlMatcher('/user/{id}?q').format({ id:'bob', q:'yes' });\n * // returns '/user/bob?q=yes'\n * 
\n *\n * @param {Object} values the values to substitute for the parameters in this pattern.\n * @returns {string} the formatted URL (path and optionally search part).\n */\nUrlMatcher.prototype.format = function (values) {\n values = values || {};\n var segments = this.segments, params = this.parameters(), paramset = this.params;\n if (!this.validates(values)) return null;\n\n var i, search = false, nPath = segments.length - 1, nTotal = params.length, result = segments[0];\n\n function encodeDashes(str) { // Replace dashes with encoded \"\\-\"\n return encodeURIComponent(str).replace(/-/g, function(c) { return '%5C%' + c.charCodeAt(0).toString(16).toUpperCase(); });\n }\n\n for (i = 0; i < nTotal; i++) {\n var isPathParam = i < nPath;\n var name = params[i], param = paramset[name], value = param.value(values[name]);\n var isDefaultValue = param.isOptional && param.type.equals(param.value(), value);\n var squash = isDefaultValue ? param.squash : false;\n var encoded = param.type.encode(value);\n\n if (isPathParam) {\n var nextSegment = segments[i + 1];\n if (squash === false) {\n if (encoded != null) {\n if (isArray(encoded)) {\n result += map(encoded, encodeDashes).join(\"-\");\n } else {\n result += encodeURIComponent(encoded);\n }\n }\n result += nextSegment;\n } else if (squash === true) {\n var capture = result.match(/\\/$/) ? /\\/?(.*)/ : /(.*)/;\n result += nextSegment.match(capture)[1];\n } else if (isString(squash)) {\n result += squash + nextSegment;\n }\n } else {\n if (encoded == null || (isDefaultValue && squash !== false)) continue;\n if (!isArray(encoded)) encoded = [ encoded ];\n encoded = map(encoded, encodeURIComponent).join('&' + name + '=');\n result += (search ? '&' : '?') + (name + '=' + encoded);\n search = true;\n }\n }\n\n return result;\n};\n\n/**\n * @ngdoc object\n * @name ui.router.util.type:Type\n *\n * @description\n * Implements an interface to define custom parameter types that can be decoded from and encoded to\n * string parameters matched in a URL. Used by {@link ui.router.util.type:UrlMatcher `UrlMatcher`}\n * objects when matching or formatting URLs, or comparing or validating parameter values.\n *\n * See {@link ui.router.util.$urlMatcherFactory#methods_type `$urlMatcherFactory#type()`} for more\n * information on registering custom types.\n *\n * @param {Object} config A configuration object which contains the custom type definition. The object's\n * properties will override the default methods and/or pattern in `Type`'s public interface.\n * @example\n *
\n * {\n *   decode: function(val) { return parseInt(val, 10); },\n *   encode: function(val) { return val && val.toString(); },\n *   equals: function(a, b) { return this.is(a) && a === b; },\n *   is: function(val) { return angular.isNumber(val) isFinite(val) && val % 1 === 0; },\n *   pattern: /\\d+/\n * }\n * 
\n *\n * @property {RegExp} pattern The regular expression pattern used to match values of this type when\n * coming from a substring of a URL.\n *\n * @returns {Object} Returns a new `Type` object.\n */\nfunction Type(config) {\n extend(this, config);\n}\n\n/**\n * @ngdoc function\n * @name ui.router.util.type:Type#is\n * @methodOf ui.router.util.type:Type\n *\n * @description\n * Detects whether a value is of a particular type. Accepts a native (decoded) value\n * and determines whether it matches the current `Type` object.\n *\n * @param {*} val The value to check.\n * @param {string} key Optional. If the type check is happening in the context of a specific\n * {@link ui.router.util.type:UrlMatcher `UrlMatcher`} object, this is the name of the\n * parameter in which `val` is stored. Can be used for meta-programming of `Type` objects.\n * @returns {Boolean} Returns `true` if the value matches the type, otherwise `false`.\n */\nType.prototype.is = function(val, key) {\n return true;\n};\n\n/**\n * @ngdoc function\n * @name ui.router.util.type:Type#encode\n * @methodOf ui.router.util.type:Type\n *\n * @description\n * Encodes a custom/native type value to a string that can be embedded in a URL. Note that the\n * return value does *not* need to be URL-safe (i.e. passed through `encodeURIComponent()`), it\n * only needs to be a representation of `val` that has been coerced to a string.\n *\n * @param {*} val The value to encode.\n * @param {string} key The name of the parameter in which `val` is stored. Can be used for\n * meta-programming of `Type` objects.\n * @returns {string} Returns a string representation of `val` that can be encoded in a URL.\n */\nType.prototype.encode = function(val, key) {\n return val;\n};\n\n/**\n * @ngdoc function\n * @name ui.router.util.type:Type#decode\n * @methodOf ui.router.util.type:Type\n *\n * @description\n * Converts a parameter value (from URL string or transition param) to a custom/native value.\n *\n * @param {string} val The URL parameter value to decode.\n * @param {string} key The name of the parameter in which `val` is stored. Can be used for\n * meta-programming of `Type` objects.\n * @returns {*} Returns a custom representation of the URL parameter value.\n */\nType.prototype.decode = function(val, key) {\n return val;\n};\n\n/**\n * @ngdoc function\n * @name ui.router.util.type:Type#equals\n * @methodOf ui.router.util.type:Type\n *\n * @description\n * Determines whether two decoded values are equivalent.\n *\n * @param {*} a A value to compare against.\n * @param {*} b A value to compare against.\n * @returns {Boolean} Returns `true` if the values are equivalent/equal, otherwise `false`.\n */\nType.prototype.equals = function(a, b) {\n return a == b;\n};\n\nType.prototype.$subPattern = function() {\n var sub = this.pattern.toString();\n return sub.substr(1, sub.length - 2);\n};\n\nType.prototype.pattern = /.*/;\n\nType.prototype.toString = function() { return \"{Type:\" + this.name + \"}\"; };\n\n/*\n * Wraps an existing custom Type as an array of Type, depending on 'mode'.\n * e.g.:\n * - urlmatcher pattern \"/path?{queryParam[]:int}\"\n * - url: \"/path?queryParam=1&queryParam=2\n * - $stateParams.queryParam will be [1, 2]\n * if `mode` is \"auto\", then\n * - url: \"/path?queryParam=1 will create $stateParams.queryParam: 1\n * - url: \"/path?queryParam=1&queryParam=2 will create $stateParams.queryParam: [1, 2]\n */\nType.prototype.$asArray = function(mode, isSearch) {\n if (!mode) return this;\n if (mode === \"auto\" && !isSearch) throw new Error(\"'auto' array mode is for query parameters only\");\n return new ArrayType(this, mode);\n\n function ArrayType(type, mode) {\n function bindTo(type, callbackName) {\n return function() {\n return type[callbackName].apply(type, arguments);\n };\n }\n\n // Wrap non-array value as array\n function arrayWrap(val) { return isArray(val) ? val : (isDefined(val) ? [ val ] : []); }\n // Unwrap array value for \"auto\" mode. Return undefined for empty array.\n function arrayUnwrap(val) {\n switch(val.length) {\n case 0: return undefined;\n case 1: return mode === \"auto\" ? val[0] : val;\n default: return val;\n }\n }\n function falsey(val) { return !val; }\n\n // Wraps type (.is/.encode/.decode) functions to operate on each value of an array\n function arrayHandler(callback, allTruthyMode) {\n return function handleArray(val) {\n val = arrayWrap(val);\n var result = map(val, callback);\n if (allTruthyMode === true)\n return filter(result, falsey).length === 0;\n return arrayUnwrap(result);\n };\n }\n\n // Wraps type (.equals) functions to operate on each value of an array\n function arrayEqualsHandler(callback) {\n return function handleArray(val1, val2) {\n var left = arrayWrap(val1), right = arrayWrap(val2);\n if (left.length !== right.length) return false;\n for (var i = 0; i < left.length; i++) {\n if (!callback(left[i], right[i])) return false;\n }\n return true;\n };\n }\n\n this.encode = arrayHandler(bindTo(type, 'encode'));\n this.decode = arrayHandler(bindTo(type, 'decode'));\n this.is = arrayHandler(bindTo(type, 'is'), true);\n this.equals = arrayEqualsHandler(bindTo(type, 'equals'));\n this.pattern = type.pattern;\n this.$arrayMode = mode;\n }\n};\n\n\n\n/**\n * @ngdoc object\n * @name ui.router.util.$urlMatcherFactory\n *\n * @description\n * Factory for {@link ui.router.util.type:UrlMatcher `UrlMatcher`} instances. The factory\n * is also available to providers under the name `$urlMatcherFactoryProvider`.\n */\nfunction $UrlMatcherFactory() {\n $$UMFP = this;\n\n var isCaseInsensitive = false, isStrictMode = true, defaultSquashPolicy = false;\n\n function valToString(val) { return val != null ? val.toString().replace(/\\//g, \"%2F\") : val; }\n function valFromString(val) { return val != null ? val.toString().replace(/%2F/g, \"/\") : val; }\n// TODO: in 1.0, make string .is() return false if value is undefined by default.\n// function regexpMatches(val) { /*jshint validthis:true */ return isDefined(val) && this.pattern.test(val); }\n function regexpMatches(val) { /*jshint validthis:true */ return this.pattern.test(val); }\n\n var $types = {}, enqueue = true, typeQueue = [], injector, defaultTypes = {\n string: {\n encode: valToString,\n decode: valFromString,\n is: regexpMatches,\n pattern: /[^/]*/\n },\n int: {\n encode: valToString,\n decode: function(val) { return parseInt(val, 10); },\n is: function(val) { return isDefined(val) && this.decode(val.toString()) === val; },\n pattern: /\\d+/\n },\n bool: {\n encode: function(val) { return val ? 1 : 0; },\n decode: function(val) { return parseInt(val, 10) !== 0; },\n is: function(val) { return val === true || val === false; },\n pattern: /0|1/\n },\n date: {\n encode: function (val) {\n if (!this.is(val))\n return undefined;\n return [ val.getFullYear(),\n ('0' + (val.getMonth() + 1)).slice(-2),\n ('0' + val.getDate()).slice(-2)\n ].join(\"-\");\n },\n decode: function (val) {\n if (this.is(val)) return val;\n var match = this.capture.exec(val);\n return match ? new Date(match[1], match[2] - 1, match[3]) : undefined;\n },\n is: function(val) { return val instanceof Date && !isNaN(val.valueOf()); },\n equals: function (a, b) { return this.is(a) && this.is(b) && a.toISOString() === b.toISOString(); },\n pattern: /[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,\n capture: /([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/\n },\n json: {\n encode: angular.toJson,\n decode: angular.fromJson,\n is: angular.isObject,\n equals: angular.equals,\n pattern: /[^/]*/\n },\n any: { // does not encode/decode\n encode: angular.identity,\n decode: angular.identity,\n is: angular.identity,\n equals: angular.equals,\n pattern: /.*/\n }\n };\n\n function getDefaultConfig() {\n return {\n strict: isStrictMode,\n caseInsensitive: isCaseInsensitive\n };\n }\n\n function isInjectable(value) {\n return (isFunction(value) || (isArray(value) && isFunction(value[value.length - 1])));\n }\n\n /**\n * [Internal] Get the default value of a parameter, which may be an injectable function.\n */\n $UrlMatcherFactory.$$getDefaultValue = function(config) {\n if (!isInjectable(config.value)) return config.value;\n if (!injector) throw new Error(\"Injectable functions cannot be called at configuration time\");\n return injector.invoke(config.value);\n };\n\n /**\n * @ngdoc function\n * @name ui.router.util.$urlMatcherFactory#caseInsensitive\n * @methodOf ui.router.util.$urlMatcherFactory\n *\n * @description\n * Defines whether URL matching should be case sensitive (the default behavior), or not.\n *\n * @param {boolean} value `false` to match URL in a case sensitive manner; otherwise `true`;\n * @returns {boolean} the current value of caseInsensitive\n */\n this.caseInsensitive = function(value) {\n if (isDefined(value))\n isCaseInsensitive = value;\n return isCaseInsensitive;\n };\n\n /**\n * @ngdoc function\n * @name ui.router.util.$urlMatcherFactory#strictMode\n * @methodOf ui.router.util.$urlMatcherFactory\n *\n * @description\n * Defines whether URLs should match trailing slashes, or not (the default behavior).\n *\n * @param {boolean=} value `false` to match trailing slashes in URLs, otherwise `true`.\n * @returns {boolean} the current value of strictMode\n */\n this.strictMode = function(value) {\n if (isDefined(value))\n isStrictMode = value;\n return isStrictMode;\n };\n\n /**\n * @ngdoc function\n * @name ui.router.util.$urlMatcherFactory#defaultSquashPolicy\n * @methodOf ui.router.util.$urlMatcherFactory\n *\n * @description\n * Sets the default behavior when generating or matching URLs with default parameter values.\n *\n * @param {string} value A string that defines the default parameter URL squashing behavior.\n * `nosquash`: When generating an href with a default parameter value, do not squash the parameter value from the URL\n * `slash`: When generating an href with a default parameter value, squash (remove) the parameter value, and, if the\n * parameter is surrounded by slashes, squash (remove) one slash from the URL\n * any other string, e.g. \"~\": When generating an href with a default parameter value, squash (remove)\n * the parameter value from the URL and replace it with this string.\n */\n this.defaultSquashPolicy = function(value) {\n if (!isDefined(value)) return defaultSquashPolicy;\n if (value !== true && value !== false && !isString(value))\n throw new Error(\"Invalid squash policy: \" + value + \". Valid policies: false, true, arbitrary-string\");\n defaultSquashPolicy = value;\n return value;\n };\n\n /**\n * @ngdoc function\n * @name ui.router.util.$urlMatcherFactory#compile\n * @methodOf ui.router.util.$urlMatcherFactory\n *\n * @description\n * Creates a {@link ui.router.util.type:UrlMatcher `UrlMatcher`} for the specified pattern.\n *\n * @param {string} pattern The URL pattern.\n * @param {Object} config The config object hash.\n * @returns {UrlMatcher} The UrlMatcher.\n */\n this.compile = function (pattern, config) {\n return new UrlMatcher(pattern, extend(getDefaultConfig(), config));\n };\n\n /**\n * @ngdoc function\n * @name ui.router.util.$urlMatcherFactory#isMatcher\n * @methodOf ui.router.util.$urlMatcherFactory\n *\n * @description\n * Returns true if the specified object is a `UrlMatcher`, or false otherwise.\n *\n * @param {Object} object The object to perform the type check against.\n * @returns {Boolean} Returns `true` if the object matches the `UrlMatcher` interface, by\n * implementing all the same methods.\n */\n this.isMatcher = function (o) {\n if (!isObject(o)) return false;\n var result = true;\n\n forEach(UrlMatcher.prototype, function(val, name) {\n if (isFunction(val)) {\n result = result && (isDefined(o[name]) && isFunction(o[name]));\n }\n });\n return result;\n };\n\n /**\n * @ngdoc function\n * @name ui.router.util.$urlMatcherFactory#type\n * @methodOf ui.router.util.$urlMatcherFactory\n *\n * @description\n * Registers a custom {@link ui.router.util.type:Type `Type`} object that can be used to\n * generate URLs with typed parameters.\n *\n * @param {string} name The type name.\n * @param {Object|Function} definition The type definition. See\n * {@link ui.router.util.type:Type `Type`} for information on the values accepted.\n * @param {Object|Function} definitionFn (optional) A function that is injected before the app\n * runtime starts. The result of this function is merged into the existing `definition`.\n * See {@link ui.router.util.type:Type `Type`} for information on the values accepted.\n *\n * @returns {Object} Returns `$urlMatcherFactoryProvider`.\n *\n * @example\n * This is a simple example of a custom type that encodes and decodes items from an\n * array, using the array index as the URL-encoded value:\n *\n *
\n   * var list = ['John', 'Paul', 'George', 'Ringo'];\n   *\n   * $urlMatcherFactoryProvider.type('listItem', {\n   *   encode: function(item) {\n   *     // Represent the list item in the URL using its corresponding index\n   *     return list.indexOf(item);\n   *   },\n   *   decode: function(item) {\n   *     // Look up the list item by index\n   *     return list[parseInt(item, 10)];\n   *   },\n   *   is: function(item) {\n   *     // Ensure the item is valid by checking to see that it appears\n   *     // in the list\n   *     return list.indexOf(item) > -1;\n   *   }\n   * });\n   *\n   * $stateProvider.state('list', {\n   *   url: \"/list/{item:listItem}\",\n   *   controller: function($scope, $stateParams) {\n   *     console.log($stateParams.item);\n   *   }\n   * });\n   *\n   * // ...\n   *\n   * // Changes URL to '/list/3', logs \"Ringo\" to the console\n   * $state.go('list', { item: \"Ringo\" });\n   * 
\n *\n * This is a more complex example of a type that relies on dependency injection to\n * interact with services, and uses the parameter name from the URL to infer how to\n * handle encoding and decoding parameter values:\n *\n *
\n   * // Defines a custom type that gets a value from a service,\n   * // where each service gets different types of values from\n   * // a backend API:\n   * $urlMatcherFactoryProvider.type('dbObject', {}, function(Users, Posts) {\n   *\n   *   // Matches up services to URL parameter names\n   *   var services = {\n   *     user: Users,\n   *     post: Posts\n   *   };\n   *\n   *   return {\n   *     encode: function(object) {\n   *       // Represent the object in the URL using its unique ID\n   *       return object.id;\n   *     },\n   *     decode: function(value, key) {\n   *       // Look up the object by ID, using the parameter\n   *       // name (key) to call the correct service\n   *       return services[key].findById(value);\n   *     },\n   *     is: function(object, key) {\n   *       // Check that object is a valid dbObject\n   *       return angular.isObject(object) && object.id && services[key];\n   *     }\n   *     equals: function(a, b) {\n   *       // Check the equality of decoded objects by comparing\n   *       // their unique IDs\n   *       return a.id === b.id;\n   *     }\n   *   };\n   * });\n   *\n   * // In a config() block, you can then attach URLs with\n   * // type-annotated parameters:\n   * $stateProvider.state('users', {\n   *   url: \"/users\",\n   *   // ...\n   * }).state('users.item', {\n   *   url: \"/{user:dbObject}\",\n   *   controller: function($scope, $stateParams) {\n   *     // $stateParams.user will now be an object returned from\n   *     // the Users service\n   *   },\n   *   // ...\n   * });\n   * 
\n */\n this.type = function (name, definition, definitionFn) {\n if (!isDefined(definition)) return $types[name];\n if ($types.hasOwnProperty(name)) throw new Error(\"A type named '\" + name + \"' has already been defined.\");\n\n $types[name] = new Type(extend({ name: name }, definition));\n if (definitionFn) {\n typeQueue.push({ name: name, def: definitionFn });\n if (!enqueue) flushTypeQueue();\n }\n return this;\n };\n\n // `flushTypeQueue()` waits until `$urlMatcherFactory` is injected before invoking the queued `definitionFn`s\n function flushTypeQueue() {\n while(typeQueue.length) {\n var type = typeQueue.shift();\n if (type.pattern) throw new Error(\"You cannot override a type's .pattern at runtime.\");\n angular.extend($types[type.name], injector.invoke(type.def));\n }\n }\n\n // Register default types. Store them in the prototype of $types.\n forEach(defaultTypes, function(type, name) { $types[name] = new Type(extend({name: name}, type)); });\n $types = inherit($types, {});\n\n /* No need to document $get, since it returns this */\n this.$get = ['$injector', function ($injector) {\n injector = $injector;\n enqueue = false;\n flushTypeQueue();\n\n forEach(defaultTypes, function(type, name) {\n if (!$types[name]) $types[name] = new Type(type);\n });\n return this;\n }];\n\n this.Param = function Param(id, type, config, location) {\n var self = this;\n config = unwrapShorthand(config);\n type = getType(config, type, location);\n var arrayMode = getArrayMode();\n type = arrayMode ? type.$asArray(arrayMode, location === \"search\") : type;\n if (type.name === \"string\" && !arrayMode && location === \"path\" && config.value === undefined)\n config.value = \"\"; // for 0.2.x; in 0.3.0+ do not automatically default to \"\"\n var isOptional = config.value !== undefined;\n var squash = getSquashPolicy(config, isOptional);\n var replace = getReplace(config, arrayMode, isOptional, squash);\n\n function unwrapShorthand(config) {\n var keys = isObject(config) ? objectKeys(config) : [];\n var isShorthand = indexOf(keys, \"value\") === -1 && indexOf(keys, \"type\") === -1 &&\n indexOf(keys, \"squash\") === -1 && indexOf(keys, \"array\") === -1;\n if (isShorthand) config = { value: config };\n config.$$fn = isInjectable(config.value) ? config.value : function () { return config.value; };\n return config;\n }\n\n function getType(config, urlType, location) {\n if (config.type && urlType) throw new Error(\"Param '\"+id+\"' has two type configurations.\");\n if (urlType) return urlType;\n if (!config.type) return (location === \"config\" ? $types.any : $types.string);\n return config.type instanceof Type ? config.type : new Type(config.type);\n }\n\n // array config: param name (param[]) overrides default settings. explicit config overrides param name.\n function getArrayMode() {\n var arrayDefaults = { array: (location === \"search\" ? \"auto\" : false) };\n var arrayParamNomenclature = id.match(/\\[\\]$/) ? { array: true } : {};\n return extend(arrayDefaults, arrayParamNomenclature, config).array;\n }\n\n /**\n * returns false, true, or the squash value to indicate the \"default parameter url squash policy\".\n */\n function getSquashPolicy(config, isOptional) {\n var squash = config.squash;\n if (!isOptional || squash === false) return false;\n if (!isDefined(squash) || squash == null) return defaultSquashPolicy;\n if (squash === true || isString(squash)) return squash;\n throw new Error(\"Invalid squash policy: '\" + squash + \"'. Valid policies: false, true, or arbitrary string\");\n }\n\n function getReplace(config, arrayMode, isOptional, squash) {\n var replace, configuredKeys, defaultPolicy = [\n { from: \"\", to: (isOptional || arrayMode ? undefined : \"\") },\n { from: null, to: (isOptional || arrayMode ? undefined : \"\") }\n ];\n replace = isArray(config.replace) ? config.replace : [];\n if (isString(squash))\n replace.push({ from: squash, to: undefined });\n configuredKeys = map(replace, function(item) { return item.from; } );\n return filter(defaultPolicy, function(item) { return indexOf(configuredKeys, item.from) === -1; }).concat(replace);\n }\n\n /**\n * [Internal] Get the default value of a parameter, which may be an injectable function.\n */\n function $$getDefaultValue() {\n if (!injector) throw new Error(\"Injectable functions cannot be called at configuration time\");\n return injector.invoke(config.$$fn);\n }\n\n /**\n * [Internal] Gets the decoded representation of a value if the value is defined, otherwise, returns the\n * default value, which may be the result of an injectable function.\n */\n function $value(value) {\n function hasReplaceVal(val) { return function(obj) { return obj.from === val; }; }\n function $replace(value) {\n var replacement = map(filter(self.replace, hasReplaceVal(value)), function(obj) { return obj.to; });\n return replacement.length ? replacement[0] : value;\n }\n value = $replace(value);\n return isDefined(value) ? self.type.decode(value) : $$getDefaultValue();\n }\n\n function toString() { return \"{Param:\" + id + \" \" + type + \" squash: '\" + squash + \"' optional: \" + isOptional + \"}\"; }\n\n extend(this, {\n id: id,\n type: type,\n location: location,\n array: arrayMode,\n squash: squash,\n replace: replace,\n isOptional: isOptional,\n value: $value,\n dynamic: undefined,\n config: config,\n toString: toString\n });\n };\n\n function ParamSet(params) {\n extend(this, params || {});\n }\n\n ParamSet.prototype = {\n $$new: function() {\n return inherit(this, extend(new ParamSet(), { $$parent: this}));\n },\n $$keys: function () {\n var keys = [], chain = [], parent = this,\n ignore = objectKeys(ParamSet.prototype);\n while (parent) { chain.push(parent); parent = parent.$$parent; }\n chain.reverse();\n forEach(chain, function(paramset) {\n forEach(objectKeys(paramset), function(key) {\n if (indexOf(keys, key) === -1 && indexOf(ignore, key) === -1) keys.push(key);\n });\n });\n return keys;\n },\n $$values: function(paramValues) {\n var values = {}, self = this;\n forEach(self.$$keys(), function(key) {\n values[key] = self[key].value(paramValues && paramValues[key]);\n });\n return values;\n },\n $$equals: function(paramValues1, paramValues2) {\n var equal = true, self = this;\n forEach(self.$$keys(), function(key) {\n var left = paramValues1 && paramValues1[key], right = paramValues2 && paramValues2[key];\n if (!self[key].type.equals(left, right)) equal = false;\n });\n return equal;\n },\n $$validates: function $$validate(paramValues) {\n var result = true, isOptional, val, param, self = this;\n\n forEach(this.$$keys(), function(key) {\n param = self[key];\n val = paramValues[key];\n isOptional = !val && param.isOptional;\n result = result && (isOptional || !!param.type.is(val));\n });\n return result;\n },\n $$parent: undefined\n };\n\n this.ParamSet = ParamSet;\n}\n\n// Register as a provider so it's available to other providers\nangular.module('ui.router.util').provider('$urlMatcherFactory', $UrlMatcherFactory);\nangular.module('ui.router.util').run(['$urlMatcherFactory', function($urlMatcherFactory) { }]);\n\n/**\n * @ngdoc object\n * @name ui.router.router.$urlRouterProvider\n *\n * @requires ui.router.util.$urlMatcherFactoryProvider\n * @requires $locationProvider\n *\n * @description\n * `$urlRouterProvider` has the responsibility of watching `$location`. \n * When `$location` changes it runs through a list of rules one by one until a \n * match is found. `$urlRouterProvider` is used behind the scenes anytime you specify \n * a url in a state configuration. All urls are compiled into a UrlMatcher object.\n *\n * There are several methods on `$urlRouterProvider` that make it useful to use directly\n * in your module config.\n */\n$UrlRouterProvider.$inject = ['$locationProvider', '$urlMatcherFactoryProvider'];\nfunction $UrlRouterProvider( $locationProvider, $urlMatcherFactory) {\n var rules = [], otherwise = null, interceptDeferred = false, listener;\n\n // Returns a string that is a prefix of all strings matching the RegExp\n function regExpPrefix(re) {\n var prefix = /^\\^((?:\\\\[^a-zA-Z0-9]|[^\\\\\\[\\]\\^$*+?.()|{}]+)*)/.exec(re.source);\n return (prefix != null) ? prefix[1].replace(/\\\\(.)/g, \"$1\") : '';\n }\n\n // Interpolates matched values into a String.replace()-style pattern\n function interpolate(pattern, match) {\n return pattern.replace(/\\$(\\$|\\d{1,2})/, function (m, what) {\n return match[what === '$' ? 0 : Number(what)];\n });\n }\n\n /**\n * @ngdoc function\n * @name ui.router.router.$urlRouterProvider#rule\n * @methodOf ui.router.router.$urlRouterProvider\n *\n * @description\n * Defines rules that are used by `$urlRouterProvider` to find matches for\n * specific URLs.\n *\n * @example\n *
\n   * var app = angular.module('app', ['ui.router.router']);\n   *\n   * app.config(function ($urlRouterProvider) {\n   *   // Here's an example of how you might allow case insensitive urls\n   *   $urlRouterProvider.rule(function ($injector, $location) {\n   *     var path = $location.path(),\n   *         normalized = path.toLowerCase();\n   *\n   *     if (path !== normalized) {\n   *       return normalized;\n   *     }\n   *   });\n   * });\n   * 
\n *\n * @param {object} rule Handler function that takes `$injector` and `$location`\n * services as arguments. You can use them to return a valid path as a string.\n *\n * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance\n */\n this.rule = function (rule) {\n if (!isFunction(rule)) throw new Error(\"'rule' must be a function\");\n rules.push(rule);\n return this;\n };\n\n /**\n * @ngdoc object\n * @name ui.router.router.$urlRouterProvider#otherwise\n * @methodOf ui.router.router.$urlRouterProvider\n *\n * @description\n * Defines a path that is used when an invalid route is requested.\n *\n * @example\n *
\n   * var app = angular.module('app', ['ui.router.router']);\n   *\n   * app.config(function ($urlRouterProvider) {\n   *   // if the path doesn't match any of the urls you configured\n   *   // otherwise will take care of routing the user to the\n   *   // specified url\n   *   $urlRouterProvider.otherwise('/index');\n   *\n   *   // Example of using function rule as param\n   *   $urlRouterProvider.otherwise(function ($injector, $location) {\n   *     return '/a/valid/url';\n   *   });\n   * });\n   * 
\n *\n * @param {string|object} rule The url path you want to redirect to or a function \n * rule that returns the url path. The function version is passed two params: \n * `$injector` and `$location` services, and must return a url string.\n *\n * @return {object} `$urlRouterProvider` - `$urlRouterProvider` instance\n */\n this.otherwise = function (rule) {\n if (isString(rule)) {\n var redirect = rule;\n rule = function () { return redirect; };\n }\n else if (!isFunction(rule)) throw new Error(\"'rule' must be a function\");\n otherwise = rule;\n return this;\n };\n\n\n function handleIfMatch($injector, handler, match) {\n if (!match) return false;\n var result = $injector.invoke(handler, handler, { $match: match });\n return isDefined(result) ? result : true;\n }\n\n /**\n * @ngdoc function\n * @name ui.router.router.$urlRouterProvider#when\n * @methodOf ui.router.router.$urlRouterProvider\n *\n * @description\n * Registers a handler for a given url matching. if handle is a string, it is\n * treated as a redirect, and is interpolated according to the syntax of match\n * (i.e. like `String.replace()` for `RegExp`, or like a `UrlMatcher` pattern otherwise).\n *\n * If the handler is a function, it is injectable. It gets invoked if `$location`\n * matches. You have the option of inject the match object as `$match`.\n *\n * The handler can return\n *\n * - **falsy** to indicate that the rule didn't match after all, then `$urlRouter`\n * will continue trying to find another one that matches.\n * - **string** which is treated as a redirect and passed to `$location.url()`\n * - **void** or any **truthy** value tells `$urlRouter` that the url was handled.\n *\n * @example\n *
\n   * var app = angular.module('app', ['ui.router.router']);\n   *\n   * app.config(function ($urlRouterProvider) {\n   *   $urlRouterProvider.when($state.url, function ($match, $stateParams) {\n   *     if ($state.$current.navigable !== state ||\n   *         !equalForKeys($match, $stateParams) {\n   *      $state.transitionTo(state, $match, false);\n   *     }\n   *   });\n   * });\n   * 
\n *\n * @param {string|object} what The incoming path that you want to redirect.\n * @param {string|object} handler The path you want to redirect your user to.\n */\n this.when = function (what, handler) {\n var redirect, handlerIsString = isString(handler);\n if (isString(what)) what = $urlMatcherFactory.compile(what);\n\n if (!handlerIsString && !isFunction(handler) && !isArray(handler))\n throw new Error(\"invalid 'handler' in when()\");\n\n var strategies = {\n matcher: function (what, handler) {\n if (handlerIsString) {\n redirect = $urlMatcherFactory.compile(handler);\n handler = ['$match', function ($match) { return redirect.format($match); }];\n }\n return extend(function ($injector, $location) {\n return handleIfMatch($injector, handler, what.exec($location.path(), $location.search()));\n }, {\n prefix: isString(what.prefix) ? what.prefix : ''\n });\n },\n regex: function (what, handler) {\n if (what.global || what.sticky) throw new Error(\"when() RegExp must not be global or sticky\");\n\n if (handlerIsString) {\n redirect = handler;\n handler = ['$match', function ($match) { return interpolate(redirect, $match); }];\n }\n return extend(function ($injector, $location) {\n return handleIfMatch($injector, handler, what.exec($location.path()));\n }, {\n prefix: regExpPrefix(what)\n });\n }\n };\n\n var check = { matcher: $urlMatcherFactory.isMatcher(what), regex: what instanceof RegExp };\n\n for (var n in check) {\n if (check[n]) return this.rule(strategies[n](what, handler));\n }\n\n throw new Error(\"invalid 'what' in when()\");\n };\n\n /**\n * @ngdoc function\n * @name ui.router.router.$urlRouterProvider#deferIntercept\n * @methodOf ui.router.router.$urlRouterProvider\n *\n * @description\n * Disables (or enables) deferring location change interception.\n *\n * If you wish to customize the behavior of syncing the URL (for example, if you wish to\n * defer a transition but maintain the current URL), call this method at configuration time.\n * Then, at run time, call `$urlRouter.listen()` after you have configured your own\n * `$locationChangeSuccess` event handler.\n *\n * @example\n *
\n   * var app = angular.module('app', ['ui.router.router']);\n   *\n   * app.config(function ($urlRouterProvider) {\n   *\n   *   // Prevent $urlRouter from automatically intercepting URL changes;\n   *   // this allows you to configure custom behavior in between\n   *   // location changes and route synchronization:\n   *   $urlRouterProvider.deferIntercept();\n   *\n   * }).run(function ($rootScope, $urlRouter, UserService) {\n   *\n   *   $rootScope.$on('$locationChangeSuccess', function(e) {\n   *     // UserService is an example service for managing user state\n   *     if (UserService.isLoggedIn()) return;\n   *\n   *     // Prevent $urlRouter's default handler from firing\n   *     e.preventDefault();\n   *\n   *     UserService.handleLogin().then(function() {\n   *       // Once the user has logged in, sync the current URL\n   *       // to the router:\n   *       $urlRouter.sync();\n   *     });\n   *   });\n   *\n   *   // Configures $urlRouter's listener *after* your custom listener\n   *   $urlRouter.listen();\n   * });\n   * 
\n *\n * @param {boolean} defer Indicates whether to defer location change interception. Passing\n no parameter is equivalent to `true`.\n */\n this.deferIntercept = function (defer) {\n if (defer === undefined) defer = true;\n interceptDeferred = defer;\n };\n\n /**\n * @ngdoc object\n * @name ui.router.router.$urlRouter\n *\n * @requires $location\n * @requires $rootScope\n * @requires $injector\n * @requires $browser\n *\n * @description\n *\n */\n this.$get = $get;\n $get.$inject = ['$location', '$rootScope', '$injector', '$browser'];\n function $get( $location, $rootScope, $injector, $browser) {\n\n var baseHref = $browser.baseHref(), location = $location.url(), lastPushedUrl;\n\n function appendBasePath(url, isHtml5, absolute) {\n if (baseHref === '/') return url;\n if (isHtml5) return baseHref.slice(0, -1) + url;\n if (absolute) return baseHref.slice(1) + url;\n return url;\n }\n\n // TODO: Optimize groups of rules with non-empty prefix into some sort of decision tree\n function update(evt) {\n if (evt && evt.defaultPrevented) return;\n var ignoreUpdate = lastPushedUrl && $location.url() === lastPushedUrl;\n lastPushedUrl = undefined;\n if (ignoreUpdate) return true;\n\n function check(rule) {\n var handled = rule($injector, $location);\n\n if (!handled) return false;\n if (isString(handled)) $location.replace().url(handled);\n return true;\n }\n var n = rules.length, i;\n\n for (i = 0; i < n; i++) {\n if (check(rules[i])) return;\n }\n // always check otherwise last to allow dynamic updates to the set of rules\n if (otherwise) check(otherwise);\n }\n\n function listen() {\n listener = listener || $rootScope.$on('$locationChangeSuccess', update);\n return listener;\n }\n\n if (!interceptDeferred) listen();\n\n return {\n /**\n * @ngdoc function\n * @name ui.router.router.$urlRouter#sync\n * @methodOf ui.router.router.$urlRouter\n *\n * @description\n * Triggers an update; the same update that happens when the address bar url changes, aka `$locationChangeSuccess`.\n * This method is useful when you need to use `preventDefault()` on the `$locationChangeSuccess` event,\n * perform some custom logic (route protection, auth, config, redirection, etc) and then finally proceed\n * with the transition by calling `$urlRouter.sync()`.\n *\n * @example\n *
\n       * angular.module('app', ['ui.router'])\n       *   .run(function($rootScope, $urlRouter) {\n       *     $rootScope.$on('$locationChangeSuccess', function(evt) {\n       *       // Halt state change from even starting\n       *       evt.preventDefault();\n       *       // Perform custom logic\n       *       var meetsRequirement = ...\n       *       // Continue with the update and state transition if logic allows\n       *       if (meetsRequirement) $urlRouter.sync();\n       *     });\n       * });\n       * 
\n */\n sync: function() {\n update();\n },\n\n listen: function() {\n return listen();\n },\n\n update: function(read) {\n if (read) {\n location = $location.url();\n return;\n }\n if ($location.url() === location) return;\n\n $location.url(location);\n $location.replace();\n },\n\n push: function(urlMatcher, params, options) {\n $location.url(urlMatcher.format(params || {}));\n lastPushedUrl = options && options.$$avoidResync ? $location.url() : undefined;\n if (options && options.replace) $location.replace();\n },\n\n /**\n * @ngdoc function\n * @name ui.router.router.$urlRouter#href\n * @methodOf ui.router.router.$urlRouter\n *\n * @description\n * A URL generation method that returns the compiled URL for a given\n * {@link ui.router.util.type:UrlMatcher `UrlMatcher`}, populated with the provided parameters.\n *\n * @example\n *
\n       * $bob = $urlRouter.href(new UrlMatcher(\"/about/:person\"), {\n       *   person: \"bob\"\n       * });\n       * // $bob == \"/about/bob\";\n       * 
\n *\n * @param {UrlMatcher} urlMatcher The `UrlMatcher` object which is used as the template of the URL to generate.\n * @param {object=} params An object of parameter values to fill the matcher's required parameters.\n * @param {object=} options Options object. The options are:\n *\n * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. \"http://www.example.com/fullurl\".\n *\n * @returns {string} Returns the fully compiled URL, or `null` if `params` fail validation against `urlMatcher`\n */\n href: function(urlMatcher, params, options) {\n if (!urlMatcher.validates(params)) return null;\n\n var isHtml5 = $locationProvider.html5Mode();\n if (angular.isObject(isHtml5)) {\n isHtml5 = isHtml5.enabled;\n }\n \n var url = urlMatcher.format(params);\n options = options || {};\n\n if (!isHtml5 && url !== null) {\n url = \"#\" + $locationProvider.hashPrefix() + url;\n }\n url = appendBasePath(url, isHtml5, options.absolute);\n\n if (!options.absolute || !url) {\n return url;\n }\n\n var slash = (!isHtml5 && url ? '/' : ''), port = $location.port();\n port = (port === 80 || port === 443 ? '' : ':' + port);\n\n return [$location.protocol(), '://', $location.host(), port, slash, url].join('');\n }\n };\n }\n}\n\nangular.module('ui.router.router').provider('$urlRouter', $UrlRouterProvider);\n\n/**\n * @ngdoc object\n * @name ui.router.state.$stateProvider\n *\n * @requires ui.router.router.$urlRouterProvider\n * @requires ui.router.util.$urlMatcherFactoryProvider\n *\n * @description\n * The new `$stateProvider` works similar to Angular's v1 router, but it focuses purely\n * on state.\n *\n * A state corresponds to a \"place\" in the application in terms of the overall UI and\n * navigation. A state describes (via the controller / template / view properties) what\n * the UI looks like and does at that place.\n *\n * States often have things in common, and the primary way of factoring out these\n * commonalities in this model is via the state hierarchy, i.e. parent/child states aka\n * nested states.\n *\n * The `$stateProvider` provides interfaces to declare these states for your app.\n */\n$StateProvider.$inject = ['$urlRouterProvider', '$urlMatcherFactoryProvider'];\nfunction $StateProvider( $urlRouterProvider, $urlMatcherFactory) {\n\n var root, states = {}, $state, queue = {}, abstractKey = 'abstract';\n\n // Builds state properties from definition passed to registerState()\n var stateBuilder = {\n\n // Derive parent state from a hierarchical name only if 'parent' is not explicitly defined.\n // state.children = [];\n // if (parent) parent.children.push(state);\n parent: function(state) {\n if (isDefined(state.parent) && state.parent) return findState(state.parent);\n // regex matches any valid composite state name\n // would match \"contact.list\" but not \"contacts\"\n var compositeName = /^(.+)\\.[^.]+$/.exec(state.name);\n return compositeName ? findState(compositeName[1]) : root;\n },\n\n // inherit 'data' from parent and override by own values (if any)\n data: function(state) {\n if (state.parent && state.parent.data) {\n state.data = state.self.data = extend({}, state.parent.data, state.data);\n }\n return state.data;\n },\n\n // Build a URLMatcher if necessary, either via a relative or absolute URL\n url: function(state) {\n var url = state.url, config = { params: state.params || {} };\n\n if (isString(url)) {\n if (url.charAt(0) == '^') return $urlMatcherFactory.compile(url.substring(1), config);\n return (state.parent.navigable || root).url.concat(url, config);\n }\n\n if (!url || $urlMatcherFactory.isMatcher(url)) return url;\n throw new Error(\"Invalid url '\" + url + \"' in state '\" + state + \"'\");\n },\n\n // Keep track of the closest ancestor state that has a URL (i.e. is navigable)\n navigable: function(state) {\n return state.url ? state : (state.parent ? state.parent.navigable : null);\n },\n\n // Own parameters for this state. state.url.params is already built at this point. Create and add non-url params\n ownParams: function(state) {\n var params = state.url && state.url.params || new $$UMFP.ParamSet();\n forEach(state.params || {}, function(config, id) {\n if (!params[id]) params[id] = new $$UMFP.Param(id, null, config, \"config\");\n });\n return params;\n },\n\n // Derive parameters for this state and ensure they're a super-set of parent's parameters\n params: function(state) {\n return state.parent && state.parent.params ? extend(state.parent.params.$$new(), state.ownParams) : new $$UMFP.ParamSet();\n },\n\n // If there is no explicit multi-view configuration, make one up so we don't have\n // to handle both cases in the view directive later. Note that having an explicit\n // 'views' property will mean the default unnamed view properties are ignored. This\n // is also a good time to resolve view names to absolute names, so everything is a\n // straight lookup at link time.\n views: function(state) {\n var views = {};\n\n forEach(isDefined(state.views) ? state.views : { '': state }, function (view, name) {\n if (name.indexOf('@') < 0) name += '@' + state.parent.name;\n views[name] = view;\n });\n return views;\n },\n\n // Keep a full path from the root down to this state as this is needed for state activation.\n path: function(state) {\n return state.parent ? state.parent.path.concat(state) : []; // exclude root from path\n },\n\n // Speed up $state.contains() as it's used a lot\n includes: function(state) {\n var includes = state.parent ? extend({}, state.parent.includes) : {};\n includes[state.name] = true;\n return includes;\n },\n\n $delegates: {}\n };\n\n function isRelative(stateName) {\n return stateName.indexOf(\".\") === 0 || stateName.indexOf(\"^\") === 0;\n }\n\n function findState(stateOrName, base) {\n if (!stateOrName) return undefined;\n\n var isStr = isString(stateOrName),\n name = isStr ? stateOrName : stateOrName.name,\n path = isRelative(name);\n\n if (path) {\n if (!base) throw new Error(\"No reference point given for path '\" + name + \"'\");\n base = findState(base);\n \n var rel = name.split(\".\"), i = 0, pathLength = rel.length, current = base;\n\n for (; i < pathLength; i++) {\n if (rel[i] === \"\" && i === 0) {\n current = base;\n continue;\n }\n if (rel[i] === \"^\") {\n if (!current.parent) throw new Error(\"Path '\" + name + \"' not valid for state '\" + base.name + \"'\");\n current = current.parent;\n continue;\n }\n break;\n }\n rel = rel.slice(i).join(\".\");\n name = current.name + (current.name && rel ? \".\" : \"\") + rel;\n }\n var state = states[name];\n\n if (state && (isStr || (!isStr && (state === stateOrName || state.self === stateOrName)))) {\n return state;\n }\n return undefined;\n }\n\n function queueState(parentName, state) {\n if (!queue[parentName]) {\n queue[parentName] = [];\n }\n queue[parentName].push(state);\n }\n\n function flushQueuedChildren(parentName) {\n var queued = queue[parentName] || [];\n while(queued.length) {\n registerState(queued.shift());\n }\n }\n\n function registerState(state) {\n // Wrap a new object around the state so we can store our private details easily.\n state = inherit(state, {\n self: state,\n resolve: state.resolve || {},\n toString: function() { return this.name; }\n });\n\n var name = state.name;\n if (!isString(name) || name.indexOf('@') >= 0) throw new Error(\"State must have a valid name\");\n if (states.hasOwnProperty(name)) throw new Error(\"State '\" + name + \"'' is already defined\");\n\n // Get parent name\n var parentName = (name.indexOf('.') !== -1) ? name.substring(0, name.lastIndexOf('.'))\n : (isString(state.parent)) ? state.parent\n : (isObject(state.parent) && isString(state.parent.name)) ? state.parent.name\n : '';\n\n // If parent is not registered yet, add state to queue and register later\n if (parentName && !states[parentName]) {\n return queueState(parentName, state.self);\n }\n\n for (var key in stateBuilder) {\n if (isFunction(stateBuilder[key])) state[key] = stateBuilder[key](state, stateBuilder.$delegates[key]);\n }\n states[name] = state;\n\n // Register the state in the global state list and with $urlRouter if necessary.\n if (!state[abstractKey] && state.url) {\n $urlRouterProvider.when(state.url, ['$match', '$stateParams', function ($match, $stateParams) {\n if ($state.$current.navigable != state || !equalForKeys($match, $stateParams)) {\n $state.transitionTo(state, $match, { inherit: true, location: false });\n }\n }]);\n }\n\n // Register any queued children\n flushQueuedChildren(name);\n\n return state;\n }\n\n // Checks text to see if it looks like a glob.\n function isGlob (text) {\n return text.indexOf('*') > -1;\n }\n\n // Returns true if glob matches current $state name.\n function doesStateMatchGlob (glob) {\n var globSegments = glob.split('.'),\n segments = $state.$current.name.split('.');\n\n //match greedy starts\n if (globSegments[0] === '**') {\n segments = segments.slice(indexOf(segments, globSegments[1]));\n segments.unshift('**');\n }\n //match greedy ends\n if (globSegments[globSegments.length - 1] === '**') {\n segments.splice(indexOf(segments, globSegments[globSegments.length - 2]) + 1, Number.MAX_VALUE);\n segments.push('**');\n }\n\n if (globSegments.length != segments.length) {\n return false;\n }\n\n //match single stars\n for (var i = 0, l = globSegments.length; i < l; i++) {\n if (globSegments[i] === '*') {\n segments[i] = '*';\n }\n }\n\n return segments.join('') === globSegments.join('');\n }\n\n\n // Implicit root state that is always active\n root = registerState({\n name: '',\n url: '^',\n views: null,\n 'abstract': true\n });\n root.navigable = null;\n\n\n /**\n * @ngdoc function\n * @name ui.router.state.$stateProvider#decorator\n * @methodOf ui.router.state.$stateProvider\n *\n * @description\n * Allows you to extend (carefully) or override (at your own peril) the \n * `stateBuilder` object used internally by `$stateProvider`. This can be used \n * to add custom functionality to ui-router, for example inferring templateUrl \n * based on the state name.\n *\n * When passing only a name, it returns the current (original or decorated) builder\n * function that matches `name`.\n *\n * The builder functions that can be decorated are listed below. Though not all\n * necessarily have a good use case for decoration, that is up to you to decide.\n *\n * In addition, users can attach custom decorators, which will generate new \n * properties within the state's internal definition. There is currently no clear \n * use-case for this beyond accessing internal states (i.e. $state.$current), \n * however, expect this to become increasingly relevant as we introduce additional \n * meta-programming features.\n *\n * **Warning**: Decorators should not be interdependent because the order of \n * execution of the builder functions in non-deterministic. Builder functions \n * should only be dependent on the state definition object and super function.\n *\n *\n * Existing builder functions and current return values:\n *\n * - **parent** `{object}` - returns the parent state object.\n * - **data** `{object}` - returns state data, including any inherited data that is not\n * overridden by own values (if any).\n * - **url** `{object}` - returns a {@link ui.router.util.type:UrlMatcher UrlMatcher}\n * or `null`.\n * - **navigable** `{object}` - returns closest ancestor state that has a URL (aka is \n * navigable).\n * - **params** `{object}` - returns an array of state params that are ensured to \n * be a super-set of parent's params.\n * - **views** `{object}` - returns a views object where each key is an absolute view \n * name (i.e. \"viewName@stateName\") and each value is the config object \n * (template, controller) for the view. Even when you don't use the views object \n * explicitly on a state config, one is still created for you internally.\n * So by decorating this builder function you have access to decorating template \n * and controller properties.\n * - **ownParams** `{object}` - returns an array of params that belong to the state, \n * not including any params defined by ancestor states.\n * - **path** `{string}` - returns the full path from the root down to this state. \n * Needed for state activation.\n * - **includes** `{object}` - returns an object that includes every state that \n * would pass a `$state.includes()` test.\n *\n * @example\n *
\n   * // Override the internal 'views' builder with a function that takes the state\n   * // definition, and a reference to the internal function being overridden:\n   * $stateProvider.decorator('views', function (state, parent) {\n   *   var result = {},\n   *       views = parent(state);\n   *\n   *   angular.forEach(views, function (config, name) {\n   *     var autoName = (state.name + '.' + name).replace('.', '/');\n   *     config.templateUrl = config.templateUrl || '/partials/' + autoName + '.html';\n   *     result[name] = config;\n   *   });\n   *   return result;\n   * });\n   *\n   * $stateProvider.state('home', {\n   *   views: {\n   *     'contact.list': { controller: 'ListController' },\n   *     'contact.item': { controller: 'ItemController' }\n   *   }\n   * });\n   *\n   * // ...\n   *\n   * $state.go('home');\n   * // Auto-populates list and item views with /partials/home/contact/list.html,\n   * // and /partials/home/contact/item.html, respectively.\n   * 
\n *\n * @param {string} name The name of the builder function to decorate. \n * @param {object} func A function that is responsible for decorating the original \n * builder function. The function receives two parameters:\n *\n * - `{object}` - state - The state config object.\n * - `{object}` - super - The original builder function.\n *\n * @return {object} $stateProvider - $stateProvider instance\n */\n this.decorator = decorator;\n function decorator(name, func) {\n /*jshint validthis: true */\n if (isString(name) && !isDefined(func)) {\n return stateBuilder[name];\n }\n if (!isFunction(func) || !isString(name)) {\n return this;\n }\n if (stateBuilder[name] && !stateBuilder.$delegates[name]) {\n stateBuilder.$delegates[name] = stateBuilder[name];\n }\n stateBuilder[name] = func;\n return this;\n }\n\n /**\n * @ngdoc function\n * @name ui.router.state.$stateProvider#state\n * @methodOf ui.router.state.$stateProvider\n *\n * @description\n * Registers a state configuration under a given state name. The stateConfig object\n * has the following acceptable properties.\n *\n * @param {string} name A unique state name, e.g. \"home\", \"about\", \"contacts\".\n * To create a parent/child state use a dot, e.g. \"about.sales\", \"home.newest\".\n * @param {object} stateConfig State configuration object.\n * @param {string|function=} stateConfig.template\n * \n * html template as a string or a function that returns\n * an html template as a string which should be used by the uiView directives. This property \n * takes precedence over templateUrl.\n * \n * If `template` is a function, it will be called with the following parameters:\n *\n * - {array.<object>} - state parameters extracted from the current $location.path() by\n * applying the current state\n *\n *
template:\n   *   \"

inline template definition

\" +\n * \"
\"
\n *
template: function(params) {\n   *       return \"

generated template

\"; }
\n * \n *\n * @param {string|function=} stateConfig.templateUrl\n * \n *\n * path or function that returns a path to an html\n * template that should be used by uiView.\n * \n * If `templateUrl` is a function, it will be called with the following parameters:\n *\n * - {array.<object>} - state parameters extracted from the current $location.path() by \n * applying the current state\n *\n *
templateUrl: \"home.html\"
\n *
templateUrl: function(params) {\n   *     return myTemplates[params.pageId]; }
\n *\n * @param {function=} stateConfig.templateProvider\n * \n * Provider function that returns HTML content string.\n *
 templateProvider:\n   *       function(MyTemplateService, params) {\n   *         return MyTemplateService.getTemplate(params.pageId);\n   *       }
\n *\n * @param {string|function=} stateConfig.controller\n * \n *\n * Controller fn that should be associated with newly\n * related scope or the name of a registered controller if passed as a string.\n * Optionally, the ControllerAs may be declared here.\n *
controller: \"MyRegisteredController\"
\n *
controller:\n   *     \"MyRegisteredController as fooCtrl\"}
\n *
controller: function($scope, MyService) {\n   *     $scope.data = MyService.getData(); }
\n *\n * @param {function=} stateConfig.controllerProvider\n * \n *\n * Injectable provider function that returns the actual controller or string.\n *
controllerProvider:\n   *   function(MyResolveData) {\n   *     if (MyResolveData.foo)\n   *       return \"FooCtrl\"\n   *     else if (MyResolveData.bar)\n   *       return \"BarCtrl\";\n   *     else return function($scope) {\n   *       $scope.baz = \"Qux\";\n   *     }\n   *   }
\n *\n * @param {string=} stateConfig.controllerAs\n * \n * \n * A controller alias name. If present the controller will be\n * published to scope under the controllerAs name.\n *
controllerAs: \"myCtrl\"
\n *\n * @param {object=} stateConfig.resolve\n * \n *\n * An optional map<string, function> of dependencies which\n * should be injected into the controller. If any of these dependencies are promises, \n * the router will wait for them all to be resolved before the controller is instantiated.\n * If all the promises are resolved successfully, the $stateChangeSuccess event is fired\n * and the values of the resolved promises are injected into any controllers that reference them.\n * If any of the promises are rejected the $stateChangeError event is fired.\n *\n * The map object is:\n * \n * - key - {string}: name of dependency to be injected into controller\n * - factory - {string|function}: If string then it is alias for service. Otherwise if function, \n * it is injected and return value it treated as dependency. If result is a promise, it is \n * resolved before its value is injected into controller.\n *\n *
resolve: {\n   *     myResolve1:\n   *       function($http, $stateParams) {\n   *         return $http.get(\"/api/foos/\"+stateParams.fooID);\n   *       }\n   *     }
\n *\n * @param {string=} stateConfig.url\n * \n *\n * A url fragment with optional parameters. When a state is navigated or\n * transitioned to, the `$stateParams` service will be populated with any \n * parameters that were passed.\n *\n * examples:\n *
url: \"/home\"\n   * url: \"/users/:userid\"\n   * url: \"/books/{bookid:[a-zA-Z_-]}\"\n   * url: \"/books/{categoryid:int}\"\n   * url: \"/books/{publishername:string}/{categoryid:int}\"\n   * url: \"/messages?before&after\"\n   * url: \"/messages?{before:date}&{after:date}\"
\n * url: \"/messages/:mailboxid?{before:date}&{after:date}\"\n *\n * @param {object=} stateConfig.views\n * \n * an optional map<string, object> which defined multiple views, or targets views\n * manually/explicitly.\n *\n * Examples:\n *\n * Targets three named `ui-view`s in the parent state's template\n *
views: {\n   *     header: {\n   *       controller: \"headerCtrl\",\n   *       templateUrl: \"header.html\"\n   *     }, body: {\n   *       controller: \"bodyCtrl\",\n   *       templateUrl: \"body.html\"\n   *     }, footer: {\n   *       controller: \"footCtrl\",\n   *       templateUrl: \"footer.html\"\n   *     }\n   *   }
\n *\n * Targets named `ui-view=\"header\"` from grandparent state 'top''s template, and named `ui-view=\"body\" from parent state's template.\n *
views: {\n   *     'header@top': {\n   *       controller: \"msgHeaderCtrl\",\n   *       templateUrl: \"msgHeader.html\"\n   *     }, 'body': {\n   *       controller: \"messagesCtrl\",\n   *       templateUrl: \"messages.html\"\n   *     }\n   *   }
\n *\n * @param {boolean=} [stateConfig.abstract=false]\n * \n * An abstract state will never be directly activated,\n * but can provide inherited properties to its common children states.\n *
abstract: true
\n *\n * @param {function=} stateConfig.onEnter\n * \n *\n * Callback function for when a state is entered. Good way\n * to trigger an action or dispatch an event, such as opening a dialog.\n * If minifying your scripts, make sure to explictly annotate this function,\n * because it won't be automatically annotated by your build tools.\n *\n *
onEnter: function(MyService, $stateParams) {\n   *     MyService.foo($stateParams.myParam);\n   * }
\n *\n * @param {function=} stateConfig.onExit\n * \n *\n * Callback function for when a state is exited. Good way to\n * trigger an action or dispatch an event, such as opening a dialog.\n * If minifying your scripts, make sure to explictly annotate this function,\n * because it won't be automatically annotated by your build tools.\n *\n *
onExit: function(MyService, $stateParams) {\n   *     MyService.cleanup($stateParams.myParam);\n   * }
\n *\n * @param {boolean=} [stateConfig.reloadOnSearch=true]\n * \n *\n * If `false`, will not retrigger the same state\n * just because a search/query parameter has changed (via $location.search() or $location.hash()). \n * Useful for when you'd like to modify $location.search() without triggering a reload.\n *
reloadOnSearch: false
\n *\n * @param {object=} stateConfig.data\n * \n *\n * Arbitrary data object, useful for custom configuration. The parent state's `data` is\n * prototypally inherited. In other words, adding a data property to a state adds it to\n * the entire subtree via prototypal inheritance.\n *\n *
data: {\n   *     requiredRole: 'foo'\n   * } 
\n *\n * @param {object=} stateConfig.params\n * \n *\n * A map which optionally configures parameters declared in the `url`, or\n * defines additional non-url parameters. For each parameter being\n * configured, add a configuration object keyed to the name of the parameter.\n *\n * Each parameter configuration object may contain the following properties:\n *\n * - ** value ** - {object|function=}: specifies the default value for this\n * parameter. This implicitly sets this parameter as optional.\n *\n * When UI-Router routes to a state and no value is\n * specified for this parameter in the URL or transition, the\n * default value will be used instead. If `value` is a function,\n * it will be injected and invoked, and the return value used.\n *\n * *Note*: `undefined` is treated as \"no default value\" while `null`\n * is treated as \"the default value is `null`\".\n *\n * *Shorthand*: If you only need to configure the default value of the\n * parameter, you may use a shorthand syntax. In the **`params`**\n * map, instead mapping the param name to a full parameter configuration\n * object, simply set map it to the default parameter value, e.g.:\n *\n *
// define a parameter's default value\n   * params: {\n   *     param1: { value: \"defaultValue\" }\n   * }\n   * // shorthand default values\n   * params: {\n   *     param1: \"defaultValue\",\n   *     param2: \"param2Default\"\n   * }
\n *\n * - ** array ** - {boolean=}: *(default: false)* If true, the param value will be\n * treated as an array of values. If you specified a Type, the value will be\n * treated as an array of the specified Type. Note: query parameter values\n * default to a special `\"auto\"` mode.\n *\n * For query parameters in `\"auto\"` mode, if multiple values for a single parameter\n * are present in the URL (e.g.: `/foo?bar=1&bar=2&bar=3`) then the values\n * are mapped to an array (e.g.: `{ foo: [ '1', '2', '3' ] }`). However, if\n * only one value is present (e.g.: `/foo?bar=1`) then the value is treated as single\n * value (e.g.: `{ foo: '1' }`).\n *\n *
params: {\n   *     param1: { array: true }\n   * }
\n *\n * - ** squash ** - {bool|string=}: `squash` configures how a default parameter value is represented in the URL when\n * the current parameter value is the same as the default value. If `squash` is not set, it uses the\n * configured default squash policy.\n * (See {@link ui.router.util.$urlMatcherFactory#methods_defaultSquashPolicy `defaultSquashPolicy()`})\n *\n * There are three squash settings:\n *\n * - false: The parameter's default value is not squashed. It is encoded and included in the URL\n * - true: The parameter's default value is omitted from the URL. If the parameter is preceeded and followed\n * by slashes in the state's `url` declaration, then one of those slashes are omitted.\n * This can allow for cleaner looking URLs.\n * - `\"\"`: The parameter's default value is replaced with an arbitrary placeholder of your choice.\n *\n *
params: {\n   *     param1: {\n   *       value: \"defaultId\",\n   *       squash: true\n   * } }\n   * // squash \"defaultValue\" to \"~\"\n   * params: {\n   *     param1: {\n   *       value: \"defaultValue\",\n   *       squash: \"~\"\n   * } }\n   * 
\n *\n *\n * @example\n *
\n   * // Some state name examples\n   *\n   * // stateName can be a single top-level name (must be unique).\n   * $stateProvider.state(\"home\", {});\n   *\n   * // Or it can be a nested state name. This state is a child of the\n   * // above \"home\" state.\n   * $stateProvider.state(\"home.newest\", {});\n   *\n   * // Nest states as deeply as needed.\n   * $stateProvider.state(\"home.newest.abc.xyz.inception\", {});\n   *\n   * // state() returns $stateProvider, so you can chain state declarations.\n   * $stateProvider\n   *   .state(\"home\", {})\n   *   .state(\"about\", {})\n   *   .state(\"contacts\", {});\n   * 
\n *\n */\n this.state = state;\n function state(name, definition) {\n /*jshint validthis: true */\n if (isObject(name)) definition = name;\n else definition.name = name;\n registerState(definition);\n return this;\n }\n\n /**\n * @ngdoc object\n * @name ui.router.state.$state\n *\n * @requires $rootScope\n * @requires $q\n * @requires ui.router.state.$view\n * @requires $injector\n * @requires ui.router.util.$resolve\n * @requires ui.router.state.$stateParams\n * @requires ui.router.router.$urlRouter\n *\n * @property {object} params A param object, e.g. {sectionId: section.id)}, that \n * you'd like to test against the current active state.\n * @property {object} current A reference to the state's config object. However \n * you passed it in. Useful for accessing custom data.\n * @property {object} transition Currently pending transition. A promise that'll \n * resolve or reject.\n *\n * @description\n * `$state` service is responsible for representing states as well as transitioning\n * between them. It also provides interfaces to ask for current state or even states\n * you're coming from.\n */\n this.$get = $get;\n $get.$inject = ['$rootScope', '$q', '$view', '$injector', '$resolve', '$stateParams', '$urlRouter', '$location', '$urlMatcherFactory'];\n function $get( $rootScope, $q, $view, $injector, $resolve, $stateParams, $urlRouter, $location, $urlMatcherFactory) {\n\n var TransitionSuperseded = $q.reject(new Error('transition superseded'));\n var TransitionPrevented = $q.reject(new Error('transition prevented'));\n var TransitionAborted = $q.reject(new Error('transition aborted'));\n var TransitionFailed = $q.reject(new Error('transition failed'));\n\n // Handles the case where a state which is the target of a transition is not found, and the user\n // can optionally retry or defer the transition\n function handleRedirect(redirect, state, params, options) {\n /**\n * @ngdoc event\n * @name ui.router.state.$state#$stateNotFound\n * @eventOf ui.router.state.$state\n * @eventType broadcast on root scope\n * @description\n * Fired when a requested state **cannot be found** using the provided state name during transition.\n * The event is broadcast allowing any handlers a single chance to deal with the error (usually by\n * lazy-loading the unfound state). A special `unfoundState` object is passed to the listener handler,\n * you can see its three properties in the example. You can use `event.preventDefault()` to abort the\n * transition and the promise returned from `go` will be rejected with a `'transition aborted'` value.\n *\n * @param {Object} event Event object.\n * @param {Object} unfoundState Unfound State information. Contains: `to, toParams, options` properties.\n * @param {State} fromState Current state object.\n * @param {Object} fromParams Current state params.\n *\n * @example\n *\n *
\n       * // somewhere, assume lazy.state has not been defined\n       * $state.go(\"lazy.state\", {a:1, b:2}, {inherit:false});\n       *\n       * // somewhere else\n       * $scope.$on('$stateNotFound',\n       * function(event, unfoundState, fromState, fromParams){\n       *     console.log(unfoundState.to); // \"lazy.state\"\n       *     console.log(unfoundState.toParams); // {a:1, b:2}\n       *     console.log(unfoundState.options); // {inherit:false} + default options\n       * })\n       * 
\n */\n var evt = $rootScope.$broadcast('$stateNotFound', redirect, state, params);\n\n if (evt.defaultPrevented) {\n $urlRouter.update();\n return TransitionAborted;\n }\n\n if (!evt.retry) {\n return null;\n }\n\n // Allow the handler to return a promise to defer state lookup retry\n if (options.$retry) {\n $urlRouter.update();\n return TransitionFailed;\n }\n var retryTransition = $state.transition = $q.when(evt.retry);\n\n retryTransition.then(function() {\n if (retryTransition !== $state.transition) return TransitionSuperseded;\n redirect.options.$retry = true;\n return $state.transitionTo(redirect.to, redirect.toParams, redirect.options);\n }, function() {\n return TransitionAborted;\n });\n $urlRouter.update();\n\n return retryTransition;\n }\n\n root.locals = { resolve: null, globals: { $stateParams: {} } };\n\n $state = {\n params: {},\n current: root.self,\n $current: root,\n transition: null\n };\n\n /**\n * @ngdoc function\n * @name ui.router.state.$state#reload\n * @methodOf ui.router.state.$state\n *\n * @description\n * A method that force reloads the current state. All resolves are re-resolved, events are not re-fired, \n * and controllers reinstantiated (bug with controllers reinstantiating right now, fixing soon).\n *\n * @example\n *
\n     * var app angular.module('app', ['ui.router']);\n     *\n     * app.controller('ctrl', function ($scope, $state) {\n     *   $scope.reload = function(){\n     *     $state.reload();\n     *   }\n     * });\n     * 
\n *\n * `reload()` is just an alias for:\n *
\n     * $state.transitionTo($state.current, $stateParams, { \n     *   reload: true, inherit: false, notify: true\n     * });\n     * 
\n *\n * @returns {promise} A promise representing the state of the new transition. See\n * {@link ui.router.state.$state#methods_go $state.go}.\n */\n $state.reload = function reload() {\n return $state.transitionTo($state.current, $stateParams, { reload: true, inherit: false, notify: true });\n };\n\n /**\n * @ngdoc function\n * @name ui.router.state.$state#go\n * @methodOf ui.router.state.$state\n *\n * @description\n * Convenience method for transitioning to a new state. `$state.go` calls \n * `$state.transitionTo` internally but automatically sets options to \n * `{ location: true, inherit: true, relative: $state.$current, notify: true }`. \n * This allows you to easily use an absolute or relative to path and specify \n * only the parameters you'd like to update (while letting unspecified parameters \n * inherit from the currently active ancestor states).\n *\n * @example\n *
\n     * var app = angular.module('app', ['ui.router']);\n     *\n     * app.controller('ctrl', function ($scope, $state) {\n     *   $scope.changeState = function () {\n     *     $state.go('contact.detail');\n     *   };\n     * });\n     * 
\n * \n *\n * @param {string} to Absolute state name or relative state path. Some examples:\n *\n * - `$state.go('contact.detail')` - will go to the `contact.detail` state\n * - `$state.go('^')` - will go to a parent state\n * - `$state.go('^.sibling')` - will go to a sibling state\n * - `$state.go('.child.grandchild')` - will go to grandchild state\n *\n * @param {object=} params A map of the parameters that will be sent to the state, \n * will populate $stateParams. Any parameters that are not specified will be inherited from currently \n * defined parameters. This allows, for example, going to a sibling state that shares parameters\n * specified in a parent state. Parameter inheritance only works between common ancestor states, I.e.\n * transitioning to a sibling will get you the parameters for all parents, transitioning to a child\n * will get you all current parameters, etc.\n * @param {object=} options Options object. The options are:\n *\n * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false`\n * will not. If string, must be `\"replace\"`, which will update url and also replace last history record.\n * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url.\n * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), \n * defines which state to be relative from.\n * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events.\n * - **`reload`** (v0.2.5) - {boolean=false}, If `true` will force transition even if the state or params \n * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd\n * use this when you want to force a reload when *everything* is the same, including search params.\n *\n * @returns {promise} A promise representing the state of the new transition.\n *\n * Possible success values:\n *\n * - $state.current\n *\n *
Possible rejection values:\n *\n * - 'transition superseded' - when a newer transition has been started after this one\n * - 'transition prevented' - when `event.preventDefault()` has been called in a `$stateChangeStart` listener\n * - 'transition aborted' - when `event.preventDefault()` has been called in a `$stateNotFound` listener or\n * when a `$stateNotFound` `event.retry` promise errors.\n * - 'transition failed' - when a state has been unsuccessfully found after 2 tries.\n * - *resolve error* - when an error has occurred with a `resolve`\n *\n */\n $state.go = function go(to, params, options) {\n return $state.transitionTo(to, params, extend({ inherit: true, relative: $state.$current }, options));\n };\n\n /**\n * @ngdoc function\n * @name ui.router.state.$state#transitionTo\n * @methodOf ui.router.state.$state\n *\n * @description\n * Low-level method for transitioning to a new state. {@link ui.router.state.$state#methods_go $state.go}\n * uses `transitionTo` internally. `$state.go` is recommended in most situations.\n *\n * @example\n *
\n     * var app = angular.module('app', ['ui.router']);\n     *\n     * app.controller('ctrl', function ($scope, $state) {\n     *   $scope.changeState = function () {\n     *     $state.transitionTo('contact.detail');\n     *   };\n     * });\n     * 
\n *\n * @param {string} to State name.\n * @param {object=} toParams A map of the parameters that will be sent to the state,\n * will populate $stateParams.\n * @param {object=} options Options object. The options are:\n *\n * - **`location`** - {boolean=true|string=} - If `true` will update the url in the location bar, if `false`\n * will not. If string, must be `\"replace\"`, which will update url and also replace last history record.\n * - **`inherit`** - {boolean=false}, If `true` will inherit url parameters from current url.\n * - **`relative`** - {object=}, When transitioning with relative path (e.g '^'), \n * defines which state to be relative from.\n * - **`notify`** - {boolean=true}, If `true` will broadcast $stateChangeStart and $stateChangeSuccess events.\n * - **`reload`** (v0.2.5) - {boolean=false}, If `true` will force transition even if the state or params \n * have not changed, aka a reload of the same state. It differs from reloadOnSearch because you'd\n * use this when you want to force a reload when *everything* is the same, including search params.\n *\n * @returns {promise} A promise representing the state of the new transition. See\n * {@link ui.router.state.$state#methods_go $state.go}.\n */\n $state.transitionTo = function transitionTo(to, toParams, options) {\n toParams = toParams || {};\n options = extend({\n location: true, inherit: false, relative: null, notify: true, reload: false, $retry: false\n }, options || {});\n\n var from = $state.$current, fromParams = $state.params, fromPath = from.path;\n var evt, toState = findState(to, options.relative);\n\n if (!isDefined(toState)) {\n var redirect = { to: to, toParams: toParams, options: options };\n var redirectResult = handleRedirect(redirect, from.self, fromParams, options);\n\n if (redirectResult) {\n return redirectResult;\n }\n\n // Always retry once if the $stateNotFound was not prevented\n // (handles either redirect changed or state lazy-definition)\n to = redirect.to;\n toParams = redirect.toParams;\n options = redirect.options;\n toState = findState(to, options.relative);\n\n if (!isDefined(toState)) {\n if (!options.relative) throw new Error(\"No such state '\" + to + \"'\");\n throw new Error(\"Could not resolve '\" + to + \"' from state '\" + options.relative + \"'\");\n }\n }\n if (toState[abstractKey]) throw new Error(\"Cannot transition to abstract state '\" + to + \"'\");\n if (options.inherit) toParams = inheritParams($stateParams, toParams || {}, $state.$current, toState);\n if (!toState.params.$$validates(toParams)) return TransitionFailed;\n\n toParams = toState.params.$$values(toParams);\n to = toState;\n\n var toPath = to.path;\n\n // Starting from the root of the path, keep all levels that haven't changed\n var keep = 0, state = toPath[keep], locals = root.locals, toLocals = [];\n\n if (!options.reload) {\n while (state && state === fromPath[keep] && state.ownParams.$$equals(toParams, fromParams)) {\n locals = toLocals[keep] = state.locals;\n keep++;\n state = toPath[keep];\n }\n }\n\n // If we're going to the same state and all locals are kept, we've got nothing to do.\n // But clear 'transition', as we still want to cancel any other pending transitions.\n // TODO: We may not want to bump 'transition' if we're called from a location change\n // that we've initiated ourselves, because we might accidentally abort a legitimate\n // transition initiated from code?\n if (shouldTriggerReload(to, from, locals, options)) {\n if (to.self.reloadOnSearch !== false) $urlRouter.update();\n $state.transition = null;\n return $q.when($state.current);\n }\n\n // Filter parameters before we pass them to event handlers etc.\n toParams = filterByKeys(to.params.$$keys(), toParams || {});\n\n // Broadcast start event and cancel the transition if requested\n if (options.notify) {\n /**\n * @ngdoc event\n * @name ui.router.state.$state#$stateChangeStart\n * @eventOf ui.router.state.$state\n * @eventType broadcast on root scope\n * @description\n * Fired when the state transition **begins**. You can use `event.preventDefault()`\n * to prevent the transition from happening and then the transition promise will be\n * rejected with a `'transition prevented'` value.\n *\n * @param {Object} event Event object.\n * @param {State} toState The state being transitioned to.\n * @param {Object} toParams The params supplied to the `toState`.\n * @param {State} fromState The current state, pre-transition.\n * @param {Object} fromParams The params supplied to the `fromState`.\n *\n * @example\n *\n *
\n         * $rootScope.$on('$stateChangeStart',\n         * function(event, toState, toParams, fromState, fromParams){\n         *     event.preventDefault();\n         *     // transitionTo() promise will be rejected with\n         *     // a 'transition prevented' error\n         * })\n         * 
\n */\n if ($rootScope.$broadcast('$stateChangeStart', to.self, toParams, from.self, fromParams).defaultPrevented) {\n $urlRouter.update();\n return TransitionPrevented;\n }\n }\n\n // Resolve locals for the remaining states, but don't update any global state just\n // yet -- if anything fails to resolve the current state needs to remain untouched.\n // We also set up an inheritance chain for the locals here. This allows the view directive\n // to quickly look up the correct definition for each view in the current state. Even\n // though we create the locals object itself outside resolveState(), it is initially\n // empty and gets filled asynchronously. We need to keep track of the promise for the\n // (fully resolved) current locals, and pass this down the chain.\n var resolved = $q.when(locals);\n\n for (var l = keep; l < toPath.length; l++, state = toPath[l]) {\n locals = toLocals[l] = inherit(locals);\n resolved = resolveState(state, toParams, state === to, resolved, locals, options);\n }\n\n // Once everything is resolved, we are ready to perform the actual transition\n // and return a promise for the new state. We also keep track of what the\n // current promise is, so that we can detect overlapping transitions and\n // keep only the outcome of the last transition.\n var transition = $state.transition = resolved.then(function () {\n var l, entering, exiting;\n\n if ($state.transition !== transition) return TransitionSuperseded;\n\n // Exit 'from' states not kept\n for (l = fromPath.length - 1; l >= keep; l--) {\n exiting = fromPath[l];\n if (exiting.self.onExit) {\n $injector.invoke(exiting.self.onExit, exiting.self, exiting.locals.globals);\n }\n exiting.locals = null;\n }\n\n // Enter 'to' states not kept\n for (l = keep; l < toPath.length; l++) {\n entering = toPath[l];\n entering.locals = toLocals[l];\n if (entering.self.onEnter) {\n $injector.invoke(entering.self.onEnter, entering.self, entering.locals.globals);\n }\n }\n\n // Run it again, to catch any transitions in callbacks\n if ($state.transition !== transition) return TransitionSuperseded;\n\n // Update globals in $state\n $state.$current = to;\n $state.current = to.self;\n $state.params = toParams;\n copy($state.params, $stateParams);\n $state.transition = null;\n\n if (options.location && to.navigable) {\n $urlRouter.push(to.navigable.url, to.navigable.locals.globals.$stateParams, {\n $$avoidResync: true, replace: options.location === 'replace'\n });\n }\n\n if (options.notify) {\n /**\n * @ngdoc event\n * @name ui.router.state.$state#$stateChangeSuccess\n * @eventOf ui.router.state.$state\n * @eventType broadcast on root scope\n * @description\n * Fired once the state transition is **complete**.\n *\n * @param {Object} event Event object.\n * @param {State} toState The state being transitioned to.\n * @param {Object} toParams The params supplied to the `toState`.\n * @param {State} fromState The current state, pre-transition.\n * @param {Object} fromParams The params supplied to the `fromState`.\n */\n $rootScope.$broadcast('$stateChangeSuccess', to.self, toParams, from.self, fromParams);\n }\n $urlRouter.update(true);\n\n return $state.current;\n }, function (error) {\n if ($state.transition !== transition) return TransitionSuperseded;\n\n $state.transition = null;\n /**\n * @ngdoc event\n * @name ui.router.state.$state#$stateChangeError\n * @eventOf ui.router.state.$state\n * @eventType broadcast on root scope\n * @description\n * Fired when an **error occurs** during transition. It's important to note that if you\n * have any errors in your resolve functions (javascript errors, non-existent services, etc)\n * they will not throw traditionally. You must listen for this $stateChangeError event to\n * catch **ALL** errors.\n *\n * @param {Object} event Event object.\n * @param {State} toState The state being transitioned to.\n * @param {Object} toParams The params supplied to the `toState`.\n * @param {State} fromState The current state, pre-transition.\n * @param {Object} fromParams The params supplied to the `fromState`.\n * @param {Error} error The resolve error object.\n */\n evt = $rootScope.$broadcast('$stateChangeError', to.self, toParams, from.self, fromParams, error);\n\n if (!evt.defaultPrevented) {\n $urlRouter.update();\n }\n\n return $q.reject(error);\n });\n\n return transition;\n };\n\n /**\n * @ngdoc function\n * @name ui.router.state.$state#is\n * @methodOf ui.router.state.$state\n *\n * @description\n * Similar to {@link ui.router.state.$state#methods_includes $state.includes},\n * but only checks for the full state name. If params is supplied then it will be\n * tested for strict equality against the current active params object, so all params\n * must match with none missing and no extras.\n *\n * @example\n *
\n     * $state.$current.name = 'contacts.details.item';\n     *\n     * // absolute name\n     * $state.is('contact.details.item'); // returns true\n     * $state.is(contactDetailItemStateObject); // returns true\n     *\n     * // relative name (. and ^), typically from a template\n     * // E.g. from the 'contacts.details' template\n     * 
Item
\n *
\n *\n * @param {string|object} stateOrName The state name (absolute or relative) or state object you'd like to check.\n * @param {object=} params A param object, e.g. `{sectionId: section.id}`, that you'd like\n * to test against the current active state.\n * @param {object=} options An options object. The options are:\n *\n * - **`relative`** - {string|object} - If `stateOrName` is a relative state name and `options.relative` is set, .is will\n * test relative to `options.relative` state (or name).\n *\n * @returns {boolean} Returns true if it is the state.\n */\n $state.is = function is(stateOrName, params, options) {\n options = extend({ relative: $state.$current }, options || {});\n var state = findState(stateOrName, options.relative);\n\n if (!isDefined(state)) { return undefined; }\n if ($state.$current !== state) { return false; }\n return params ? equalForKeys(state.params.$$values(params), $stateParams) : true;\n };\n\n /**\n * @ngdoc function\n * @name ui.router.state.$state#includes\n * @methodOf ui.router.state.$state\n *\n * @description\n * A method to determine if the current active state is equal to or is the child of the\n * state stateName. If any params are passed then they will be tested for a match as well.\n * Not all the parameters need to be passed, just the ones you'd like to test for equality.\n *\n * @example\n * Partial and relative names\n *
\n     * $state.$current.name = 'contacts.details.item';\n     *\n     * // Using partial names\n     * $state.includes(\"contacts\"); // returns true\n     * $state.includes(\"contacts.details\"); // returns true\n     * $state.includes(\"contacts.details.item\"); // returns true\n     * $state.includes(\"contacts.list\"); // returns false\n     * $state.includes(\"about\"); // returns false\n     *\n     * // Using relative names (. and ^), typically from a template\n     * // E.g. from the 'contacts.details' template\n     * 
Item
\n *
\n *\n * Basic globbing patterns\n *
\n     * $state.$current.name = 'contacts.details.item.url';\n     *\n     * $state.includes(\"*.details.*.*\"); // returns true\n     * $state.includes(\"*.details.**\"); // returns true\n     * $state.includes(\"**.item.**\"); // returns true\n     * $state.includes(\"*.details.item.url\"); // returns true\n     * $state.includes(\"*.details.*.url\"); // returns true\n     * $state.includes(\"*.details.*\"); // returns false\n     * $state.includes(\"item.**\"); // returns false\n     * 
\n *\n * @param {string} stateOrName A partial name, relative name, or glob pattern\n * to be searched for within the current state name.\n * @param {object=} params A param object, e.g. `{sectionId: section.id}`,\n * that you'd like to test against the current active state.\n * @param {object=} options An options object. The options are:\n *\n * - **`relative`** - {string|object=} - If `stateOrName` is a relative state reference and `options.relative` is set,\n * .includes will test relative to `options.relative` state (or name).\n *\n * @returns {boolean} Returns true if it does include the state\n */\n $state.includes = function includes(stateOrName, params, options) {\n options = extend({ relative: $state.$current }, options || {});\n if (isString(stateOrName) && isGlob(stateOrName)) {\n if (!doesStateMatchGlob(stateOrName)) {\n return false;\n }\n stateOrName = $state.$current.name;\n }\n\n var state = findState(stateOrName, options.relative);\n if (!isDefined(state)) { return undefined; }\n if (!isDefined($state.$current.includes[state.name])) { return false; }\n return params ? equalForKeys(state.params.$$values(params), $stateParams, objectKeys(params)) : true;\n };\n\n\n /**\n * @ngdoc function\n * @name ui.router.state.$state#href\n * @methodOf ui.router.state.$state\n *\n * @description\n * A url generation method that returns the compiled url for the given state populated with the given params.\n *\n * @example\n *
\n     * expect($state.href(\"about.person\", { person: \"bob\" })).toEqual(\"/about/bob\");\n     * 
\n *\n * @param {string|object} stateOrName The state name or state object you'd like to generate a url from.\n * @param {object=} params An object of parameter values to fill the state's required parameters.\n * @param {object=} options Options object. The options are:\n *\n * - **`lossy`** - {boolean=true} - If true, and if there is no url associated with the state provided in the\n * first parameter, then the constructed href url will be built from the first navigable ancestor (aka\n * ancestor with a valid url).\n * - **`inherit`** - {boolean=true}, If `true` will inherit url parameters from current url.\n * - **`relative`** - {object=$state.$current}, When transitioning with relative path (e.g '^'), \n * defines which state to be relative from.\n * - **`absolute`** - {boolean=false}, If true will generate an absolute url, e.g. \"http://www.example.com/fullurl\".\n * \n * @returns {string} compiled state url\n */\n $state.href = function href(stateOrName, params, options) {\n options = extend({\n lossy: true,\n inherit: true,\n absolute: false,\n relative: $state.$current\n }, options || {});\n\n var state = findState(stateOrName, options.relative);\n\n if (!isDefined(state)) return null;\n if (options.inherit) params = inheritParams($stateParams, params || {}, $state.$current, state);\n \n var nav = (state && options.lossy) ? state.navigable : state;\n\n if (!nav || nav.url === undefined || nav.url === null) {\n return null;\n }\n return $urlRouter.href(nav.url, filterByKeys(state.params.$$keys(), params || {}), {\n absolute: options.absolute\n });\n };\n\n /**\n * @ngdoc function\n * @name ui.router.state.$state#get\n * @methodOf ui.router.state.$state\n *\n * @description\n * Returns the state configuration object for any specific state or all states.\n *\n * @param {string|object=} stateOrName (absolute or relative) If provided, will only get the config for\n * the requested state. If not provided, returns an array of ALL state configs.\n * @param {string|object=} context When stateOrName is a relative state reference, the state will be retrieved relative to context.\n * @returns {Object|Array} State configuration object or array of all objects.\n */\n $state.get = function (stateOrName, context) {\n if (arguments.length === 0) return map(objectKeys(states), function(name) { return states[name].self; });\n var state = findState(stateOrName, context || $state.$current);\n return (state && state.self) ? state.self : null;\n };\n\n function resolveState(state, params, paramsAreFiltered, inherited, dst, options) {\n // Make a restricted $stateParams with only the parameters that apply to this state if\n // necessary. In addition to being available to the controller and onEnter/onExit callbacks,\n // we also need $stateParams to be available for any $injector calls we make during the\n // dependency resolution process.\n var $stateParams = (paramsAreFiltered) ? params : filterByKeys(state.params.$$keys(), params);\n var locals = { $stateParams: $stateParams };\n\n // Resolve 'global' dependencies for the state, i.e. those not specific to a view.\n // We're also including $stateParams in this; that way the parameters are restricted\n // to the set that should be visible to the state, and are independent of when we update\n // the global $state and $stateParams values.\n dst.resolve = $resolve.resolve(state.resolve, locals, dst.resolve, state);\n var promises = [dst.resolve.then(function (globals) {\n dst.globals = globals;\n })];\n if (inherited) promises.push(inherited);\n\n // Resolve template and dependencies for all views.\n forEach(state.views, function (view, name) {\n var injectables = (view.resolve && view.resolve !== state.resolve ? view.resolve : {});\n injectables.$template = [ function () {\n return $view.load(name, { view: view, locals: locals, params: $stateParams, notify: options.notify }) || '';\n }];\n\n promises.push($resolve.resolve(injectables, locals, dst.resolve, state).then(function (result) {\n // References to the controller (only instantiated at link time)\n if (isFunction(view.controllerProvider) || isArray(view.controllerProvider)) {\n var injectLocals = angular.extend({}, injectables, locals);\n result.$$controller = $injector.invoke(view.controllerProvider, null, injectLocals);\n } else {\n result.$$controller = view.controller;\n }\n // Provide access to the state itself for internal use\n result.$$state = state;\n result.$$controllerAs = view.controllerAs;\n dst[name] = result;\n }));\n });\n\n // Wait for all the promises and then return the activation object\n return $q.all(promises).then(function (values) {\n return dst;\n });\n }\n\n return $state;\n }\n\n function shouldTriggerReload(to, from, locals, options) {\n if (to === from && ((locals === from.locals && !options.reload) || (to.self.reloadOnSearch === false))) {\n return true;\n }\n }\n}\n\nangular.module('ui.router.state')\n .value('$stateParams', {})\n .provider('$state', $StateProvider);\n\n\n$ViewProvider.$inject = [];\nfunction $ViewProvider() {\n\n this.$get = $get;\n /**\n * @ngdoc object\n * @name ui.router.state.$view\n *\n * @requires ui.router.util.$templateFactory\n * @requires $rootScope\n *\n * @description\n *\n */\n $get.$inject = ['$rootScope', '$templateFactory'];\n function $get( $rootScope, $templateFactory) {\n return {\n // $view.load('full.viewName', { template: ..., controller: ..., resolve: ..., async: false, params: ... })\n /**\n * @ngdoc function\n * @name ui.router.state.$view#load\n * @methodOf ui.router.state.$view\n *\n * @description\n *\n * @param {string} name name\n * @param {object} options option object.\n */\n load: function load(name, options) {\n var result, defaults = {\n template: null, controller: null, view: null, locals: null, notify: true, async: true, params: {}\n };\n options = extend(defaults, options);\n\n if (options.view) {\n result = $templateFactory.fromConfig(options.view, options.params, options.locals);\n }\n if (result && options.notify) {\n /**\n * @ngdoc event\n * @name ui.router.state.$state#$viewContentLoading\n * @eventOf ui.router.state.$view\n * @eventType broadcast on root scope\n * @description\n *\n * Fired once the view **begins loading**, *before* the DOM is rendered.\n *\n * @param {Object} event Event object.\n * @param {Object} viewConfig The view config properties (template, controller, etc).\n *\n * @example\n *\n *
\n         * $scope.$on('$viewContentLoading',\n         * function(event, viewConfig){\n         *     // Access to all the view config properties.\n         *     // and one special property 'targetView'\n         *     // viewConfig.targetView\n         * });\n         * 
\n */\n $rootScope.$broadcast('$viewContentLoading', options);\n }\n return result;\n }\n };\n }\n}\n\nangular.module('ui.router.state').provider('$view', $ViewProvider);\n\n/**\n * @ngdoc object\n * @name ui.router.state.$uiViewScrollProvider\n *\n * @description\n * Provider that returns the {@link ui.router.state.$uiViewScroll} service function.\n */\nfunction $ViewScrollProvider() {\n\n var useAnchorScroll = false;\n\n /**\n * @ngdoc function\n * @name ui.router.state.$uiViewScrollProvider#useAnchorScroll\n * @methodOf ui.router.state.$uiViewScrollProvider\n *\n * @description\n * Reverts back to using the core [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll) service for\n * scrolling based on the url anchor.\n */\n this.useAnchorScroll = function () {\n useAnchorScroll = true;\n };\n\n /**\n * @ngdoc object\n * @name ui.router.state.$uiViewScroll\n *\n * @requires $anchorScroll\n * @requires $timeout\n *\n * @description\n * When called with a jqLite element, it scrolls the element into view (after a\n * `$timeout` so the DOM has time to refresh).\n *\n * If you prefer to rely on `$anchorScroll` to scroll the view to the anchor,\n * this can be enabled by calling {@link ui.router.state.$uiViewScrollProvider#methods_useAnchorScroll `$uiViewScrollProvider.useAnchorScroll()`}.\n */\n this.$get = ['$anchorScroll', '$timeout', function ($anchorScroll, $timeout) {\n if (useAnchorScroll) {\n return $anchorScroll;\n }\n\n return function ($element) {\n $timeout(function () {\n $element[0].scrollIntoView();\n }, 0, false);\n };\n }];\n}\n\nangular.module('ui.router.state').provider('$uiViewScroll', $ViewScrollProvider);\n\n/**\n * @ngdoc directive\n * @name ui.router.state.directive:ui-view\n *\n * @requires ui.router.state.$state\n * @requires $compile\n * @requires $controller\n * @requires $injector\n * @requires ui.router.state.$uiViewScroll\n * @requires $document\n *\n * @restrict ECA\n *\n * @description\n * The ui-view directive tells $state where to place your templates.\n *\n * @param {string=} name A view name. The name should be unique amongst the other views in the\n * same state. You can have views of the same name that live in different states.\n *\n * @param {string=} autoscroll It allows you to set the scroll behavior of the browser window\n * when a view is populated. By default, $anchorScroll is overridden by ui-router's custom scroll\n * service, {@link ui.router.state.$uiViewScroll}. This custom service let's you\n * scroll ui-view elements into view when they are populated during a state activation.\n *\n * *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll)\n * functionality, call `$uiViewScrollProvider.useAnchorScroll()`.*\n *\n * @param {string=} onload Expression to evaluate whenever the view updates.\n * \n * @example\n * A view can be unnamed or named. \n *
\n * \n * 
\n * \n * \n *
\n *
\n *\n * You can only have one unnamed view within any template (or root html). If you are only using a \n * single view and it is unnamed then you can populate it like so:\n *
\n * 
\n * $stateProvider.state(\"home\", {\n * template: \"

HELLO!

\"\n * })\n *
\n * \n * The above is a convenient shortcut equivalent to specifying your view explicitly with the {@link ui.router.state.$stateProvider#views `views`}\n * config property, by name, in this case an empty name:\n *
\n * $stateProvider.state(\"home\", {\n *   views: {\n *     \"\": {\n *       template: \"

HELLO!

\"\n * }\n * } \n * })\n *
\n * \n * But typically you'll only use the views property if you name your view or have more than one view \n * in the same template. There's not really a compelling reason to name a view if its the only one, \n * but you could if you wanted, like so:\n *
\n * 
\n *
\n *
\n * $stateProvider.state(\"home\", {\n *   views: {\n *     \"main\": {\n *       template: \"

HELLO!

\"\n * }\n * } \n * })\n *
\n * \n * Really though, you'll use views to set up multiple views:\n *
\n * 
\n *
\n *
\n *
\n * \n *
\n * $stateProvider.state(\"home\", {\n *   views: {\n *     \"\": {\n *       template: \"

HELLO!

\"\n * },\n * \"chart\": {\n * template: \"\"\n * },\n * \"data\": {\n * template: \"\"\n * }\n * } \n * })\n *
\n *\n * Examples for `autoscroll`:\n *\n *
\n * \n * \n *\n * \n * \n * \n * \n * 
\n */\n$ViewDirective.$inject = ['$state', '$injector', '$uiViewScroll', '$interpolate'];\nfunction $ViewDirective( $state, $injector, $uiViewScroll, $interpolate) {\n\n function getService() {\n return ($injector.has) ? function(service) {\n return $injector.has(service) ? $injector.get(service) : null;\n } : function(service) {\n try {\n return $injector.get(service);\n } catch (e) {\n return null;\n }\n };\n }\n\n var service = getService(),\n $animator = service('$animator'),\n $animate = service('$animate');\n\n // Returns a set of DOM manipulation functions based on which Angular version\n // it should use\n function getRenderer(attrs, scope) {\n var statics = function() {\n return {\n enter: function (element, target, cb) { target.after(element); cb(); },\n leave: function (element, cb) { element.remove(); cb(); }\n };\n };\n\n if ($animate) {\n return {\n enter: function(element, target, cb) {\n var promise = $animate.enter(element, null, target, cb);\n if (promise && promise.then) promise.then(cb);\n },\n leave: function(element, cb) {\n var promise = $animate.leave(element, cb);\n if (promise && promise.then) promise.then(cb);\n }\n };\n }\n\n if ($animator) {\n var animate = $animator && $animator(scope, attrs);\n\n return {\n enter: function(element, target, cb) {animate.enter(element, null, target); cb(); },\n leave: function(element, cb) { animate.leave(element); cb(); }\n };\n }\n\n return statics();\n }\n\n var directive = {\n restrict: 'ECA',\n terminal: true,\n priority: 400,\n transclude: 'element',\n compile: function (tElement, tAttrs, $transclude) {\n return function (scope, $element, attrs) {\n var previousEl, currentEl, currentScope, latestLocals,\n onloadExp = attrs.onload || '',\n autoScrollExp = attrs.autoscroll,\n renderer = getRenderer(attrs, scope);\n\n scope.$on('$stateChangeSuccess', function() {\n updateView(false);\n });\n scope.$on('$viewContentLoading', function() {\n updateView(false);\n });\n\n updateView(true);\n\n function cleanupLastView() {\n if (previousEl) {\n previousEl.remove();\n previousEl = null;\n }\n\n if (currentScope) {\n currentScope.$destroy();\n currentScope = null;\n }\n\n if (currentEl) {\n renderer.leave(currentEl, function() {\n previousEl = null;\n });\n\n previousEl = currentEl;\n currentEl = null;\n }\n }\n\n function updateView(firstTime) {\n var newScope,\n name = getUiViewName(scope, attrs, $element, $interpolate),\n previousLocals = name && $state.$current && $state.$current.locals[name];\n\n if (!firstTime && previousLocals === latestLocals) return; // nothing to do\n newScope = scope.$new();\n latestLocals = $state.$current.locals[name];\n\n var clone = $transclude(newScope, function(clone) {\n renderer.enter(clone, $element, function onUiViewEnter() {\n if(currentScope) {\n currentScope.$emit('$viewContentAnimationEnded');\n }\n\n if (angular.isDefined(autoScrollExp) && !autoScrollExp || scope.$eval(autoScrollExp)) {\n $uiViewScroll(clone);\n }\n });\n cleanupLastView();\n });\n\n currentEl = clone;\n currentScope = newScope;\n /**\n * @ngdoc event\n * @name ui.router.state.directive:ui-view#$viewContentLoaded\n * @eventOf ui.router.state.directive:ui-view\n * @eventType emits on ui-view directive scope\n * @description *\n * Fired once the view is **loaded**, *after* the DOM is rendered.\n *\n * @param {Object} event Event object.\n */\n currentScope.$emit('$viewContentLoaded');\n currentScope.$eval(onloadExp);\n }\n };\n }\n };\n\n return directive;\n}\n\n$ViewDirectiveFill.$inject = ['$compile', '$controller', '$state', '$interpolate'];\nfunction $ViewDirectiveFill ( $compile, $controller, $state, $interpolate) {\n return {\n restrict: 'ECA',\n priority: -400,\n compile: function (tElement) {\n var initial = tElement.html();\n return function (scope, $element, attrs) {\n var current = $state.$current,\n name = getUiViewName(scope, attrs, $element, $interpolate),\n locals = current && current.locals[name];\n\n if (! locals) {\n return;\n }\n\n $element.data('$uiView', { name: name, state: locals.$$state });\n $element.html(locals.$template ? locals.$template : initial);\n\n var link = $compile($element.contents());\n\n if (locals.$$controller) {\n locals.$scope = scope;\n var controller = $controller(locals.$$controller, locals);\n if (locals.$$controllerAs) {\n scope[locals.$$controllerAs] = controller;\n }\n $element.data('$ngControllerController', controller);\n $element.children().data('$ngControllerController', controller);\n }\n\n link(scope);\n };\n }\n };\n}\n\n/**\n * Shared ui-view code for both directives:\n * Given scope, element, and its attributes, return the view's name\n */\nfunction getUiViewName(scope, attrs, element, $interpolate) {\n var name = $interpolate(attrs.uiView || attrs.name || '')(scope);\n var inherited = element.inheritedData('$uiView');\n return name.indexOf('@') >= 0 ? name : (name + '@' + (inherited ? inherited.state.name : ''));\n}\n\nangular.module('ui.router.state').directive('uiView', $ViewDirective);\nangular.module('ui.router.state').directive('uiView', $ViewDirectiveFill);\n\nfunction parseStateRef(ref, current) {\n var preparsed = ref.match(/^\\s*({[^}]*})\\s*$/), parsed;\n if (preparsed) ref = current + '(' + preparsed[1] + ')';\n parsed = ref.replace(/\\n/g, \" \").match(/^([^(]+?)\\s*(\\((.*)\\))?$/);\n if (!parsed || parsed.length !== 4) throw new Error(\"Invalid state ref '\" + ref + \"'\");\n return { state: parsed[1], paramExpr: parsed[3] || null };\n}\n\nfunction stateContext(el) {\n var stateData = el.parent().inheritedData('$uiView');\n\n if (stateData && stateData.state && stateData.state.name) {\n return stateData.state;\n }\n}\n\n/**\n * @ngdoc directive\n * @name ui.router.state.directive:ui-sref\n *\n * @requires ui.router.state.$state\n * @requires $timeout\n *\n * @restrict A\n *\n * @description\n * A directive that binds a link (`` tag) to a state. If the state has an associated \n * URL, the directive will automatically generate & update the `href` attribute via \n * the {@link ui.router.state.$state#methods_href $state.href()} method. Clicking \n * the link will trigger a state transition with optional parameters. \n *\n * Also middle-clicking, right-clicking, and ctrl-clicking on the link will be \n * handled natively by the browser.\n *\n * You can also use relative state paths within ui-sref, just like the relative \n * paths passed to `$state.go()`. You just need to be aware that the path is relative\n * to the state that the link lives in, in other words the state that loaded the \n * template containing the link.\n *\n * You can specify options to pass to {@link ui.router.state.$state#go $state.go()}\n * using the `ui-sref-opts` attribute. Options are restricted to `location`, `inherit`,\n * and `reload`.\n *\n * @example\n * Here's an example of how you'd use ui-sref and how it would compile. If you have the \n * following template:\n *
\n * Home | About | Next page\n * \n * \n * 
\n * \n * Then the compiled html would be (assuming Html5Mode is off and current state is contacts):\n *
\n * Home | About | Next page\n * \n * 
    \n *
  • \n * Joe\n *
  • \n *
  • \n * Alice\n *
  • \n *
  • \n * Bob\n *
  • \n *
\n *\n * Home\n *
\n *\n * @param {string} ui-sref 'stateName' can be any valid absolute or relative state\n * @param {Object} ui-sref-opts options to pass to {@link ui.router.state.$state#go $state.go()}\n */\n$StateRefDirective.$inject = ['$state', '$timeout'];\nfunction $StateRefDirective($state, $timeout) {\n var allowedOptions = ['location', 'inherit', 'reload'];\n\n return {\n restrict: 'A',\n require: ['?^uiSrefActive', '?^uiSrefActiveEq'],\n link: function(scope, element, attrs, uiSrefActive) {\n var ref = parseStateRef(attrs.uiSref, $state.current.name);\n var params = null, url = null, base = stateContext(element) || $state.$current;\n var newHref = null, isAnchor = element.prop(\"tagName\") === \"A\";\n var isForm = element[0].nodeName === \"FORM\";\n var attr = isForm ? \"action\" : \"href\", nav = true;\n\n var options = { relative: base, inherit: true };\n var optionsOverride = scope.$eval(attrs.uiSrefOpts) || {};\n\n angular.forEach(allowedOptions, function(option) {\n if (option in optionsOverride) {\n options[option] = optionsOverride[option];\n }\n });\n\n var update = function(newVal) {\n if (newVal) params = angular.copy(newVal);\n if (!nav) return;\n\n newHref = $state.href(ref.state, params, options);\n\n var activeDirective = uiSrefActive[1] || uiSrefActive[0];\n if (activeDirective) {\n activeDirective.$$setStateInfo(ref.state, params);\n }\n if (newHref === null) {\n nav = false;\n return false;\n }\n attrs.$set(attr, newHref);\n };\n\n if (ref.paramExpr) {\n scope.$watch(ref.paramExpr, function(newVal, oldVal) {\n if (newVal !== params) update(newVal);\n }, true);\n params = angular.copy(scope.$eval(ref.paramExpr));\n }\n update();\n\n if (isForm) return;\n\n element.bind(\"click\", function(e) {\n var button = e.which || e.button;\n if ( !(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || element.attr('target')) ) {\n // HACK: This is to allow ng-clicks to be processed before the transition is initiated:\n var transition = $timeout(function() {\n $state.go(ref.state, params, options);\n });\n e.preventDefault();\n\n // if the state has no URL, ignore one preventDefault from the directive.\n var ignorePreventDefaultCount = isAnchor && !newHref ? 1: 0;\n e.preventDefault = function() {\n if (ignorePreventDefaultCount-- <= 0)\n $timeout.cancel(transition);\n };\n }\n });\n }\n };\n}\n\n/**\n * @ngdoc directive\n * @name ui.router.state.directive:ui-sref-active\n *\n * @requires ui.router.state.$state\n * @requires ui.router.state.$stateParams\n * @requires $interpolate\n *\n * @restrict A\n *\n * @description\n * A directive working alongside ui-sref to add classes to an element when the\n * related ui-sref directive's state is active, and removing them when it is inactive.\n * The primary use-case is to simplify the special appearance of navigation menus\n * relying on `ui-sref`, by having the \"active\" state's menu button appear different,\n * distinguishing it from the inactive menu items.\n *\n * ui-sref-active can live on the same element as ui-sref or on a parent element. The first\n * ui-sref-active found at the same level or above the ui-sref will be used.\n *\n * Will activate when the ui-sref's target state or any child state is active. If you\n * need to activate only when the ui-sref target state is active and *not* any of\n * it's children, then you will use\n * {@link ui.router.state.directive:ui-sref-active-eq ui-sref-active-eq}\n *\n * @example\n * Given the following template:\n *
\n * \n * 
\n *\n *\n * When the app state is \"app.user\" (or any children states), and contains the state parameter \"user\" with value \"bilbobaggins\",\n * the resulting HTML will appear as (note the 'active' class):\n *
\n * \n * 
\n *\n * The class name is interpolated **once** during the directives link time (any further changes to the\n * interpolated value are ignored).\n *\n * Multiple classes may be specified in a space-separated format:\n *
\n * 
    \n *
  • \n * link\n *
  • \n *
\n *
\n */\n\n/**\n * @ngdoc directive\n * @name ui.router.state.directive:ui-sref-active-eq\n *\n * @requires ui.router.state.$state\n * @requires ui.router.state.$stateParams\n * @requires $interpolate\n *\n * @restrict A\n *\n * @description\n * The same as {@link ui.router.state.directive:ui-sref-active ui-sref-active} but will only activate\n * when the exact target state used in the `ui-sref` is active; no child states.\n *\n */\n$StateRefActiveDirective.$inject = ['$state', '$stateParams', '$interpolate'];\nfunction $StateRefActiveDirective($state, $stateParams, $interpolate) {\n return {\n restrict: \"A\",\n controller: ['$scope', '$element', '$attrs', function ($scope, $element, $attrs) {\n var state, params, activeClass;\n\n // There probably isn't much point in $observing this\n // uiSrefActive and uiSrefActiveEq share the same directive object with some\n // slight difference in logic routing\n activeClass = $interpolate($attrs.uiSrefActiveEq || $attrs.uiSrefActive || '', false)($scope);\n\n // Allow uiSref to communicate with uiSrefActive[Equals]\n this.$$setStateInfo = function (newState, newParams) {\n state = $state.get(newState, stateContext($element));\n params = newParams;\n update();\n };\n\n $scope.$on('$stateChangeSuccess', update);\n\n // Update route state\n function update() {\n if (isMatch()) {\n $element.addClass(activeClass);\n } else {\n $element.removeClass(activeClass);\n }\n }\n\n function isMatch() {\n if (typeof $attrs.uiSrefActiveEq !== 'undefined') {\n return state && $state.is(state.name, params);\n } else {\n return state && $state.includes(state.name, params);\n }\n }\n }]\n };\n}\n\nangular.module('ui.router.state')\n .directive('uiSref', $StateRefDirective)\n .directive('uiSrefActive', $StateRefActiveDirective)\n .directive('uiSrefActiveEq', $StateRefActiveDirective);\n\n/**\n * @ngdoc filter\n * @name ui.router.state.filter:isState\n *\n * @requires ui.router.state.$state\n *\n * @description\n * Translates to {@link ui.router.state.$state#methods_is $state.is(\"stateName\")}.\n */\n$IsStateFilter.$inject = ['$state'];\nfunction $IsStateFilter($state) {\n var isFilter = function (state) {\n return $state.is(state);\n };\n isFilter.$stateful = true;\n return isFilter;\n}\n\n/**\n * @ngdoc filter\n * @name ui.router.state.filter:includedByState\n *\n * @requires ui.router.state.$state\n *\n * @description\n * Translates to {@link ui.router.state.$state#methods_includes $state.includes('fullOrPartialStateName')}.\n */\n$IncludedByStateFilter.$inject = ['$state'];\nfunction $IncludedByStateFilter($state) {\n var includesFilter = function (state) {\n return $state.includes(state);\n };\n includesFilter.$stateful = true;\n return includesFilter;\n}\n\nangular.module('ui.router.state')\n .filter('isState', $IsStateFilter)\n .filter('includedByState', $IncludedByStateFilter);\n})(window, window.angular);\ndefine(\"ui-router\", [\"angular\"], function(){});\n\n","/**\n * defines constants for application\n */\ndefine('config',['angular'], function (angular) {\n 'use strict';\n\n // define sentry environment by browser domain\n var SENTRY_ENV_URLS = {\n dev: 'https://314d46eeaa1a4ebf94ea03dd7eeadd13@app.getsentry.com/40818',\n qa: 'https://818ac29e08bd4892b5ebd92f4f56108f@app.getsentry.com/40815',\n prod: 'https://2c2ff72d6d664ae295c51c3fa977a236@app.getsentry.com/29638'\n };\n\n var SINGLE_SIGN_ON_URLS = {\n prod: 'https://merchanttrack.fullsteampay.net/Account/SingleSignOn',\n test: 'https://merchanttrack-ext.fullsteampay.net/Account/SingleSignOn'\n };\n\n var host = window.location.host;\n var SENTRY_URL = SENTRY_ENV_URLS.dev;\n var SINGLE_SIGN_ON_URL = SINGLE_SIGN_ON_URLS.test;\n\n if (host === 'app.bridallive.com') {\n SENTRY_URL = SENTRY_ENV_URLS.prod;\n SINGLE_SIGN_ON_URL = SINGLE_SIGN_ON_URLS.prod;\n } else if (host === 'qa.bridallive.com') {\n SENTRY_URL = SENTRY_ENV_URLS.qa;\n }\n\n return angular.module('bl.constants', [])\n\n .constant('CONFIG', {\n ITEM_PLACEHOLDER_SRC: '/assets/img/item/placeholder.png',\n MKT_ITEM_PLACEHOLDER_SRC: '/assets/img/item/mkt-item-placeholder.png',\n NO_PICTURE_PLACEHOLDER_SRC: '/assets/img/item/no-picture-placeholder-2.png',\n NO_PICTURE_PLACEHOLDER_SM_SRC: '/assets/img/item/no-picture-placeholder-sm-purple.png',\n NO_PICTURE_PLACEHOLDER_LG_SRC: '/assets/img/item/no-picture-placeholder-lg-white-purple.png'\n })\n\n .constant('CONSTANTS', {\n USE_BLOCK_TIMES:'1',\n DIGITAL_SIGNATURE: {\n ON_SCREEN: '2',\n BL_PAY_TERMINAL: '3'\n },\n SYSTEM: 'SYSTEM',\n ONLINE_SCHEDULER: 'ONLINE_SCHEDULER'\n })\n\n .constant('DEFAULTS', {\n SCHEDULER: {\n theme: {\n palette: 'blue',\n textColor: '#222222',\n primaryColor: '#bfadd1',\n secondaryColor: '#e8e8e8',\n selectedColor: '#2C6CB0',\n availableColor: '#dff0d8',\n timeSlotColor: '#e8e8e8',\n inputBorderColor: '#E2E8F0',\n primaryTextColor: '#222222',\n secondaryTextColor: '#222222',\n selectedTextColor: '#222222',\n availableTextColor: '#222222',\n timeSlotTextColor: '#222222',\n font: 'Default',\n transparent: true\n },\n selectDateTimeSettings: {\n noAppointment: 'No appointment available on this day'\n },\n layoutType: 'steps',\n steps: [\n {\n id: 'appointmentType',\n tabId: 'basic',\n type: 'selectAppointmentType',\n title: 'Select Appointment Type',\n description: '',\n enabled: true,\n _default: true,\n config: {\n preset: true // can't be disabled\n }\n },\n {\n id: 'associate',\n tabId: 'basic',\n type: 'selectAssociate',\n title: 'Select an Associate',\n description: '',\n enabled: true,\n _default: false\n },\n {\n id: 'dateAndTime',\n tabId: 'basic',\n type: 'selectDateAndTime',\n title: 'Select Date & Time',\n foo:'bar',\n description: '',\n enabled: true,\n _default: true,\n config: {\n preset: true // can't be disabled\n }\n },\n {\n id: 'requiredFields', // API field\n tabId: 'required',\n type: 'customForm', // renderer component\n title: 'Contact Information', // renderer title\n description: '',\n fields: [\n { type: 'text', label: 'First Name', id: 'firstName', required: true, config: { preset: true }, _default: true },\n { type: 'text', label: 'Last Name', id: 'lastName', required: true, config: { preset: true }, _default: true },\n { type: 'phone', label: 'Phone', id: 'phone', required: true, config: { preset: true }, _default: true },// phoneType gonna be combined with phone by renderer\n { type: 'email', label: 'Email', id: 'email', required: true, config: { preset: true }, _default: true },\n { type: 'date', label: 'Event Date', id: 'eventDate', required: true, config: { preset: true }, _default: true },\n ],\n enabled: true,\n _default: true,\n config: {preset: true} // can't be disabled\n },\n {\n id: 'additionalDetails', // API field\n tabId: 'custom',\n type: 'customForm', // renderer component\n title: 'Additional Details', // renderer title\n description: '',\n fields: [],\n customFields: [],\n enabled: true,\n _default: false\n }\n ]\n },\n REQUEST: {\n theme: {\n palette: 'red',\n textColor: '#222222'\n },\n layoutType: 'steps',\n steps: [\n {\n id: 'appointmentType',\n tabId: 'basic',\n type: 'selectAppointmentType',\n title: 'Select Appointment Type',\n description: '',\n enabled: true,\n config: {\n preset: true // can't be disabled\n }\n },\n {\n id: 'associate',\n tabId: 'basic',\n type: 'selectAssociate',\n title: 'Select an Associate',\n description: '',\n enabled: false,\n },\n {\n id: 'dateAndTime',\n tabId: 'basic',\n type: 'selectDateAndTime',\n title: 'Select Date & Time',\n description: '',\n enabled: true,\n config: {\n preset: true // can't be disabled\n }\n },\n {\n id: 'requiredFields', // API field\n tabId: 'required',\n type: 'customForm', // renderer component\n title: 'Required Details', // renderer title\n description: '',\n fields: [\n { type: 'text', label: 'First Name', id: 'firstName', required: true, config: { preset: true } },\n { type: 'text', label: 'Last Name', id: 'lastName', required: true, config: { preset: true } },\n { type: 'phone', label: 'Phone', id: 'phone', required: true, config: { preset: true } },// phoneType gonna be combined with phone by renderer\n { type: 'email', label: 'Email', id: 'email', required: true, config: { preset: true } },\n { type: 'date', label: 'Event Date', id: 'eventDate', required: true, config: { preset: true } },\n ],\n enabled: true,\n config: {preset: true} // can't be disabled\n },\n {\n id: 'additionalDetails', // API field\n tabId: 'custom',\n type: 'customForm', // renderer component\n title: 'Additional Details', // renderer title\n description: '',\n fields: [],\n customFields: [],\n enabled: true\n }\n ]\n },\n LEAD: {\n theme: {\n palette: 'orange',\n textColor: '#222222'\n },\n layoutType: 'steps',\n steps: []\n },\n INTERVIEW: {\n theme: {\n palette: 'green',\n textColor: '#222222'\n },\n layoutType: 'steps',\n steps: [\n {\n id: 'requiredFields', // API field\n tabId: 'required',\n type: 'customForm', // renderer component\n title: 'Required Details', // renderer title\n description: '',\n fields: [\n {type: 'text', label: 'First Name', id: 'firstName', required: true, config: {preset: true}},\n {type: 'text', label: 'Last Name', id: 'lastName', required: true, config: {preset: true}},\n {type: 'phone', label: 'Phone', id: 'phone', required: true, config: {preset: true}},// phoneType gonna be combined with phone by renderer\n {type: 'email', label: 'Email', id: 'email', required: true, config: {preset: true}},\n {type: 'date', label: 'Event Date', id: 'eventDate', required: true, config: {preset: true}},\n ],\n enabled: true,\n config: {preset: true} // can't be disabled\n }\n ]\n },\n FEEDBACK: {\n theme: {\n palette: 'yellow',\n textColor: '#222222'\n },\n layoutType: 'steps',\n steps: []\n }\n }\n )\n\n .constant('PORTAL', {\n USER_ID: -1,\n USERNAME: 'PORTAL',\n SENDER: 'Client Portal',\n HERO_IMAGE_PLACEHOLDER_SRC:'/assets/img/hero-image-1.jpg'\n })\n\n .constant('PAYMENT_PLAN', {\n USER_ID: -2,\n USERNAME: 'Payment Plan',\n SENDER: 'Payment Plan',\n })\n\n .constant('QUOTE', {\n USERNAME: 'QUOTE'\n })\n\n .constant('QBConstants', {\n INCOME_ACC_TYPE:'INCOME',\n COGS_ACC_TYPE:'COST_OF_GOODS_SOLD',\n MERCHANDISE_SALES: 'Merchandise Sales',\n COGS: 'Cost of Goods Sold',\n SALES_TAX_VENDOR:'Sales Tax Vendor Name',\n ACCOUNT_MAPPING: 'accounts',\n DEPARTMENT_MAPPING: 'departments',\n VENDOR_MAPPING: 'vendors',\n BILL:'bill',\n ENTITY: 'entity',\n INVOICE: 'invoice',\n JOURNAL: 'journal',\n PAYMENT: 'payment',\n PENDING: 'pending'\n })\n\n .constant('FULLSTEAM', {\n TIP_TYPES: {\n PERCENT: 'P',\n DOLLAR: 'D'\n },\n DEVICES: {\n MX915: 'MX915',\n MX925: 'MX925',\n L5000: 'L5000',\n L7000: 'L7000',\n MOVE_5000: 'M5000',\n ISMP4: 'iSMP4',\n LINK_2500: 'LK2500',\n A77: 'PAX_A77',\n A920_PRO: 'PAX_A920PRO',\n ARIES_8: 'PAX_ARIES8'\n },\n CARD_ENTRY: {\n POS_CARD_PRESENT: { id: 1, key: 'PointOfSaleCardPresent' }, //In App - Terminal\n WEB_CONSUMER_INITIATED: { id: 5, key: 'WebConsumerInitiated' }, //Portal Payments\n WEB_MERCHANT_ENTERED_PHONE_ORDER: { id: 7, key: 'WebMerchantEnteredPhoneOrder' }, //In App - Manual Entry\n CARD_ON_FILE_RECURRING: { id: 9, key: 'CardOnFileRecurring' }, // In App - Appt Charges & Use Card on file\n CARD_ON_FILE_MERCHANT_INITIATED_PHONE_ORDER: { id: 13, key: 'CardOnFileMerchantInitiatedPhoneOrder' } // In App - Appt Charges & Use Card on file\n },\n AUTHENTICATION_KEY: {\n TOKEN: 'token',\n PAYMENT: 'payment'\n },\n DEALS: {\n PORTFOLIO:{\n BL: {\n ID: 5638534,\n DESC: 'BridalLive'\n }\n },\n STAGE: {\n QD_LEAD: {\n ID: 2095729,\n DESC: 'Qualified Lead (Entered In System)'\n },\n LOST: {\n ID: 2095726,\n DESC:'Lost'\n },\n WON: {\n ID: 2095741,\n DESC:'Won'\n },\n DISCOVERY_MADE_CONTACT:{\n ID: 2095732,\n DESC: 'Discovery - Made Contact'\n },\n QUOTE: {\n ID: 2095735,\n DESC:'Quote / Negotiation'\n },\n AGREEMENT_REACHED:{\n ID: 2132449,\n DESC:'Agreement Reached'\n }\n },\n SOURCE: {\n EXISTING: {\n ID: 2913802,\n DESC: 'Existing Merchant (Conversion)'\n },\n NEW: {\n ID: 2925319,\n DESC: 'New Software Customer'\n }\n },\n PILELINE: {\n PAYMENTS: {\n ID: 263425,\n DESC: 'Payments Sales Pipeline'\n }\n },\n DEAL_PRIORITY:{\n ASAP: 5638648,\n LOW: 5638657,\n MEDIUM: 5638654,\n HIGH: 5638651\n },\n HARDWARE: {\n YES: 5638660,\n NO: 5638663\n },\n USERS: {\n TIM: {\n ID: 645538\n }\n }\n },\n ERRORS: {\n errors:[\n { type:'Zip - Zip is Required', message: 'settings.merchant-account.fullsteam-errors.invalid-zip' },\n { type:'HostedControlsCardDetailsViewModel.Zip', message: 'settings.merchant-account.fullsteam-errors.invalid-zip' },\n { type:'ExpirationMonth', message: 'settings.merchant-account.fullsteam-errors.invalid-month' },\n { type:'ExpirationYear', message: 'settings.merchant-account.fullsteam-errors.invalid-year', method: 'getCreditCardYears' }\n ]\n },\n WAF_KEY_WORDS: [\n {\n key: 'isnull',\n value: 'isnull'\n },\n {\n key: 'is null',\n value: 'is null'\n }\n ]\n })\n\n .constant('US_STATES', [\n { \"label\":\"Alabama\", \"value\": \"AL\" },\n { \"label\":\"Alaska\", \"value\": \"AK\" },\n { \"label\":\"Arizona\", \"value\": \"AZ\" },\n { \"label\":\"Arkansas\", \"value\": \"AR\" },\n { \"label\":\"California\", \"value\": \"CA\" },\n { \"label\":\"Colorado\", \"value\": \"CO\" },\n { \"label\":\"Connecticut\", \"value\": \"CT\" },\n { \"label\":\"Delaware\", \"value\": \"DE\" },\n { \"label\":\"District of Columbia\", \"value\": \"DC\" },\n { \"label\":\"Florida\", \"value\": \"FL\" },\n { \"label\":\"Georgia\", \"value\": \"GA\" },\n { \"label\":\"Hawaii\", \"value\": \"HI\" },\n { \"label\":\"Idaho\", \"value\": \"ID\" },\n { \"label\":\"Illinois\", \"value\": \"IL\" },\n { \"label\":\"Indiana\", \"value\": \"IN\" },\n { \"label\":\"Iowa\", \"value\": \"IA\" },\n { \"label\":\"Kansas\", \"value\": \"KS\" },\n { \"label\":\"Kentucky\", \"value\": \"KY\" },\n { \"label\":\"Louisiana\", \"value\": \"LA\" },\n { \"label\":\"Maine\", \"value\": \"ME\" },\n { \"label\":\"Maryland\", \"value\": \"MD\" },\n { \"label\":\"Massachusetts\", \"value\": \"MA\" },\n { \"label\":\"Michigan\", \"value\": \"MI\" },\n { \"label\":\"Minnesota\", \"value\": \"MN\" },\n { \"label\":\"Mississippi\", \"value\": \"MS\" },\n { \"label\":\"Missouri\", \"value\": \"MO\" },\n { \"label\":\"Montana\", \"value\": \"MT\" },\n { \"label\":\"Nebraska\", \"value\": \"NE\" },\n { \"label\":\"Nevada\", \"value\": \"NV\" },\n { \"label\":\"New Hampshire\", \"value\": \"NH\" },\n { \"label\":\"New Jersey\", \"value\": \"NJ\" },\n { \"label\":\"New Mexico\", \"value\": \"NM\" },\n { \"label\":\"New York\", \"value\": \"NY\" },\n { \"label\":\"North Carolina\", \"value\": \"NC\" },\n { \"label\":\"North Dakota\", \"value\": \"ND\" },\n { \"label\":\"Ohio\", \"value\": \"OH\" },\n { \"label\":\"Oklahoma\", \"value\": \"OK\" },\n { \"label\":\"Oregon\", \"value\": \"OR\" },\n { \"label\":\"Pennsylvania\", \"value\": \"PA\" },\n { \"label\":\"Rhode Island\", \"value\": \"RI\" },\n { \"label\":\"South Carolina\", \"value\": \"SC\" },\n { \"label\":\"South Dakota\", \"value\": \"SD\" },\n { \"label\":\"Tennessee\", \"value\": \"TN\" },\n { \"label\":\"Texas\", \"value\": \"TX\" },\n { \"label\":\"Utah\", \"value\": \"UT\" },\n { \"label\":\"Vermont\", \"value\": \"VT\" },\n { \"label\":\"Virginia\", \"value\": \"VA\" },\n { \"label\":\"Washington\", \"value\": \"WA\" },\n { \"label\":\"West Virginia\", \"value\": \"WV\" },\n { \"label\":\"Wisconsin\", \"value\": \"WI\" },\n { \"label\":\"Wyoming\", \"value\": \"WY\" },\n { \"label\":\"American Samoa\", \"value\": \"AS\" },\n { \"label\":\"Guam\", \"value\": \"GU\" },\n { \"label\":\"Northern Mariana Islands\", \"value\": \"MP\" },\n { \"label\":\"Puerto Rico\", \"value\": \"PR\" },\n { \"label\":\"U.S. Virgin Islands\", \"value\": \"VI\" },\n { \"label\":\"Micronesia\", \"value\": \"FM\" },\n { \"label\":\"Marshall Islands\", \"value\": \"MH\" },\n { \"label\":\"Palau\", \"value\": \"PW\" },\n { \"label\":\"U.S. Armed Forces – Americas\", \"value\": \"AA\" },\n { \"label\":\"U.S. Armed Forces – Europe\", \"value\": \"AE\" },\n { \"label\":\"U.S. Armed Forces – Pacific\", \"value\": \"AP\" },\n { \"label\":\"Northern Mariana Islands\", \"value\": \"CM\" },\n { \"label\":\"Panama Canal Zone\", \"value\": \"CZ\" }\n ])\n\n .constant('PORTAL_COLOR_THEMES', [{\n id:'BL',\n name: 'BL_DEFAULT',\n headerFooterBG: '#9686b1', // Header and footer background color - Navbar/Footer on client portal.\n headerFooterText: '#FFFFFF', // Header and footer text color - Navbar/Footer on client portal.\n primaryBtnBG: '#9686b1', // Primary button background color - All 'btn-primary' and 'card-primary' classes, the 'timeline-badge' element, and 'active-card' class updating 'border-color' using darken method.\n primaryBtnText: '#FFFFFF' // Primary button text color - All 'btn-primary' and 'card-primary' classes in client portal.\n }, {\n id:'SB',\n name: 'SOMETHING_BLUE',\n headerFooterBG: '#A4B0BE',\n headerFooterText: '#FFFFFF',\n primaryBtnBG: '#c4cbd4',\n primaryBtnText: '#FFFFFF'\n }, {\n id:'DK',\n name: 'DUSK',\n headerFooterBG: '#969376',\n headerFooterText: '#FFFFFF',\n primaryBtnBG: '#878296',\n primaryBtnText: '#FFFFFF'\n }, {\n id:'MW',\n name: 'MEADOW',\n headerFooterBG: '#d2e0d4',\n headerFooterText: '#FFFFFF',\n primaryBtnBG: '#a5998d',\n primaryBtnText: '#FFFFFF'\n },\n {\n id:'BH',\n name: 'BLUSH',\n headerFooterBG: '#f7e1db',\n headerFooterText: '#454545',\n primaryBtnBG: '#f7e1db',\n primaryBtnText: '#454545'\n },\n {\n id:'WF',\n name: 'WILD_AND_FREE',\n headerFooterBG: '#f0f0f0',\n headerFooterText: '#e0baa4',\n primaryBtnBG: '#f0f0f0',\n primaryBtnText: '#e0baa4'\n },\n {\n id:'IT',\n name: 'ISLAND_TIME',\n headerFooterBG: '#2c303a',\n headerFooterText: '#cad295',\n primaryBtnBG: '#2c303a',\n primaryBtnText: '#cad295'\n },\n {\n id:'NL',\n name: 'NEUTRAL',\n headerFooterBG: '#C2C1C0',\n headerFooterText: '#FFFFFF',\n primaryBtnBG: '#9B9A9A',\n primaryBtnText: '#FFFFFF'\n }])\n\n .constant('WEBFORM_COLOR_THEMES', [{\n id:'BL',\n name: 'BL_DEFAULT',\n transparent: true,\n backgroundColor: '#ffffff',\n textColor: '#454545',\n primaryColor: '#9686b1',\n secondaryColor: '#e8e8e8',\n selectedColor: '#b9a5cd',\n availableColor: '#dff0d8',\n timeSlotColor: '#e8e8e8',\n inputBorderColor: '#E2E8F0',\n primaryTextColor: '#FFFFFF',\n secondaryTextColor: '#454545',\n selectedTextColor: '#ffffff',\n availableTextColor: '#ffffff',\n timeSlotTextColor: '#454545'\n },\n {\n id:'SB',\n name: 'SOMETHING_BLUE',\n transparent: false,\n backgroundColor: '#A4B0BE',\n textColor: '#454545',\n primaryColor: '#c4cbd4',\n secondaryColor: '#e8e8e8',\n selectedColor: '#c4cbd4',\n availableColor: '#dff0d8',\n timeSlotColor: '#e8e8e8',\n inputBorderColor: '#E2E8F0',\n primaryTextColor: '#ffffff',\n secondaryTextColor: '#454545',\n selectedTextColor: '#ffffff',\n availableTextColor: '#ffffff',\n timeSlotTextColor: '#454545'\n },\n {\n id:'DK',\n name: 'DUSK',\n transparent: false,\n backgroundColor: '#969376',\n textColor: '#454545',\n primaryColor: '#878296',\n secondaryColor: '#e8e8e8',\n selectedColor: '#878296',\n availableColor: '#dff0d8',\n timeSlotColor: '#e8e8e8',\n inputBorderColor: '#E2E8F0',\n primaryTextColor: '#ffffff',\n secondaryTextColor: '#454545',\n selectedTextColor: '#ffffff',\n availableTextColor: '#ffffff',\n timeSlotTextColor: '#454545'\n },\n {\n id:'MW',\n name: 'MEADOW',\n transparent: false,\n backgroundColor: '#d2e0d4',\n textColor: '#454545',\n primaryColor: '#a5998d',\n secondaryColor: '#e8e8e8',\n selectedColor: '#a5998d',\n availableColor: '#dff0d8',\n timeSlotColor: '#e8e8e8',\n inputBorderColor: '#E2E8F0',\n primaryTextColor: '#ffffff',\n secondaryTextColor: '#454545',\n selectedTextColor: '#ffffff',\n availableTextColor: '#ffffff',\n timeSlotTextColor: '#454545'\n },\n {\n id:'BH',\n name: 'BLUSH',\n transparent: false,\n backgroundColor: '#ffffff',\n textColor: '#454545',\n primaryColor: '#f7e1db',\n secondaryColor: '#e8e8e8',\n selectedColor: '#f7e1db',\n availableColor: '#dff0d8',\n timeSlotColor: '#e8e8e8',\n inputBorderColor: '#E2E8F0',\n primaryTextColor: '#454545',\n secondaryTextColor: '#454545',\n selectedTextColor: '#454545',\n availableTextColor: '#454545',\n timeSlotTextColor: '#454545'\n },\n {\n id:'WF',\n name: 'WILD_AND_FREE',\n transparent: false,\n backgroundColor: '#ffffff',\n textColor: '#e0baa4',\n primaryColor: '#f0f0f0',\n secondaryColor: '#e8e8e8',\n selectedColor: '#f0f0f0',\n availableColor: '#dff0d8',\n timeSlotColor: '#e8e8e8',\n inputBorderColor: '#E2E8F0',\n primaryTextColor: '#e0baa4',\n secondaryTextColor: '#454545',\n selectedTextColor: '#e0baa4',\n availableTextColor: '#e0baa4',\n timeSlotTextColor: '#454545',\n },\n {\n id:'IT',\n name: 'ISLAND_TIME',\n transparent: false,\n backgroundColor: '#ffffff',\n textColor: '#cad295',\n secondaryColor: '#e8e8e8',\n primaryColor: '#2c303a',\n selectedColor: '#2c303a',\n availableColor: '#dff0d8',\n timeSlotColor: '#e8e8e8',\n inputBorderColor: '#E2E8F0',\n primaryTextColor: '#cad295',\n secondaryTextColor: '#454545',\n selectedTextColor: '#cad295',\n availableTextColor: '#cad295',\n timeSlotTextColor: '#454545',\n },\n {\n id:'NL',\n name: 'NEUTRAL',\n transparent: true,\n backgroundColor: '#ffffff',\n textColor: '#222222',\n primaryColor: '#7f7f7f',\n secondaryColor: '#e8e8e8',\n selectedColor: '#9B9A9A',\n availableColor: '#dff0d8',\n timeSlotColor: '#e8e8e8',\n inputBorderColor: '#E2E8F0',\n primaryTextColor: '#222222',\n secondaryTextColor: '#454545',\n selectedTextColor: '#222222',\n availableTextColor: '#222222',\n timeSlotTextColor: '#454545'\n }])\n\n .constant('ItemInterestEmailSettings', {\n showItemName: {\n id: 0,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.favorites.show-item-name'\n },\n showVendorName: {\n id: 1,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.favorites.show-vendor'\n },\n showColor: {\n id: 2,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.favorites.show-color'\n },\n showSize: {\n id: 3,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.favorites.show-size'\n },\n showColorString: {\n id: 4,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.favorites.show-available-colors'\n },\n showColor2String: {\n id: 5,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.favorites.show-available-accent-colors'\n },\n showImage: {\n id: 6,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.favorites.show-image'\n },\n showNotes: {\n id: 7,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.favorites.show-notes'\n },\n showTriedOnDescription: {\n id: 8,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.favorites.show-tried-on-description'\n },\n showSizeString: {\n id: 9,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.favorites.show-available-sizes.title',\n additionalValues: [{\n id: 1,\n value: 'RANGE',\n type: 'radio',\n label: '',\n key: 'showSizeStringType',\n values: [\n {\n label: 'settings.email-settings.favorites.show-available-sizes.all-sizes',\n value: 'ALL'\n },\n {\n label: 'settings.email-settings.favorites.show-available-sizes.size-range',\n value: 'RANGE'\n }\n ]\n }]\n }\n })\n\n .constant('PaymentEmailSettings', {\n showPaymentNumber: {\n id: 0,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-number'\n },\n showPaymentTransaction: {\n id: 1,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-transaction'\n },\n showPaymentDate: {\n id: 2,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-date'\n },\n showPaymentCreatedDate: {\n id: 3,\n value: false,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-created-date'\n },\n showPaymentMethod: {\n id: 4,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-method'\n },\n showPaymentAmount: {\n id: 5,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-amount'\n },\n showPaymentChangeAmount: {\n id: 6,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-change-amount'\n },\n showPaymentTipAmount: {\n id: 7,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-tip-amount'\n },\n showPaymentApprovalCode: {\n id: 8,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-approval-code'\n },\n showPaymentEmployeeName: {\n id: 9,\n value: false,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-employee-name'\n },\n showPaymentRefundAmount: {\n id: 10,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-refund-amount'\n },\n showPaymentTipRefundAmount: {\n id: 11,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-tip-refund-amount'\n },\n showPaymentStatus: {\n id: 12,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-status'\n },\n showPaymentPlatformFeeAmount: {\n id: 13,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-platform-fee-amount'\n },\n showPaymentPlatformFeePercentage: {\n id: 14,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-platform-fee-percentage'\n },\n showPaymentPlatformFeeAmountRefunded: {\n id: 15,\n value: true,\n type: 'checkbox',\n label: 'settings.email-settings.payments.show-payment-platform-fee-amount-refund'\n }\n })\n\n .constant('COOKIE_NAME', 'bl_user')\n\n .constant('SENTRY_URL', SENTRY_URL)\n\n .constant('SINGLE_SIGN_ON_URL', SINGLE_SIGN_ON_URL)\n\n .constant('MergeFields', [\n\n { group:'merge-fields.company.title', description:'merge-fields.company.name.description', key:'[Company.name]' },\n { group:'merge-fields.company.title', description:'merge-fields.company.website.description', key:'[Company.websiteAddress]' },\n { group:'merge-fields.company.title', description:'merge-fields.company.email-address.description', key:'[Company.emailAddress]' },\n { group:'merge-fields.company.title', description:'merge-fields.company.address1.description', key:'[Company.address1]' },\n { group:'merge-fields.company.title', description:'merge-fields.company.address2.description', key:'[Company.address2]' },\n { group:'merge-fields.company.title', description:'merge-fields.company.city-state-and-postal-code.description', key:'[Company.cityStateZipString]' },\n { group:'merge-fields.company.title', description:'merge-fields.company.city.description', key:'[Company.city]' },\n { group:'merge-fields.company.title', description:'merge-fields.company.state.description', key:'[Company.state]' },\n { group:'merge-fields.company.title', description:'merge-fields.company.zip.description', key:'[Company.zip]' },\n { group:'merge-fields.company.title', description:'merge-fields.company.phone.description', key:'[Company.phoneNumberFormatted]' },\n { group:'merge-fields.company.title', description:'merge-fields.company.fax.description', key:'[Company.faxNumberFormatted]' },\n { group:'merge-fields.company.title', description:'merge-fields.company.vat-number.description', key:'[Company.vatNumber]' },\n { group:'merge-fields.company.title', description:'merge-fields.company.uk-address.description', key:'[Company.ukAddressFormatted]' },\n { group:'merge-fields.company.title', description:'merge-fields.company.vat-label.description', key:'[Company.vatLabel]' },\n\n { group:'merge-fields.contact.title', description:'merge-fields.contact.first-name.description', key:'[Contact.firstName]' },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.last-name.description', key:'[Contact.lastName]' },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.full-name.description', key:'[Contact.fullName]' },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.event-date.description', key:'[Contact.eventDateFormatted]' },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.interview-url.description', key:'[InterviewWidgetSettings.urlForContact]' },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.feedback-url.description', key:'[FeedbackWidgetSettings.urlForContact]' },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.contact-id.description', key:'[Contact.id]' },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.email-address.description', key:'[Contact.emailAddress]' },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.contact-pin.description', key:'[Contact.portalPin]' },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.portal-home.description', key:'[Contact.portalDashboardUrl]' },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.portal-registration.description', key:'[Contact.portalRegistrationUrl]' },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.portal-lookbook.description', key:'[Contact.portalLookBookUrl]' },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.portal-payment.description', key:'[Contact.portalPaymentUrl]', transactionRequired: false, paymentRequest: true, signatureRequest: false, optional: true },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.portal-agreement.description', key:'[Contact.portalAgreementUrl]', transactionRequired: false, paymentRequest: false, signatureRequest: true, signatureRequestType: 'TRX', optional: true },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.portal-payment-and-agreement.description', key:'[Contact.portalPaymentAgreementUrl]', transactionRequired: false, paymentRequest: true, signatureRequest: true, signatureRequestType: 'TRX', optional: true },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.portal-quote-agreement.description', key:'[Contact.portalQuoteAgreementUrl]', quoteRequired: true, paymentRequest: false, signatureRequest: true, signatureRequestType: 'QUOTE', optional: true },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.portal-tuxedo-measurements.description', key:'[Contact.portalTuxedoMeasurementsUrl]', measurementsRequest: true },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.portal-dress-measurements.description', key:'[Contact.portalDressMeasurementsUrl]', measurementsRequest: true },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.portal-measurements.description', key:'[Contact.portalMeasurementsUrl]', measurementsRequest: true },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.portal-payment-info.description', key:'[Contact.portalPaymentInfoUrl]', paymentInfoRequest: true },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.portal-billing.description', key:'[Contact.portalBillingUrl]', billingRequest: true },\n { group:'merge-fields.contact.title', description:'merge-fields.contact.portal-payment-plan-agreement.description', key:'[Contact.portalPaymentPlanAgreementUrl]', planSignatureRequest: true },\n\n { group:'merge-fields.appointment.title', description:'merge-fields.appointment.start-day-of-week.description', key:'[Appointment.startDayOfWeek]', appointmentRequired: true },\n { group:'merge-fields.appointment.title', description:'merge-fields.appointment.start-date-formatted.description', key:'[Appointment.startDateFormatted]', appointmentRequired: true },\n { group:'merge-fields.appointment.title', description:'merge-fields.appointment.start-time-formatted.description', key:'[Appointment.startTimeFormatted]', appointmentRequired: true },\n { group:'merge-fields.appointment.title', description:'merge-fields.appointment.type-description.description', key:'[Appointment.typeDescription]', appointmentRequired: true },\n { group:'merge-fields.appointment.title', description:'merge-fields.appointment.employee-name.description', key:'[Appointment.employeeName]', appointmentRequired: true },\n { group:'merge-fields.appointment.title', description:'merge-fields.appointment.confirm-url.description', key:'[Appointment.confirmUrl]', appointmentRequired: true },\n { group:'merge-fields.appointment.title', description:'merge-fields.appointment.cancel-url.description', key:'[Appointment.cancelUrl]', appointmentRequired: true },\n { group:'merge-fields.appointment.title', description:'merge-fields.appointment.confirm-cancel-options.description', key:'[TwilioSettings.confirmCancelOptions]', appointmentRequired: true },\n { group:'merge-fields.appointment.title', description:'merge-fields.appointment.opt-out-option.description', key:'[TwilioSettings.optOutOption]', appointmentRequired: false },\n\n { group:'merge-fields.associate.title', description:'merge-fields.associate.first-name.description', key:'[Employee.firstName]' },\n { group:'merge-fields.associate.title', description:'merge-fields.associate.full-name.description', key:'[Employee.fullName]' },\n\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.trx-number.description', key:'[POSTransaction.trxNumber]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.type.description', key:'[POSTransaction.typeDescription]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.order-date.description', key:'[POSTransaction.transactionDateFormatted]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.contact-name.description', key:'[POSTransaction.contactName]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.contact-phone.description', key:'[POSTransaction.contactPhoneFormatted]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.event-contact-name.description', key:'[POSTransaction.eventContactName]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.event-date.description', key:'[POSTransaction.eventDateFormatted]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.items.description', key:'[POSTransaction.lineItemsHTML]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.payment-items.description', key:'[POSTransaction.paymentHistoryHTML]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.notes.description', key:'[POSTransaction.notes]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.subtotal.description', key:'[POSTransaction.subtotalFormatted]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.shipping-amount.description', key:'[POSTransaction.shippingFormatted]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.shipping-info.description', key:'[POSTransaction.shippingAddressHTML]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.discount-amount.description', key:'[POSTransaction.discountAmountFormatted]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.fee-amount.description', key:'[POSTransaction.feesFormatted]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.tax-amount.description', key:'[POSTransaction.taxAmountFormatted]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.included-tax-amount.description', key:'[POSTransaction.includedTaxAmountFormatted]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.vat-total-amount.description', key:'[POSTransaction.vatAmountTotalFormatted]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.amount-due.description', key:'[POSTransaction.amountDueFormatted]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.total-amount.description', key:'[POSTransaction.totalPaymentAmountFormatted]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.sales-agreement.description', key:'[POSTransaction.terms]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.sales-agreement-signature.description', key:'[POSTransaction.signatureHTML]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.upcoming-appointments.description', key:'[POSTransaction.upcomingAppointmentsHTML]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.discount-header-toggle.description', key:'[POSTransaction.discountToggle]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.tip-header-toggle.description', key:'[POSTransaction.tipToggle]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.platform-fee-header-toggle.description', key:'[POSTransaction.platformFeeToggle]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.order-level-discount-header-toggle.description', key:'[POSTransaction.orderLevelDiscountToggle]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.order-level-discount-amount.description', key:'[POSTransaction.orderLevelDiscountFormatted]', transactionRequired: true },\n { group:'merge-fields.transaction.title', description:'merge-fields.transaction.agreement-header-toggle.description', key:'[POSTransaction.salesAgreementHeaderToggle]', transactionRequired: true },\n\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.po-number.description', key:'[PurchaseOrder.purchaseOrderNumber]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.vendor-name.description', key:'[PurchaseOrder.vendorName]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.vendor-account-number.description', key:'[PurchaseOrder.vendorAccountNumber]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.order-date.description', key:'[PurchaseOrder.orderDateFormatted]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.event-date.description', key:'[PurchaseOrder.eventDateFormatted]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.contact-name.description', key:'[PurchaseOrder.contactName]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.event-contact-date.description', key:'[PurchaseOrder.eventContactName]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.shipping-date.description', key:'[PurchaseOrder.shipDateFormatted]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.items.description', key:'[PurchaseOrder.lineItemsHTML]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.vendor-address.description', key:'[PurchaseOrder.vendorAddressString]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.vendor-state-and-postal-code.description', key:'[PurchaseOrder.vendorCityStateZipString]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.vendor-country.description', key:'[PurchaseOrder.vendorCountryString]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.vendor-phone.description', key:'[PurchaseOrder.vendorPhoneNumberFormatted]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.vendor-fax.description', key:'[PurchaseOrder.vendorFaxNumberFormatted]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.notes.description', key:'[PurchaseOrder.notes]' },\n { group:'merge-fields.purchase-order.title', description:'merge-fields.purchase-order.totals.description', key:'[PurchaseOrder.totalsHTML]' },\n\n { group:'merge-fields.quote.title', description:'merge-fields.quote.quote-number.description', key:'[POSQuote.quoteNumber]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.created-date.description', key:'[POSQuote.createdDateFormatted]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.items.description', key:'[POSQuote.quoteLineItemsHTML]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.items-vat.description', key:'[POSQuote.quoteLineItemsWithVatHTML]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.employee-name.description', key:'[POSQuote.employeeName]', quoteRequired:true},\n { group:'merge-fields.quote.title', description:'merge-fields.quote.contact-name.description', key:'[POSQuote.contactName]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.event-contact-date.description', key:'[POSQuote.eventContactName]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.event-date.description', key:'[POSQuote.eventDateFormatted]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.notes.description', key:'[POSQuote.notes]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.subtotal.description', key:'[POSQuote.subtotalFormatted]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.fee-amount.description', key:'[POSQuote.feeAmountFormatted]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.discount-amount.description', key:'[POSQuote.discountAmountFormatted]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.discount-header-toggle.description', key:'[POSQuote.discountToggle]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.subtotal-before-vat.description', key:'[POSQuote.subtotalWithoutIncludedTaxFormatted]', quoteRequired: true },\n { group:'merge-fields.quote.title', description:'merge-fields.transaction.included-tax-amount.description', key:'[POSQuote.includedTaxAmountFormatted]', quoteRequired: true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.total-amount.description', key:'[POSQuote.totalAmountFormatted]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.quote-agreement.description', key:'[POSQuote.terms]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.quote-agreement-signature.description', key:'[POSQuote.signatureHTML]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.upcoming-appointments.description', key:'[POSQuote.upcomingAppointmentsHTML]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.order-level-discount-header-toggle.description', key:'[POSQuote.orderLevelDiscountToggle]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.order-level-discount-amount.description', key:'[POSQuote.orderLevelDiscountFormatted]', quoteRequired:true },\n { group:'merge-fields.quote.title', description:'merge-fields.quote.expiration-date.description', key:'[POSQuote.expirationDateFormatted]', quoteRequired:true },\n\n { group:'merge-fields.item-interest.title', description:'merge-fields.item-interest.color.description', key:'[ItemInterest.color]', itemInterestRequired: true, sendOnly: true },\n { group:'merge-fields.item-interest.title', description:'merge-fields.item-interest.color2.description', key:'[ItemInterest.color2]', itemInterestRequired: true, sendOnly: true },\n { group:'merge-fields.item-interest.title', description:'merge-fields.item-interest.size.description', key:'[ItemInterest.size]', itemInterestRequired: true, sendOnly: true },\n { group:'merge-fields.item-interest.title', description:'merge-fields.item-interest.notes.description', key:'[ItemInterest.notesFormatted]', itemInterestRequired: true, sendOnly: true },\n { group:'merge-fields.item-interest.title', description:'merge-fields.item-interest.tried-on.description', key:'[ItemInterest.triedOnDescription]', itemInterestRequired: true, sendOnly: true },\n { group:'merge-fields.item-interest.title', description:'merge-fields.item-interest.item-name.description', key:'[ItemInterest.itemName]', itemInterestRequired: true, sendOnly: true },\n { group:'merge-fields.item-interest.title', description:'merge-fields.item-interest.vendor-name.description', key:'[ItemInterest.vendorName]', itemInterestRequired: true, sendOnly: true },\n { group:'merge-fields.item-interest.title', description:'merge-fields.item-interest.color-string.description', key:'[ItemInterest.colorString]', itemInterestRequired: true, sendOnly: true },\n { group:'merge-fields.item-interest.title', description:'merge-fields.item-interest.color-2-string.description', key:'[ItemInterest.color2String]', itemInterestRequired: true, sendOnly: true },\n { group:'merge-fields.item-interest.title', description:'merge-fields.item-interest.size-string.description', key:'[ItemInterest.sizeStringFormatted]', itemInterestRequired: true, sendOnly: true },\n { group:'merge-fields.item-interest.title', description:'merge-fields.item-interest.size-string-all-sizes.description', key:'[ItemInterest.sizeStringAllSizesFormatted]', itemInterestRequired: true, sendOnly: true },\n { group:'merge-fields.item-interest.title', description:'merge-fields.item-interest.item-picture-image.description', key:'[ItemInterest.itemPictureImageUrlHTML]', itemInterestRequired: true, sendOnly: true },\n { group:'merge-fields.item-interest.title', description:'merge-fields.item-interest.multiple-favorites.description', key:'[ItemInterest.multipleFavoritesHTML]', itemInterestRequired: true, sendOnly: true },\n\n { group:'merge-fields.vendor.title', description:'merge-fields.vendor.name.description', key:'[Vendor.name]' },\n\n { group:'merge-fields.payment-plan-item.title', description:'merge-fields.payment-plan-item.payment-due-date.description', key:'[PaymentPlanItem.paymentDueDateFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment-plan-item.title', description:'merge-fields.payment-plan-item.amount.description', key:'[PaymentPlanItem.amountFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment-plan-item.title', description:'merge-fields.payment-plan-item.payment-received-date.description', key:'[PaymentPlanItem.paymentReceivedDateFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment-plan-item.title', description:'merge-fields.payment-plan-item.status.description', key:'[PaymentPlanItem.statusFormatted]', paymentRequired: true, sendOnly: true },\n\n { group:'merge-fields.payment-plan.title', description:'merge-fields.payment-plan.card-image-url.description', key:'[PaymentPlan.cardImageUrl]', paymentPlanRequired: true, emailOnly: true, sendOnly: true },\n { group:'merge-fields.payment-plan.title', description:'merge-fields.payment-plan.card-image-html.description', key:'[PaymentPlan.cardImageHTML]', paymentPlanRequired: true, emailOnly: true, sendOnly: true },\n { group:'merge-fields.payment-plan.title', description:'merge-fields.payment-plan.trx-desc.description', key:'[PaymentPlan.formattedTransactionDescription]', paymentPlanRequired: true, sendOnly: true },\n { group:'merge-fields.payment-plan.title', description:'merge-fields.payment-plan.card-desc.description', key:'[PaymentPlan.formattedCardDescription]', paymentPlanRequired: true, sendOnly: true },\n { group:'merge-fields.payment-plan.title', description:'merge-fields.payment-plan.contact-name.description', key:'[PaymentPlan.contactName]', paymentPlanRequired: true, sendOnly: true },\n { group:'merge-fields.payment-plan.title', description:'merge-fields.payment-plan.balance-due.description', key:'[PaymentPlan.balanceDueFormatted]', sendOnly: true },\n { group:'merge-fields.payment-plan.title', description:'merge-fields.payment-plan.remaining-installments.description', key:'[PaymentPlan.remainingInstallmentsFormatted]', paymentPlanRequired: true, sendOnly: true },\n { group:'merge-fields.payment-plan.title', description:'merge-fields.payment-plan.final-payment-date.description', key:'[PaymentPlan.finalPaymentDateFormatted]', paymentPlanRequired: true, sendOnly: true },\n { group:'merge-fields.payment-plan.title', description:'merge-fields.payment-plan.installments-html.description', key:'[PaymentPlan.installmentsTableHTML]', paymentPlanRequired: true, emailOnly: true, sendOnly: true },\n { group:'merge-fields.payment-plan.title', description:'merge-fields.payment-plan.signature-url.description', key:'[PaymentPlan.signatureImageURL]', paymentPlanRequired: true, emailOnly: true, sendOnly: true },\n { group:'merge-fields.payment-plan.title', description:'merge-fields.payment-plan.signature-html.description', key:'[PaymentPlan.signatureImageHTML]', paymentPlanRequired: true, emailOnly: true, sendOnly: true },\n { group:'merge-fields.payment-plan.title', description:'merge-fields.payment-plan.terms.description', key:'[PaymentPlan.terms]', paymentPlanRequired: true, emailOnly: true, sendOnly: true },\n\n { group:'merge-fields.payment.title', description:'merge-fields.payment.date.description', key:'[Payment.dateFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.created-date.description', key:'[Payment.createdDateFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.amount.description', key:'[Payment.amountFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.payment-grand-total.description', key:'[Payment.paymentGrandTotal]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.change-amount.description', key:'[Payment.changeAmountFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.tip-amount.description', key:'[Payment.tipAmountFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.platform-fee-amount.description', key:'[Payment.platformFeeAmountFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.platform-fee-percentage.description', key:'[Payment.platformFeePercentageFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.amount-refunded.description', key:'[Payment.amountRefundedFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.tip-amount-refunded.description', key:'[Payment.tipAmountRefundedFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.platform-fee-amount-refunded.description', key:'[Payment.platformFeeAmountRefundedFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.employee-name.description', key:'[Payment.employeeName]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.receipt-number.description', key:'[Payment.receiptNumber]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.method.description', key:'[Payment.methodDescription]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.account-number.description', key:'[Payment.xwebAccountNumber]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.approval-code.description', key:'[Payment.xwebApprovalCode]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.split-payment-transactions.description', key:'[Payment.splitTransactionHTML]', paymentRequired: true, sendOnly: true },\n\n { group:'merge-fields.payment.title', description:'merge-fields.payment.tip-amount-toggle.description', key:'[Payment.tipFormattedToggle]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.platform-fee-amount-toggle.description', key:'[Payment.platformFeeFormattedToggle]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.total-amount-toggle.description', key:'[Payment.totalAmountPaidToggle]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.trx-tax-amount.description', key:'[Payment.trxTaxAmountFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.trx-sub-total-amount.description', key:'[Payment.subTotalTrxAmountFormatted]', paymentRequired: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.trx-balance-due.description', key:'[Payment.trxBalanceDueFormatted]', paymentRequired: true, sendOnly: true },\n\n { group:'merge-fields.payment.title', description:'merge-fields.payment.default-template.description', key:'[Payment.defaultTemplateForPaymentView]', paymentRequired: true, paymentDefaultTemplate: true, sendOnly: true },\n { group:'merge-fields.payment.title', description:'merge-fields.payment.default-template-split.description', key:'[Payment.defaultTemplateForSplitPaymentView]', paymentRequired: true, splitPaymentDefaultTemplate: true, sendOnly: true }\n ])\n\n .constant('COUNTRIES', [\n {\n country: 'United States',\n phoneMask: \"999-999-9999\",\n phoneMaskWithExtension: \"999-999-9999 ?99999\",\n mobilePhoneMask: \"999-999-9999\",\n usesStates: true,\n states: [\n { label: \"Alabama\", value: \"AL\" },\n { label: \"Alaska\", value: \"AK\" },\n { label: \"Arizona\", value: \"AZ\" },\n { label: \"Arkansas\", value: \"AR\" },\n { label: \"California\", value: \"CA\" },\n { label: \"Colorado\", value: \"CO\" },\n { label: \"Connecticut\", value: \"CT\" },\n { label: \"Delaware\", value: \"DE\" },\n { label: \"District Of Columbia\", value: \"DC\" },\n { label: \"Florida\", value: \"FL\" },\n { label: \"Georgia\", value: \"GA\" },\n { label: \"Hawaii\", value: \"HI\" },\n { label: \"Idaho\", value: \"ID\" },\n { label: \"Illinois\", value: \"IL\" },\n { label: \"Indiana\", value: \"IN\" },\n { label: \"Iowa\", value: \"IA\" },\n { label: \"Kansas\", value: \"KS\" },\n { label: \"Kentucky\", value: \"KY\" },\n { label: \"Louisiana\", value: \"LA\" },\n { label: \"Maine\", value: \"ME\" },\n { label: \"Maryland\", value: \"MD\" },\n { label: \"Massachusetts\", value: \"MA\" },\n { label: \"Michigan\", value: \"MI\" },\n { label: \"Minnesota\", value: \"MN\" },\n { label: \"Mississippi\", value: \"MS\" },\n { label: \"Missouri\", value: \"MO\" },\n { label: \"Montana\", value: \"MT\" },\n { label: \"Nebraska\", value: \"NE\" },\n { label: \"Nevada\", value: \"NV\" },\n { label: \"New Hampshire\", value: \"NH\" },\n { label: \"New Jersey\", value: \"NJ\" },\n { label: \"New Mexico\", value: \"NM\" },\n { label: \"New York\", value: \"NY\" },\n { label: \"North Carolina\", value: \"NC\" },\n { label: \"North Dakota\", value: \"ND\" },\n { label: \"Ohio\", value: \"OH\" },\n { label: \"Oklahoma\", value: \"OK\" },\n { label: \"Oregon\", value: \"OR\" },\n { label: \"Pennsylvania\", value: \"PA\" },\n { label: \"Puerto Rico\", value: \"PR\" },\n { label: \"Rhode Island\", value: \"RI\" },\n { label: \"South Carolina\", value: \"SC\" },\n { label: \"South Dakota\", value: \"SD\" },\n { label: \"Tennessee\", value: \"TN\" },\n { label: \"Texas\", value: \"TX\" },\n { label: \"Utah\", value: \"UT\" },\n { label: \"Vermont\", value: \"VT\" },\n { label: \"Virginia\", value: \"VA\" },\n { label: \"Virgin Islands (US)\", value: \"USVI\" },\n { label: \"Virgin Islands (British)\", value: \"BVI\" },\n { label: \"Washington\", value: \"WA\" },\n { label: \"West Virginia\", value: \"WV\" },\n { label: \"Wisconsin\", value: \"WI\" },\n { label: \"Wyoming\", value: \"WY\" },\n { label: \"---------------------------------------\", value: \" \" },\n { label: \"Alberta\", value: \"AB\" },\n { label: \"British Columbia\", value: \"BC\" },\n { label: \"Manitoba\", value: \"MB\" },\n { label: \"New Brunswick\", value: \"NB\" },\n { label: \"Newfoundland and Labrador\", value: \"NL\" },\n { label: \"Northwest Territories\", value: \"NT\" },\n { label: \"Nova Scotia\", value: \"NS\" },\n { label: \"Nunavut\", value: \"NU\" },\n { label: \"Ontario\", value: \"ON\" },\n { label: \"Prince Edward Island\", value: \"PE\" },\n { label: \"Quebec\", value: \"QC\" },\n { label: \"Saskatchewan\", value: \"SK\" },\n { label: \"Yukon\", value: \"YT\" }\n ]\n },\n {\n country: 'Australia',\n phoneMask: \"99 9999 9999\",\n phoneMaskWithExtension: \"99 9999 9999 ?99999\",\n mobilePhoneMask: \"9999 999 999\",\n usesStates: true,\n states:[\n { label: \"Australian Capital Territory\", value: \"ACT\" },\n { label: \"New South Wales\", value: \"NSW\" },\n { label: \"Northern Territory\", value: \"NT\" },\n { label: \"Queensland\", value: \"QLD\" },\n { label: \"South Australia\", value: \"SA\" },\n { label: \"Tasmania\", value: \"TAS\" },\n { label: \"Victoria\", value: \"VIC\" },\n { label: \"Western Australia\", value: \"WA\" }\n ]\n },\n {\n country: 'Austria',\n phoneMask: \"999999999?9?9?9?9?9?9\",\n phoneMaskWithExtension: \"999999999?9?9?9?9?9?9 ?99\",\n mobilePhoneMask: \"999999999?9?9?9?9?9?9\",\n usesStates: true,\n states: [\n {label: \"Wien\", value:\"WIN\"},\n {label: \"Niederösterreich\", value:\"NDR\"},\n {label: \"Oberösterreich\", value:\"OBR\"},\n {label: \"Steiermark\", value:\"STM\"},\n {label: \"Tirol\", value:\"TRL\"},\n {label: \"Kärnten\", value:\"KTN\"},\n {label: \"Salzburg\", value:\"SZB\"},\n {label: \"Voralberg\", value:\"VRB\"},\n {label: \"Burgenland\", value:\"BGL\"}\n ]\n },\n {\n country: 'New Zealand',\n phoneMask: \"999-999999?99\",\n phoneMaskWithExtension: \"999-999999?99 ?999\",\n mobilePhoneMask: \"999-999999?99\",\n usesStates: true,\n states:[\n {label: \"Northland\", value:\"NTL\"},\n {label: \"Auckland\", value:\"AUK\"},\n {label: \"Waikato\", value:\"WKO\"},\n {label: \"Bay of Plenty\", value:\"BOP\"},\n {label: \"Gisborne\", value:\"GIS\"},\n {label: \"Hawke's Bay\", value:\"HKB\"},\n {label: \"Taranaki\", value:\"TKI\"},\n {label: \"Manawatu-Whanganui\", value:\"MWT\"},\n {label: \"Wellington\", value:\"WGN\"},\n {label: \"Tasman\", value:\"TAS\"},\n {label: \"Nelson\", value:\"NSN\"},\n {label: \"Marlborough\", value:\"MBH\"},\n {label: \"West Coast\", value:\"WTC\"},\n {label: \"Canterbury\", value:\"CAN\"},\n {label: \"Otago\", value:\"OTA\"},\n {label: \"Southland\", value:\"STL\"}\n ]\n },\n {\n country:'Belgium',\n phoneMask: \"999 999 999\",\n phoneMaskWithExtension: \"999 999 999 ?99999\",\n mobilePhoneMask: \"9999 99 99 99\",\n usesStates: true,\n states: [\n {label: \"Antwerpen\", value:\"VAN\"},\n {label: \"Brabant wallon\", value:\"WBR\"},\n {label: \"Hainaut\", value:\"WHT\"},\n {label: \"Liege\", value:\"WLG\"},\n {label: \"Limburg\", value:\"VLI\"},\n {label: \"Luxembourg\", value:\"WLX\"},\n {label: \"Namur\", value:\"WNA\"},\n {label: \"Oost-Vlaanderen\", value:\"VOV\"},\n {label: \"Vlaams-Brabant\", value:\"VBR\"},\n {label: \"West-Vlaanderen\", value:\"VWV\"}\n ]\n },\n {\n country: 'Canada',\n phoneMask: \"999-999-9999\",\n phoneMaskWithExtension: \"999-999-9999 ?99999\",\n mobilePhoneMask: \"999-999-9999\",\n usesStates: true,\n states: [\n { label: \"Alberta\", value: \"AB\"},\n { label: \"British Columbia\", value: \"BC\"},\n { label: \"Manitoba\", value: \"MB\"},\n { label: \"New Brunswick\", value: \"NB\"},\n { label: \"Newfoundland and Labrador\", value: \"NL\"},\n { label: \"Northwest Territories\", value: \"NT\"},\n { label: \"Nova Scotia\", value: \"NS\"},\n { label: \"Nunavut\", value: \"NU\"},\n { label: \"Ontario\", value: \"ON\"},\n { label: \"Prince Edward Island\", value: \"PE\"},\n { label: \"Quebec\", value: \"QC\"},\n { label: \"Saskatchewan\", value: \"SK\"},\n { label: \"Yukon\", value: \"YT\"},\n { label: \"---------------------------------------\", value: \" \"},\n { label: \"Alabama\", value: \"AL\"},\n { label: \"Alaska\", value: \"AK\"},\n { label: \"Arizona\", value: \"AZ\"},\n { label: \"Arkansas\", value: \"AR\"},\n { label: \"California\", value: \"CA\"},\n { label: \"Colorado\", value: \"CO\"},\n { label: \"Connecticut\", value: \"CT\"},\n { label: \"Delaware\", value: \"DE\"},\n { label: \"Distric Of Columbia\", value: \"DC\"},\n { label: \"Florida\", value: \"FL\"},\n { label: \"Georgia\", value: \"GA\"},\n { label: \"Hawaii\", value: \"HI\"},\n { label: \"Idaho\", value: \"ID\"},\n { label: \"Illinois\", value: \"IL\"},\n { label: \"Indiana\", value: \"IN\"},\n { label: \"Iowa\", value: \"IA\"},\n { label: \"Kansas\", value: \"KS\"},\n { label: \"Kentucky\", value: \"KY\"},\n { label: \"Louisiana\", value: \"LA\"},\n { label: \"Maine\", value: \"ME\"},\n { label: \"Maryland\", value: \"MD\"},\n { label: \"Massachusetts\", value: \"MA\"},\n { label: \"Michigan\", value: \"MI\"},\n { label: \"Minnesota\", value: \"MN\"},\n { label: \"Mississippi\", value: \"MS\"},\n { label: \"Missouri\", value: \"MO\"},\n { label: \"Montana\", value: \"MT\"},\n { label: \"Nebraska\", value: \"NE\"},\n { label: \"Nevada\", value: \"NV\"},\n { label: \"New Hampshire\", value: \"NH\"},\n { label: \"New Jersey\", value: \"NJ\"},\n { label: \"New Mexico\", value: \"NM\"},\n { label: \"New York\", value: \"NY\"},\n { label: \"North Carolina\", value: \"NC\"},\n { label: \"North Dakota\", value: \"ND\"},\n { label: \"Ohio\", value: \"OH\"},\n { label: \"Oklahoma\", value: \"OK\"},\n { label: \"Oregon\", value: \"OR\"},\n { label: \"Pennsylvania\", value: \"PA\"},\n { label: \"Puerto Rico\", value: \"PR\"},\n { label: \"Rhode Island\", value: \"RI\"},\n { label: \"South Carolina\", value: \"SC\"},\n { label: \"South Dakota\", value: \"SD\"},\n { label: \"Tennessee\", value: \"TN\"},\n { label: \"Texas\", value: \"TX\"},\n { label: \"Utah\", value: \"UT\"},\n { label: \"Vermont\", value: \"VT\"},\n { label: \"Virginia\", value: \"VA\"},\n { label: \"Virgin Islands (US)\", value: \"USVI\"},\n { label: \"Virgin Islands (British)\", value: \"BVI\"},\n { label: \"Washington\", value: \"WA\"},\n { label: \"West Virginia\", value: \"WV\"},\n { label: \"Wisconsin\", value: \"WI\"},\n { label: \"Wyoming\", value: \"WY\"}\n ]\n },\n {\n country: 'Germany',\n phoneMask: \"999999999?9?9?9?9?9?9\",\n phoneMaskWithExtension: \"999999999?9?9?9?9?9?9 ?99\",\n mobilePhoneMask: \"999999999?9?9?9?9?9?9\",\n usesStates: false,\n states: [\n { label: \"Baden-Württemberg\", value: \"BW\"},\n { label: \"Bayern\", value: \"BY\"},\n { label: \"Berlin\", value: \"BE\"},\n { label: \"Brandenburg\", value: \"BB\"},\n { label: \"Bremen\", value: \"HB\"},\n { label: \"Hamburg\", value: \"HH\"},\n { label: \"Hessen\", value: \"HE\"},\n { label: \"Niedersachsen\", value: \"NI\"},\n { label: \"Mecklenburg-Vorpommern\", value: \"MV\"},\n { label: \"Nordrhein-Westfalen\", value: \"NW\"},\n { label: \"Rheinland-Pfalz\", value: \"RP\"},\n { label: \"Saarland\", value: \"SL\"},\n { label: \"Sachsen\", value: \"SN\"},\n { label: \"Sachsen-Anhalt\", value: \"ST\"},\n { label: \"Schleswig-Holstein\", value: \"SH\"},\n { label: \"Thüringen\", value: \"TH\"}\n ]\n },\n {\n country: 'Denmark',\n phoneMask: \"99999999\",\n phoneMaskWithExtension: \"99999999\",\n mobilePhoneMask: \"99999999\",\n usesStates: true,\n states: [\n { label: \"Greenland County\", value: \"GC\" },\n { label: \"Copenhagen Municipalit\", value: \"CM\" },\n { label: \"Frederiksberg Municipality\", value: \"FM\" },\n { label: \"Copenhagen County\", value: \"CC\" },\n { label: \"Frederiksborg County\", value: \"FC\" },\n { label: \"Roskilde County\", value: \"RC\" },\n { label: \"West Zealand County\", value: \"WZC\" },\n { label: \"Storstrøm County\", value: \"SC\" },\n { label: \"Funen County\", value: \"FNC\" },\n { label: \"South Jutland County\", value: \"SJC\" },\n { label: \"Ribe County\", value: \"RC\" },\n { label: \"Vejle County\", value: \"VC\" },\n { label: \"Ringkjøbing County\", value: \"RIC\" },\n { label: \"North Jutland County\", value: \"NJC\" },\n { label: \"Viborg County\", value: \"VC\" },\n { label: \"Aarhus County\", value: \"AC\" },\n { label: \"Bornholm\", value: \"B\" }\n ]\n },\n {\n country: 'France',\n phoneMask: \"99 99 99 99 99\",\n phoneMaskWithExtension: \"99 99 99 99 99 ?99\",\n mobilePhoneMask: \"99 99 99 99 99\",\n usesStates: false,\n states:[\n {label: \"Ain\", value:\"AI\"},\n {label: \"Aisne\", value:\"AS\"},\n {label: \"Allier\", value:\"AL\"},\n {label: \"Alpes de Haute-Provence\", value:\"AP\"},\n {label: \"Alpes-Maritimes\", value:\"AM\"},\n {label: \"Ardèche\", value:\"AH\"},\n {label: \"Ardennes\", value:\"AN\"},\n {label: \"Ariège\", value:\"AG\"},\n {label: \"Aube\", value:\"AB\"},\n {label: \"Aude\", value:\"AD\"},\n {label: \"Aveyron\", value:\"AV\"},\n {label: \"Bas-Rhin\", value:\"BR\"},\n {label: \"Bouches du Rhône\", value:\"BD\"},\n {label: \"Calvados\", value:\"CV\"},\n {label: \"Cantal\", value:\"CV\"},\n {label: \"Charente\", value:\"CL\"},\n {label: \"Charente Maritime\", value:\"CM\"},\n {label: \"Cher\", value:\"CH\"},\n {label: \"Corrèze\", value:\"CZ\"},\n {label: \"Corse du Sud\", value:\"CS\"},\n {label: \"Côte d'Or\", value:\"CO\"},\n {label: \"Côtes d'Armor\", value:\"CA\"},\n {label: \"Creuse\", value:\"CR\"},\n {label: \"Deux-SŠvres\", value:\"DS\"},\n {label: \"Dordogne\", value:\"DD\"},\n {label: \"Doubs\", value:\"DB\"},\n {label: \"Drôme\", value:\"DM\"},\n {label: \"Essonne\", value:\"ES\"},\n {label: \"Eure\", value:\"EU\"},\n {label: \"Eure-et-Loir\", value:\"EL\"},\n {label: \"Finistère\", value:\"FI\"},\n {label: \"Gard\", value:\"GA\"},\n {label: \"Gers\", value:\"GE\"},\n {label: \"Gironde\", value:\"GI\"},\n {label: \"Haute-Corse\", value:\"HC\"},\n {label: \"Haute-Garonne\", value:\"HG\"},\n {label: \"Haute-Loire\", value:\"HL\"},\n {label: \"Haute-Marne\", value:\"HM\"},\n {label: \"Hautes-Alpes\", value:\"HA\"},\n {label: \"Haute-Saône\", value:\"HN\"},\n {label: \"Haute-Savoie\", value:\"HS\"},\n {label: \"Hautes-Pyrénées\", value:\"HP\"},\n {label: \"Haute-Vienne\", value:\"HV\"},\n {label: \"Haut-Rhin\", value:\"HR\"},\n {label: \"Hauts-de-Seine\", value:\"HD\"},\n {label: \"Hérault\", value:\"HE\"},\n {label: \"Ille-et-Vilaine\", value:\"IV\"},\n {label: \"Indre\", value:\"IN\"},\n {label: \"Indre-et-Loire\", value:\"IL\"},\n {label: \"Isère\", value:\"IS\"},\n {label: \"Jura\", value:\"JU\"},\n {label: \"Landes\", value:\"LD\"},\n {label: \"Loire\", value:\"LR\"},\n {label: \"Loire-Atlantique\", value:\"LA\"},\n {label: \"Loiret\", value:\"LT\"},\n {label: \"Loir-et-Cher\", value:\"LC\"},\n {label: \"Lot\", value:\"LO\"},\n {label: \"Lot-et-Garonne\", value:\"LG\"},\n {label: \"Lozère\", value:\"LZ\"},\n {label: \"Maine-et-Loire\", value:\"ML\"},\n {label: \"Manche\", value:\"MH\"},\n {label: \"Marne\", value:\"MR\"},\n {label: \"Mayenne\", value:\"MY\"},\n {label: \"Meurthe-et-Moselle\", value:\"MN\"},\n {label: \"Meuse\", value:\"MS\"},\n {label: \"Morbihan\", value:\"MB\"},\n {label: \"Moselle\", value:\"MO\"},\n {label: \"Nièvre\", value:\"NI\"},\n {label: \"Nord\", value:\"NO\"},\n {label: \"Oise\", value:\"OI\"},\n {label: \"Orne\", value:\"OR\"},\n {label: \"Paris\", value:\"VP\"},\n {label: \"Pas-de-Calais\", value:\"PC\"},\n {label: \"Puy-de-Dôme\", value:\"PD\"},\n {label: \"Pyrénées-Atlantiques\", value:\"PA\"},\n {label: \"Pyrénées-Orientales\", value:\"PO\"},\n {label: \"Rhône\", value:\"RH\"},\n {label: \"Saône-et-Loire\", value:\"SL\"},\n {label: \"Sarthe\", value:\"ST\"},\n {label: \"Savoie\", value:\"SV\"},\n {label: \"Seine-et-Marne\", value:\"SE\"},\n {label: \"Seine-Maritime\", value:\"SM\"},\n {label: \"Seine-St-Denis\", value:\"SS\"},\n {label: \"Somme\", value:\"SO\"},\n {label: \"Tarn\", value:\"TA\"},\n {label: \"Tarn-et-Garonne\", value:\"TG\"},\n {label: \"Territoire-de-Belfort\", value:\"TB\"},\n {label: \"Val-de-Marne\", value:\"VM\"},\n {label: \"Val-d'Oise\", value:\"VO\"},\n {label: \"Var\", value:\"VR\"},\n {label: \"Vaucluse\", value:\"VC\"},\n {label: \"Vendée\", value:\"VD\"},\n {label: \"Vienne\", value:\"VN\"},\n {label: \"Vosges\", value:\"VG\"},\n {label: \"Yonne\", value:\"YO\"},\n {label: \"Yvelines\", value:\"YV\"}\n ]\n },\n {\n country: 'Ireland',\n phoneMask: \"999999999?99999\",\n phoneMaskWithExtension: \"999999999?99999\",\n mobilePhoneMask: \"999999999?99999\",\n usesStates: true,\n states: [\n { label: \"Antrim\", value: \"AM\"},\n { label: \"Armagh\", value: \"AH\"},\n { label: \"Carlow\", value: \"CW\"},\n { label: \"Cavan\", value: \"CN\"},\n { label: \"Clare\", value: \"CE\"},\n { label: \"Cork\", value: \"C\"},\n { label: \"Derry\", value: \"DY\"},\n { label: \"Donegal\", value: \"DL\"},\n { label: \"Down\", value: \"DN\"},\n { label: \"Dublin\", value: \"D\"},\n { label: \"Fermanagh\", value: \"FH\"},\n { label: \"Galway\", value: \"GW\"},\n { label: \"Kerry\", value: \"KY\"},\n { label: \"Kildare\", value: \"KE\"},\n { label: \"Kilkenny\", value: \"KK\"},\n { label: \"Laois\", value: \"LS\"},\n { label: \"Leitrim\", value: \"LM\"},\n { label: \"Limerick\", value: \"LK\"},\n { label: \"Longford\", value: \"LD\"},\n { label: \"Louth\", value: \"LH\"},\n { label: \"Mayo\", value: \"MO\"},\n { label: \"Meath\", value: \"MH\"},\n { label: \"Monaghan\", value: \"MN\"},\n { label: \"Offaly\", value: \"OY\"},\n { label: \"Roscommon\", value: \"RN\"},\n { label: \"Sligo\", value: \"SO\"},\n { label: \"Tipperary N\", value: \"TN\"},\n { label: \"Tipperary S\", value: \"TS\"},\n { label: \"Tyrone\", value: \"TE\"},\n { label: \"Waterford\", value: \"WD\"},\n { label: \"Westmeath\", value: \"WH\"},\n { label: \"Wexford\", value: \"WX\"},\n { label: \"Wicklow\", value: \"WW\"}\n ]\n },\n {\n country: 'Italy',\n phoneMask: \"999 999999?9?9?9\",\n phoneMaskWithExtension: \"999 999999?9?9?9\",\n mobilePhoneMask: \"999 999999?9?9?9\",\n usesStates: false,\n states: [\n { label: \"Agrigento\", value: \"AG\" },\n { label: \"Alessandria\", value: \"AL\" },\n { label: \"Ancona\", value: \"AN\" },\n { label: \"Valle d'Aosta\", value: \"AO\" },\n { label: \"Arezzo\", value: \"AR\" },\n { label: \"Ascoli Piceno\", value: \"AP\" },\n { label: \"Asti\", value: \"AT\" },\n { label: \"Avellino\", value: \"AV\" },\n { label: \"Barletta-Andria-Trani\", value: \"BT\" },\n { label: \"Belluno\", value: \"BL\" },\n { label: \"Benevento\", value: \"BN\" },\n { label: \"Bergamo\", value: \"BG\" },\n { label: \"Biella\", value: \"BI\" },\n { label: \"Bolzano\", value: \"BZ\" },\n { label: \"Brescia\", value: \"BS\" },\n { label: \"Brindisi\", value: \"BR\" },\n { label: \"Caltanissetta\", value: \"CL\" },\n { label: \"Campobasso\", value: \"CB\" },\n { label: \"Caserta\", value: \"CE\" },\n { label: \"Catanzaro\", value: \"CZ\" },\n { label: \"Chieti\", value: \"CH\" },\n { label: \"Como\", value: \"CO\" },\n { label: \"Cosenza\", value: \"CS\" },\n { label: \"Cremona\", value: \"CR\" },\n { label: \"Crotone\", value: \"KR\" },\n { label: \"Cuneo\", value: \"CN\" },\n { label: \"Enna\", value: \"EN\" },\n { label: \"Fermo\", value: \"FM\" },\n { label: \"Ferrara\", value: \"FE\" },\n { label: \"Foggia\", value: \"FG\" },\n { label: \"Forlì-Cesena\", value: \"FC\" },\n { label: \"Frosinone\", value: \"FR\" },\n { label: \"Gorizia\", value: \"GO\" },\n { label: \"Grosseto\", value: \"GR\" },\n { label: \"Imperia\", value: \"IM\" },\n { label: \"Isernia\", value: \"IS\" },\n { label: \"La Spezia\", value: \"SP\" },\n { label: \"L'Aquila\", value: \"AQ\" },\n { label: \"Latina\", value: \"LT\" },\n { label: \"Lecce\", value: \"LE\" },\n { label: \"Lecco\", value: \"LC\" },\n { label: \"Livorno\", value: \"LI\" },\n { label: \"Lodi\", value: \"LO\" },\n { label: \"Lucca\", value: \"LU\" },\n { label: \"Macerata\", value: \"MC\" },\n { label: \"Mantova\", value: \"MN\" },\n { label: \"Massa-Carrara\", value: \"MS\" },\n { label: \"Matera\", value: \"MT\" },\n { label: \"Messina\", value: \"ME\" },\n { label: \"Monza e Brianza\", value: \"MB\" },\n { label: \"Modena\", value: \"MO\" },\n { label: \"Novara\", value: \"NO\" },\n { label: \"Nuoro\", value: \"NU\" },\n { label: \"Oristano\", value: \"OR\" },\n { label: \"Padova\", value: \"PD\" },\n { label: \"Parma\", value: \"PR\" },\n { label: \"Pavia\", value: \"PV\" },\n { label: \"Perugia\", value: \"PG\" },\n { label: \"Pesaro e Urbino\", value: \"PU\" },\n { label: \"Pescara\", value: \"PE\" },\n { label: \"Piacenza\", value: \"PC\" },\n { label: \"Pisa\", value: \"PI\" },\n { label: \"Pistoia\", value: \"PT\" },\n { label: \"Pordenone\", value: \"PN\" },\n { label: \"Potenza\", value: \"PZ\" },\n { label: \"Prato\", value: \"PO\" },\n { label: \"Ragusa\", value: \"RG\" },\n { label: \"Ravenna\", value: \"RA\" },\n { label: \"Reggio Emilia\", value: \"RE\" },\n { label: \"Rieti\", value: \"RI\" },\n { label: \"Rimini\", value: \"RN\" },\n { label: \"Rovigo\", value: \"RO\" },\n { label: \"Salerno\", value: \"SA\" },\n { label: \"Sassari\", value: \"SS\" },\n { label: \"Savona\", value: \"SV\" },\n { label: \"Siena\", value: \"SI\" },\n { label: \"Siracusa\", value: \"SR\" },\n { label: \"Sondrio\", value: \"SO\" },\n { label: \"Taranto\", value: \"TA\" },\n { label: \"Teramo\", value: \"TE\" },\n { label: \"Terni\", value: \"TR\" },\n { label: \"Trapani\", value: \"TP\" },\n { label: \"Trento\", value: \"TN\" },\n { label: \"Treviso\", value: \"TV\" },\n { label: \"Trieste\", value: \"TS\" },\n { label: \"Udine\", value: \"UD\" },\n { label: \"Varese\", value: \"VA\" },\n { label: \"Verbano-Cusio-Ossola\", value: \"VB\" },\n { label: \"Vercelli\", value: \"VC\" },\n { label: \"Verona\", value: \"VR\" },\n { label: \"Vibo Valentia\", value: \"VV\" },\n { label: \"Vicenza\", value: \"VI\" },\n { label: \"Viterbo\", value: \"VT\" }\n ]\n },\n {\n country: 'Luxembourg',\n phoneMask: \"999 999 999\",\n phoneMaskWithExtension: \"999 999 999 ?99999\",\n mobilePhoneMask: \"999 999 999\",\n usesStates: true,\n states: [\n {label: \"Kapellen\", value:\"CA\"},\n {label: \"Klierf\", value:\"CL\"},\n {label: \"Diekrech\", value:\"DI\"},\n {label: \"Iechternach\", value:\"EC\"},\n {label: \"Esch-Uelzecht\", value:\"ES\"},\n {label: \"Gréivemaacher\", value:\"GR\"},\n {label: \"Lëtzebuerg\", value:\"LU\"},\n {label: \"Miersch\", value:\"ME\"},\n {label: \"Réiden-Atert\", value:\"RD\"},\n {label: \"Réimech\", value:\"RM\"},\n {label: \"Veianen\", value:\"VD\"},\n {label: \"Wolz\", value:\"WI\"}\n ]\n },\n {\n country: 'Mexico',\n phoneMask: \"999-999-9999\",\n phoneMaskWithExtension: \"999-999-9999 ?99999\",\n mobilePhoneMask: \"999-999-9999\",\n usesStates: true,\n states: [\n { label: \"Mexican Federal District\", value: \"CMX\" },\n { label: \"Aguascalientes\", value: \"AGU\" },\n { label: \"Baja California\", value: \"BCN\" },\n { label: \"Baja California Sur\", value: \"BCS\" },\n { label: \"Campeche\", value: \"CAM\" },\n { label: \"Coahuila\", value: \"COA\" },\n { label: \"Colima\", value: \"COL\" },\n { label: \"Chiapas\", value: \"CHP\" },\n { label: \"Chihuahua\", value: \"CHH\" },\n { label: \"Durango\", value: \"DUR\" },\n { label: \"Guanajuato\", value: \"GUA\" },\n { label: \"Guerrero\", value: \"GRO\" },\n { label: \"Hidalgo\", value: \"HID\" },\n { label: \"Jalisco\", value: \"JAL\" },\n { label: \"México\", value: \"MEX\" },\n { label: \"Michoacán\", value: \"MIC\" },\n { label: \"Morelos\", value: \"MOR\" },\n { label: \"Nayarit\", value: \"NAY\" },\n { label: \"Nuevo León\", value: \"NLE\" },\n { label: \"Oaxaca\", value: \"OAX\" },\n { label: \"Puebla\", value: \"PUE\" },\n { label: \"Querétaro\", value: \"QUE\" },\n { label: \"Quintana Roo\", value: \"ROO\" },\n { label: \"San Luis Potosí\", value: \"SLP\" },\n { label: \"Sinaloa\", value: \"SIN\" },\n { label: \"Sonora\", value: \"SON\" },\n { label: \"Tabasco\", value: \"TAB\" },\n { label: \"Tamaulipas\", value: \"TAM\" },\n { label: \"Tlaxcala\", value: \"TLA\" },\n { label: \"Veracruz\", value: \"VER\" },\n { label: \"Yucatán\", value: \"YUC\" },\n { label: \"Zacatecas\", value: \"ZAC\" }\n ]\n },\n {\n country: 'Netherlands',\n phoneMask: \"999999999?99999\",\n phoneMaskWithExtension: \"999999999?99999\",\n mobilePhoneMask: \"999999999?99999\",\n usesStates: false,\n states: [\n { label: \"Drenthe\", value: \"DR\" },\n { label: \"Flevoland\", value: \"FL\" },\n { label: \"Fryslân\", value: \"FR\" },\n { label: \"Gelderland\", value: \"GE\" },\n { label: \"Groningen\", value: \"GR\" },\n { label: \"Limburg\", value: \"LI\" },\n { label: \"Noord-Brabant\", value: \"NB\" },\n { label: \"Noord-Holland\", value: \"NH\" },\n { label: \"Overijssel\", value: \"OV\" },\n { label: \"Utrecht\", value: \"UT\" },\n { label: \"Zeeland\", value: \"ZE\" },\n { label: \"Zuid-Holland\", value: \"ZH\" }\n ]\n },\n {\n country: 'Spain',\n phoneMask: \"999 999 999\",\n phoneMaskWithExtension: \"999 999 999 ?99\",\n mobilePhoneMask: \"999 999 999\",\n usesStates: false,\n states: [\n {label: \"A Coruña\", value:\"C\"},\n {label: \"Albacete\", value:\"AB\"},\n {label: \"Alicante\", value:\"A\"},\n {label: \"Almería\", value:\"AL\"},\n {label: \"Asturias\", value:\"O\"},\n {label: \"Ávila\", value:\"AV\"},\n {label: \"Badajoz\", value:\"BA\"},\n {label: \"Baleares\", value:\"PM\"},\n {label: \"Barcelona\", value:\"B\"},\n {label: \"Burgos\", value:\"BU\"},\n {label: \"Cáceres\", value:\"CC\"},\n {label: \"Cádiz\", value:\"CA\"},\n {label: \"Cantabria\", value:\"S\"},\n {label: \"Castellón\", value:\"CS\"},\n {label: \"Ciudad Real\", value:\"CR\"},\n {label: \"Córdoba\", value:\"CO\"},\n {label: \"Cuenca\", value:\"CM\"},\n {label: \"Gipuzkoa\", value:\"SS\"},\n {label: \"Girona\", value:\"GI\"},\n {label: \"Granada\", value:\"GR\"},\n {label: \"Guadalajara\", value:\"GU\"},\n {label: \"Huelva\", value:\"H\"},\n {label: \"Huesca\", value:\"HU\"},\n {label: \"Jaén\", value:\"J\"},\n {label: \"La Rioja\", value:\"LO\"},\n {label: \"Las Palmas\", value:\"GC\"},\n {label: \"León\", value:\"LE\"},\n {label: \"Lérida\", value:\"L\"},\n {label: \"Lugo\", value:\"LU\"},\n {label: \"Madrid\", value:\"M\"},\n {label: \"Málaga\", value:\"MA\"},\n {label: \"Murcia\", value:\"MU\"},\n {label: \"Navarra\", value:\"NA\"},\n {label: \"Orense\", value:\"OR\"},\n {label: \"Palencia\", value:\"P\"},\n {label: \"Pontevedra\", value:\"PO\"},\n {label: \"Santa Cruz de Tenerife\", value:\"\"},\n {label: \"Salamanca\", value:\"SA\"},\n {label: \"Segovia\", value:\"SG\"},\n {label: \"Sevilla\", value:\"SE\"},\n {label: \"Soria\", value:\"SO\"},\n {label: \"Tarragona\", value:\"T\"},\n {label: \"Teruel\", value:\"TE\"},\n {label: \"Toledo\", value:\"TO\"},\n {label: \"Valencia\", value:\"V\"},\n {label: \"Valladolid\", value:\"VA\"},\n {label: \"Vizcaya\", value:\"BI\"},\n {label: \"Zamora\", value:\"ZA\"},\n {label: \"Zaragoza\", value:\"Z\"}\n ]\n },\n {\n country: 'Romania',\n phoneMask: \"99999999?99\",\n phoneMaskWithExtension: \"99999999?99\",\n mobilePhoneMask: \"99999999?99\",\n usesStates: false,\n states:[]\n },\n {\n country:'Switzerland',\n phoneMask: \"99 99 99 99 99\",\n phoneMaskWithExtension: \"99 99 99 99 99 ?99\",\n mobilePhoneMask: \"99 99 99 99 99\",\n usesStates: true,\n states: [\n {label: \"Aargau\", value:\"AG\"},\n {label: \"Appenzell Ausserrhoden\", value:\"AR\"},\n {label: \"Appenzell Innerrhoden\", value:\"AI\"},\n {label: \"Basel-Landschaft\", value:\"BL\"},\n {label: \"Basel-Stadt\", value:\"BS\"},\n {label: \"Bern\", value:\"BE\"},\n {label: \"Fribourg\", value:\"FR\"},\n {label: \"Geneve\", value:\"GE\"},\n {label: \"Glarus\", value:\"GL\"},\n {label: \"Graubunden\", value:\"GR\"},\n {label: \"Jura\", value:\"JU\"},\n {label: \"Luzern\", value:\"LU\"},\n {label: \"Neuchatel\", value:\"NE\"},\n {label: \"Nidwalden\", value:\"NW\"},\n {label: \"Obwalden\", value:\"OW\"},\n {label: \"Sankt Gallen\", value:\"SG\"},\n {label: \"Schaffhausen\", value:\"SH\"},\n {label: \"Schwyz\", value:\"SZ\"},\n {label: \"Solothurn\", value:\"SO\"},\n {label: \"Thurgau\", value:\"TG\"},\n {label: \"Ticino\", value:\"TI\"},\n {label: \"Uri\", value:\"UR\"},\n {label: \"Valais\", value:\"VS\"},\n {label: \"Vaud\", value:\"VD\"},\n {label: \"Zug\", value:\"ZG\"},\n {label: \"Zurich\", value:\"ZH\"}\n ]\n },\n {\n country: 'United Kingdom',\n phoneMask: \"99999 99999?9?9?9?9?9\",\n phoneMaskWithExtension: \"99999 99999?9?9?9?9?9\",\n mobilePhoneMask: \"99999 99999?9?9?9?9?9\",\n usesStates: true,\n states: [\n { label: \"Avon\", value:\"AV\"},\n { label: \"Bedfordshire\", value:\"BF\"},\n { label: \"Berkshire\", value:\"BB\"},\n { label: \"Borders\", value:\"BO\"},\n { label: \"Bristol\", value:\"BR\"},\n { label: \"Buckinghamshire\", value:\"BC\"},\n { label: \"Cambridgeshire\", value:\"CS\"},\n { label: \"Central\", value:\"CT\"},\n { label: \"Cheshire\", value:\"CH\"},\n { label: \"City of London\", value:\"CL\"},\n { label: \"Cornwall\", value:\"CO\"},\n { label: \"Cumbria\", value:\"CB\"},\n { label: \"Derbyshire\", value:\"DBY\"},\n { label: \"Devon\", value:\"DV\"},\n { label: \"Dorset\", value:\"DOR\"},\n { label: \"Durham\", value:\"DH\"},\n { label: \"East Riding of Yorkshire\", value:\"ER\"},\n { label: \"East Sussex\", value:\"ES\"},\n { label: \"Essex\", value:\"EX\"},\n { label: \"Gloucestershire\", value:\"GS\"},\n { label: \"London\", value:\"GL\"},\n { label: \"Greater Manchester\", value:\"GM\"},\n { label: \"Hampshire\", value:\"HS\"},\n { label: \"Herefordshire\", value:\"HE\"},\n { label: \"Hertfordshire\", value:\"HT\"},\n { label: \"Isle of Wight\", value:\"IW\"},\n { label: \"Kent\", value:\"KT\"},\n { label: \"Lancashire\", value:\"LAN\"},\n { label: \"Leicestershire\", value:\"LT\"},\n { label: \"Lincolnshire\", value:\"LN\"},\n { label: \"Merseyside\", value:\"MS\"},\n { label: \"Norfolk\", value:\"NF\"},\n { label: \"North Yorkshire\", value:\"NY\"},\n { label: \"Northamptonshire\", value:\"NH\"},\n { label: \"Northumberland\", value:\"NL\"},\n { label: \"Nottinghamshire\", value:\"NS\"},\n { label: \"Oxfordshire\", value:\"OS\"},\n { label: \"Rutland\", value:\"RL\"},\n { label: \"Shropshire\", value:\"SHR\"},\n { label: \"Somerset\", value:\"SOM\"},\n { label: \"South Yorkshire\", value:\"SY\"},\n { label: \"Staffordshire\", value:\"STS\"},\n { label: \"Suffolk\", value:\"SF\"},\n { label: \"Surrey\", value:\"SR\"},\n { label: \"Tyne and Wear\", value:\"TW\"},\n { label: \"Warwickshire\", value:\"WAR\"},\n { label: \"West Midlands\", value:\"WM\"},\n { label: \"West Sussex\", value:\"WS\"},\n { label: \"West Yorkshire\", value:\"WY\"},\n { label: \"Wiltshire\", value:\"WR\"},\n { label: \"Worcestershire\", value:\"WC\"},\n { label: \"Yorkshire\", value:\"YS\"},\n { label: \"---------------------------------------\", value:\" \"},\n { label: \"Aberdeenshire\", value:\"AS\"},\n { label: \"Angus\", value:\"AU\"},\n { label: \"Argyll\", value:\"AG\"},\n { label: \"Ayrshire\", value:\"AY\"},\n { label: \"Banffshire\", value:\"BS\"},\n { label: \"Berwickshire\", value:\"BK\"},\n { label: \"Bute\", value:\"BT\"},\n { label: \"Caithness\", value:\"CAI\"},\n { label: \"Clackmannanshire\", value:\"CM\"},\n { label: \"Dumfriesshire\", value:\"DF\"},\n { label: \"Dunbartonshire\", value:\"DU\"},\n { label: \"East Lothian\", value:\"EL\"},\n { label: \"Fife\", value:\"FF\"},\n { label: \"Inverness-shire\", value:\"IS\"},\n { label: \"Kirkcudbrightshire\", value:\"KS\"},\n { label: \"Kincardineshire\", value:\"KN\"},\n { label: \"Kinross-shire\", value:\"KR\"},\n { label: \"Lanarkshire\", value:\"LKS\"},\n { label: \"Midlothian\", value:\"MT\"},\n { label: \"Moray\", value:\"MR\"},\n { label: \"Nairnshire\", value:\"NN\"},\n { label: \"Orkney\", value:\"OK\"},\n { label: \"Peeblesshire\", value:\"PB\"},\n { label: \"Perthshire\", value:\"PS\"},\n { label: \"Renfrewshire\", value:\"RW\"},\n { label: \"Ross and Cromarty\", value:\"RC\"},\n { label: \"Roxburghshire\", value:\"RB\"},\n { label: \"Selkirkshire\", value:\"SK\"},\n { label: \"Shetland\", value:\"SN\"},\n { label: \"Stirlingshire\", value:\"SH\"},\n { label: \"Sutherland\", value:\"SL\"},\n { label: \"West Lothian\", value:\"WL\"},\n { label: \"Wigtownshire\", value:\"WG\"},\n { label: \"---------------------------------------\", value:\" \"},\n { label: \"Antrim\", value:\"AM\"},\n { label: \"Armagh\", value:\"ABC\"},\n { label: \"Carlow\", value:\"CW\"},\n { label: \"Cavan\", value:\"CAV\"},\n { label: \"Clare\", value:\"CE\"},\n { label: \"Cork\", value:\"C\"},\n { label: \"Derry\", value:\"DY\"},\n { label: \"Donegal\", value:\"DL\"},\n { label: \"Down\", value:\"DN\"},\n { label: \"Dublin\", value:\"D\"},\n { label: \"Fermanagh\", value:\"FH\"},\n { label: \"Galway\", value:\"GW\"},\n { label: \"Kerry\", value:\"KY\"},\n { label: \"Kildare\", value:\"KE\"},\n { label: \"Kilkenny\", value:\"KK\"},\n { label: \"Laois\", value:\"LEX\"},\n { label: \"Leitrim\", value:\"LM\"},\n { label: \"Limerick\", value:\"LIM\"},\n { label: \"Longford\", value:\"LD\"},\n { label: \"Louth\", value:\"LH\"},\n { label: \"Mayo\", value:\"MO\"},\n { label: \"Meath\", value:\"MH\"},\n { label: \"Monaghan\", value:\"MN\"},\n { label: \"Offaly\", value:\"OY\"},\n { label: \"Roscommon\", value:\"RN\"},\n { label: \"Sligo\", value:\"SO\"},\n { label: \"Tipperary N\", value:\"TN\"},\n { label: \"Tipperary S\", value:\"TS\"},\n { label: \"Tyrone\", value:\"TE\"},\n { label: \"Waterford\", value:\"WD\"},\n { label: \"Westmeath\", value:\"WH\"},\n { label: \"Wexford\", value:\"WX\"},\n { label: \"Wicklow\", value:\"WIC\"},\n { label:\"---------------------------------------\", value:\" \"},\n { label: \"Anglesey\",value:\"AGY\"},\n { label: \"Breconshire\",value:\"BRE\"},\n { label: \"Caernarvonshire\",value:\"CAE\"},\n { label: \"Cardiganshire\",value:\"CGN\"},\n { label: \"Carmarthenshire\",value:\"CMN\"},\n { label: \"Clwyd\",value:\"CWD\"},\n { label: \"Denbighshire\",value:\"DEN\"},\n { label: \"Dyfed\",value:\"DFD\"},\n { label: \"Flintshire\",value:\"FLN\"},\n { label: \"Glamorgan\",value:\"GLA\"},\n { label: \"Gwent\",value:\"GNT\"},\n { label: \"Gwynedd\",value:\"GWN\"},\n { label: \"Merionethshire\",value:\"MER\"},\n { label: \"Mid Glamorgan\",value:\"MGM\"},\n { label: \"Monmouthshire\",value:\"MON\"},\n { label: \"Montgomeryshire\",value:\"MGY\"},\n { label: \"Pembrokeshire\",value:\"PEM\"},\n { label: \"Powys\",value:\"POW\"},\n { label: \"Radnorshire\",value:\"RAD\"},\n { label: \"South Glamorgan\",value:\"SGM\"},\n { label: \"West Glamorgan\",value:\"WGM\"}\n ]\n },\n {\n country: 'United States Minor Outlying Islands',\n phoneMask: \"999-999-9999\",\n phoneMaskWithExtension: \"999-999-9999 ?99999\",\n mobilePhoneMask: \"999-999-9999\",\n usesStates: true,\n states: [\n { label: \"Abaco\", value: \"AB\"},\n { label: \"Acklins Island\", value: \"AK\"},\n { label: \"Andros\", value: \"AN\"},\n { label: \"Bimini Islands\", value: \"BI\"},\n { label: \"Cat Island\", value: \"CI\"},\n { label: \"Crooked Island\", value: \"CK\"},\n { label: \"Eleuthera\", value: \"EL\"},\n { label: \"Exuma\", value: \"EX\"},\n { label: \"Grand Bahama\", value: \"GB\"},\n { label: \"Harbour Island\", value: \"HB\"},\n { label: \"Inagua\", value: \"IN\"},\n { label: \"Long Island\", value: \"LI\"},\n { label: \"Mayaguana\", value: \"MG\"},\n { label: \"Paradise Island\", value: \"PI\"},\n { label: \"Ragged Island\", value: \"RI\"},\n { label: \"Rum Cay\", value: \"RC\"},\n { label: \"San Salvador\", value: \"SS\"},\n { label: \"Nassau\", value: \"NP\"},\n { label: \"---------------------------------------\", value:\" \"},\n { label: \"Alabama\", value: \"AL\"},\n { label: \"Alaska\", value: \"AK\"},\n { label: \"Arizona\", value: \"AZ\"},\n { label: \"Arkansas\", value: \"AR\"},\n { label: \"California\", value: \"CA\"},\n { label: \"Colorado\", value: \"CO\"},\n { label: \"Connecticut\", value: \"CT\"},\n { label: \"Delaware\", value: \"DE\"},\n { label: \"District Of Columbia\", value: \"DC\"},\n { label: \"Florida\", value: \"FL\"},\n { label: \"Georgia\", value: \"GA\"},\n { label: \"Hawaii\", value: \"HI\"},\n { label: \"Idaho\", value: \"ID\"},\n { label: \"Illinois\", value: \"IL\"},\n { label: \"Indiana\", value: \"IN\"},\n { label: \"Iowa\", value: \"IA\"},\n { label: \"Kansas\", value: \"KS\"},\n { label: \"Kentucky\", value: \"KY\"},\n { label: \"Louisiana\", value: \"LA\"},\n { label: \"Maine\", value: \"ME\"},\n { label: \"Maryland\", value: \"MD\"},\n { label: \"Massachusetts\", value: \"MA\"},\n { label: \"Michigan\", value: \"MI\"},\n { label: \"Minnesota\", value: \"MN\"},\n { label: \"Mississippi\", value: \"MS\"},\n { label: \"Missouri\", value: \"MO\"},\n { label: \"Montana\", value: \"MT\"},\n { label: \"Nebraska\", value: \"NE\"},\n { label: \"Nevada\", value: \"NV\"},\n { label: \"New Hampshire\", value: \"NH\"},\n { label: \"New Jersey\", value: \"NJ\"},\n { label: \"New Mexico\", value: \"NM\"},\n { label: \"New York\", value: \"NY\"},\n { label: \"North Carolina\", value: \"NC\"},\n { label: \"North Dakota\", value: \"ND\"},\n { label: \"Ohio\", value: \"OH\"},\n { label: \"Oklahoma\", value: \"OK\"},\n { label: \"Oregon\", value: \"OR\"},\n { label: \"Pennsylvania\", value: \"PA\"},\n { label: \"Puerto Rico\", value: \"PR\"},\n { label: \"Rhode Island\", value: \"RI\"},\n { label: \"South Carolina\", value: \"SC\"},\n { label: \"South Dakota\", value: \"SD\"},\n { label: \"Tennessee\", value: \"TN\"},\n { label: \"Texas\", value: \"TX\"},\n { label: \"Utah\", value: \"UT\"},\n { label: \"Vermont\", value: \"VT\"},\n { label: \"Virginia\", value: \"VA\"},\n { label: \"Virgin Islands (US)\", value: \"USVI\"},\n { label: \"Virgin Islands (British)\", value: \"BVI\"},\n { label: \"Washington\", value: \"WA\"},\n { label: \"West Virginia\", value: \"WV\"},\n { label: \"Wisconsin\", value: \"WI\"},\n { label: \"Wyoming\", value: \"WY\"},\n { label: \"---------------------------------------\", value: \" \"},\n { label: \"Alberta\", value: \"AB\"},\n { label: \"British Columbia\", value: \"BC\"},\n { label: \"Manitoba\", value: \"MB\"},\n { label: \"New Brunswick\", value: \"NB\"},\n { label: \"Newfoundland and Labrador\", value: \"NL\"},\n { label: \"Northwest Territories\", value: \"NT\"},\n { label: \"Nova Scotia\", value: \"NS\"},\n { label: \"Nunavut\", value: \"NU\"},\n { label: \"Ontario\", value: \"ON\"},\n { label: \"Prince Edward Island\", value: \"PE\"},\n { label: \"Quebec\", value: \"QC\"},\n { label: \"Saskatchewan\", value: \"SK\"},\n { label: \"Yukon\", value: \"YT\"}\n ]\n }\n ])\n\n .constant('CALENDAR_EVENTS', {\n DISPLAY_STORE_HOURS: 'DISPLAY_STORE_HOURS',\n DISPLAY_NON_STORE_HOURS: 'DISPLAY_NON_STORE_HOURS',\n DISPLAY_FITTING_ROOM_BLOCKS: 'DISPLAY_FITTING_ROOM_BLOCKS',\n DISPLAY_AVAILABLE_TIME_BLOCKS: 'DISPLAY_AVAILABLE_TIME_BLOCKS',\n DISPLAY_WORK_SCHEDULE: 'DISPLAY_WORK_SCHEDULE',\n UPDATE_WORK_SCHEDULE: 'UPDATE_WORK_SCHEDULE'\n })\n\n .constant('PERMISSIONS_ORDER', [\n {id:'DASHBOARD', label:'common.modal.home'},\n {id:'APPT', label:'contact.appointments'},\n {id:'INV', label:'item.inventory'},\n {id:'RPT', label:'reports'},\n {id:'ADMN', label:'settings'},\n {id:'CP', label:'settings.account.client-portal'},\n {id:'AC', label:'settings.header.activities'},\n {id:'XX', label:'settings.header.contacts'},\n {id:'INT', label:'settings.header.integrations'},\n {id:'POS', label:'settings.header.point-of-sale'},\n {id:'QT', label:'quote.quotes', validate:[{ type: '$rootScope', field: 'isQuoteEnabled' }] },\n {id:'PP', label:'settings.payment-plans.title'},\n {id:'PRCH', label:'settings.header.purchasing'},\n {id:'MKT', label:'settings.role.label.marketplace'},\n {id:'MT', label:'settings.role.label.online-tools'},\n {id:'RGST', label:'settings.role.label.registry'}\n\n ]);\n});\n\n","// Underscore.js 1.8.3\n// http://underscorejs.org\n// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n// Underscore may be freely distributed under the MIT license.\n\n(function() {\n\n // Baseline setup\n // --------------\n\n // Establish the root object, `window` in the browser, or `exports` on the server.\n var root = this;\n\n // Save the previous value of the `_` variable.\n var previousUnderscore = root._;\n\n // Save bytes in the minified (but not gzipped) version:\n var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;\n\n // Create quick reference variables for speed access to core prototypes.\n var\n push = ArrayProto.push,\n slice = ArrayProto.slice,\n toString = ObjProto.toString,\n hasOwnProperty = ObjProto.hasOwnProperty;\n\n // All **ECMAScript 5** native function implementations that we hope to use\n // are declared here.\n var\n nativeIsArray = Array.isArray,\n nativeKeys = Object.keys,\n nativeBind = FuncProto.bind,\n nativeCreate = Object.create;\n\n // Naked function reference for surrogate-prototype-swapping.\n var Ctor = function(){};\n\n // Create a safe reference to the Underscore object for use below.\n var _ = function(obj) {\n if (obj instanceof _) return obj;\n if (!(this instanceof _)) return new _(obj);\n this._wrapped = obj;\n };\n\n // Export the Underscore object for **Node.js**, with\n // backwards-compatibility for the old `require()` API. If we're in\n // the browser, add `_` as a global object.\n if (typeof exports !== 'undefined') {\n if (typeof module !== 'undefined' && module.exports) {\n exports = module.exports = _;\n }\n exports._ = _;\n } else {\n root._ = _;\n }\n\n // Current version.\n _.VERSION = '1.8.3';\n\n // Internal function that returns an efficient (for current engines) version\n // of the passed-in callback, to be repeatedly applied in other Underscore\n // functions.\n var optimizeCb = function(func, context, argCount) {\n if (context === void 0) return func;\n switch (argCount == null ? 3 : argCount) {\n case 1: return function(value) {\n return func.call(context, value);\n };\n case 2: return function(value, other) {\n return func.call(context, value, other);\n };\n case 3: return function(value, index, collection) {\n return func.call(context, value, index, collection);\n };\n case 4: return function(accumulator, value, index, collection) {\n return func.call(context, accumulator, value, index, collection);\n };\n }\n return function() {\n return func.apply(context, arguments);\n };\n };\n\n // A mostly-internal function to generate callbacks that can be applied\n // to each element in a collection, returning the desired result — either\n // identity, an arbitrary callback, a property matcher, or a property accessor.\n var cb = function(value, context, argCount) {\n if (value == null) return _.identity;\n if (_.isFunction(value)) return optimizeCb(value, context, argCount);\n if (_.isObject(value)) return _.matcher(value);\n return _.property(value);\n };\n _.iteratee = function(value, context) {\n return cb(value, context, Infinity);\n };\n\n // An internal function for creating assigner functions.\n var createAssigner = function(keysFunc, undefinedOnly) {\n return function(obj) {\n var length = arguments.length;\n if (length < 2 || obj == null) return obj;\n for (var index = 1; index < length; index++) {\n var source = arguments[index],\n keys = keysFunc(source),\n l = keys.length;\n for (var i = 0; i < l; i++) {\n var key = keys[i];\n if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];\n }\n }\n return obj;\n };\n };\n\n // An internal function for creating a new object that inherits from another.\n var baseCreate = function(prototype) {\n if (!_.isObject(prototype)) return {};\n if (nativeCreate) return nativeCreate(prototype);\n Ctor.prototype = prototype;\n var result = new Ctor;\n Ctor.prototype = null;\n return result;\n };\n\n var property = function(key) {\n return function(obj) {\n return obj == null ? void 0 : obj[key];\n };\n };\n\n // Helper for collection methods to determine whether a collection\n // should be iterated as an array or as an object\n // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength\n // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094\n var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;\n var getLength = property('length');\n var isArrayLike = function(collection) {\n var length = getLength(collection);\n return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;\n };\n\n // Collection Functions\n // --------------------\n\n // The cornerstone, an `each` implementation, aka `forEach`.\n // Handles raw objects in addition to array-likes. Treats all\n // sparse array-likes as if they were dense.\n _.each = _.forEach = function(obj, iteratee, context) {\n iteratee = optimizeCb(iteratee, context);\n var i, length;\n if (isArrayLike(obj)) {\n for (i = 0, length = obj.length; i < length; i++) {\n iteratee(obj[i], i, obj);\n }\n } else {\n var keys = _.keys(obj);\n for (i = 0, length = keys.length; i < length; i++) {\n iteratee(obj[keys[i]], keys[i], obj);\n }\n }\n return obj;\n };\n\n // Return the results of applying the iteratee to each element.\n _.map = _.collect = function(obj, iteratee, context) {\n iteratee = cb(iteratee, context);\n var keys = !isArrayLike(obj) && _.keys(obj),\n length = (keys || obj).length,\n results = Array(length);\n for (var index = 0; index < length; index++) {\n var currentKey = keys ? keys[index] : index;\n results[index] = iteratee(obj[currentKey], currentKey, obj);\n }\n return results;\n };\n\n // Create a reducing function iterating left or right.\n function createReduce(dir) {\n // Optimized iterator function as using arguments.length\n // in the main function will deoptimize the, see #1991.\n function iterator(obj, iteratee, memo, keys, index, length) {\n for (; index >= 0 && index < length; index += dir) {\n var currentKey = keys ? keys[index] : index;\n memo = iteratee(memo, obj[currentKey], currentKey, obj);\n }\n return memo;\n }\n\n return function(obj, iteratee, memo, context) {\n iteratee = optimizeCb(iteratee, context, 4);\n var keys = !isArrayLike(obj) && _.keys(obj),\n length = (keys || obj).length,\n index = dir > 0 ? 0 : length - 1;\n // Determine the initial value if none is provided.\n if (arguments.length < 3) {\n memo = obj[keys ? keys[index] : index];\n index += dir;\n }\n return iterator(obj, iteratee, memo, keys, index, length);\n };\n }\n\n // **Reduce** builds up a single result from a list of values, aka `inject`,\n // or `foldl`.\n _.reduce = _.foldl = _.inject = createReduce(1);\n\n // The right-associative version of reduce, also known as `foldr`.\n _.reduceRight = _.foldr = createReduce(-1);\n\n // Return the first value which passes a truth test. Aliased as `detect`.\n _.find = _.detect = function(obj, predicate, context) {\n var key;\n if (isArrayLike(obj)) {\n key = _.findIndex(obj, predicate, context);\n } else {\n key = _.findKey(obj, predicate, context);\n }\n if (key !== void 0 && key !== -1) return obj[key];\n };\n\n // Return all the elements that pass a truth test.\n // Aliased as `select`.\n _.filter = _.select = function(obj, predicate, context) {\n var results = [];\n predicate = cb(predicate, context);\n _.each(obj, function(value, index, list) {\n if (predicate(value, index, list)) results.push(value);\n });\n return results;\n };\n\n // Return all the elements for which a truth test fails.\n _.reject = function(obj, predicate, context) {\n return _.filter(obj, _.negate(cb(predicate)), context);\n };\n\n // Determine whether all of the elements match a truth test.\n // Aliased as `all`.\n _.every = _.all = function(obj, predicate, context) {\n predicate = cb(predicate, context);\n var keys = !isArrayLike(obj) && _.keys(obj),\n length = (keys || obj).length;\n for (var index = 0; index < length; index++) {\n var currentKey = keys ? keys[index] : index;\n if (!predicate(obj[currentKey], currentKey, obj)) return false;\n }\n return true;\n };\n\n // Determine if at least one element in the object matches a truth test.\n // Aliased as `any`.\n _.some = _.any = function(obj, predicate, context) {\n predicate = cb(predicate, context);\n var keys = !isArrayLike(obj) && _.keys(obj),\n length = (keys || obj).length;\n for (var index = 0; index < length; index++) {\n var currentKey = keys ? keys[index] : index;\n if (predicate(obj[currentKey], currentKey, obj)) return true;\n }\n return false;\n };\n\n // Determine if the array or object contains a given item (using `===`).\n // Aliased as `includes` and `include`.\n _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {\n if (!isArrayLike(obj)) obj = _.values(obj);\n if (typeof fromIndex != 'number' || guard) fromIndex = 0;\n return _.indexOf(obj, item, fromIndex) >= 0;\n };\n\n // Invoke a method (with arguments) on every item in a collection.\n _.invoke = function(obj, method) {\n var args = slice.call(arguments, 2);\n var isFunc = _.isFunction(method);\n return _.map(obj, function(value) {\n var func = isFunc ? method : value[method];\n return func == null ? func : func.apply(value, args);\n });\n };\n\n // Convenience version of a common use case of `map`: fetching a property.\n _.pluck = function(obj, key) {\n return _.map(obj, _.property(key));\n };\n\n // Convenience version of a common use case of `filter`: selecting only objects\n // containing specific `key:value` pairs.\n _.where = function(obj, attrs) {\n return _.filter(obj, _.matcher(attrs));\n };\n\n // Convenience version of a common use case of `find`: getting the first object\n // containing specific `key:value` pairs.\n _.findWhere = function(obj, attrs) {\n return _.find(obj, _.matcher(attrs));\n };\n\n // Return the maximum element (or element-based computation).\n _.max = function(obj, iteratee, context) {\n var result = -Infinity, lastComputed = -Infinity,\n value, computed;\n if (iteratee == null && obj != null) {\n obj = isArrayLike(obj) ? obj : _.values(obj);\n for (var i = 0, length = obj.length; i < length; i++) {\n value = obj[i];\n if (value > result) {\n result = value;\n }\n }\n } else {\n iteratee = cb(iteratee, context);\n _.each(obj, function(value, index, list) {\n computed = iteratee(value, index, list);\n if (computed > lastComputed || computed === -Infinity && result === -Infinity) {\n result = value;\n lastComputed = computed;\n }\n });\n }\n return result;\n };\n\n // Return the minimum element (or element-based computation).\n _.min = function(obj, iteratee, context) {\n var result = Infinity, lastComputed = Infinity,\n value, computed;\n if (iteratee == null && obj != null) {\n obj = isArrayLike(obj) ? obj : _.values(obj);\n for (var i = 0, length = obj.length; i < length; i++) {\n value = obj[i];\n if (value < result) {\n result = value;\n }\n }\n } else {\n iteratee = cb(iteratee, context);\n _.each(obj, function(value, index, list) {\n computed = iteratee(value, index, list);\n if (computed < lastComputed || computed === Infinity && result === Infinity) {\n result = value;\n lastComputed = computed;\n }\n });\n }\n return result;\n };\n\n // Shuffle a collection, using the modern version of the\n // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).\n _.shuffle = function(obj) {\n var set = isArrayLike(obj) ? obj : _.values(obj);\n var length = set.length;\n var shuffled = Array(length);\n for (var index = 0, rand; index < length; index++) {\n rand = _.random(0, index);\n if (rand !== index) shuffled[index] = shuffled[rand];\n shuffled[rand] = set[index];\n }\n return shuffled;\n };\n\n // Sample **n** random values from a collection.\n // If **n** is not specified, returns a single random element.\n // The internal `guard` argument allows it to work with `map`.\n _.sample = function(obj, n, guard) {\n if (n == null || guard) {\n if (!isArrayLike(obj)) obj = _.values(obj);\n return obj[_.random(obj.length - 1)];\n }\n return _.shuffle(obj).slice(0, Math.max(0, n));\n };\n\n // Sort the object's values by a criterion produced by an iteratee.\n _.sortBy = function(obj, iteratee, context) {\n iteratee = cb(iteratee, context);\n return _.pluck(_.map(obj, function(value, index, list) {\n return {\n value: value,\n index: index,\n criteria: iteratee(value, index, list)\n };\n }).sort(function(left, right) {\n var a = left.criteria;\n var b = right.criteria;\n if (a !== b) {\n if (a > b || a === void 0) return 1;\n if (a < b || b === void 0) return -1;\n }\n return left.index - right.index;\n }), 'value');\n };\n\n // An internal function used for aggregate \"group by\" operations.\n var group = function(behavior) {\n return function(obj, iteratee, context) {\n var result = {};\n iteratee = cb(iteratee, context);\n _.each(obj, function(value, index) {\n var key = iteratee(value, index, obj);\n behavior(result, value, key);\n });\n return result;\n };\n };\n\n // Groups the object's values by a criterion. Pass either a string attribute\n // to group by, or a function that returns the criterion.\n _.groupBy = group(function(result, value, key) {\n if (_.has(result, key)) result[key].push(value); else result[key] = [value];\n });\n\n // Indexes the object's values by a criterion, similar to `groupBy`, but for\n // when you know that your index values will be unique.\n _.indexBy = group(function(result, value, key) {\n result[key] = value;\n });\n\n // Counts instances of an object that group by a certain criterion. Pass\n // either a string attribute to count by, or a function that returns the\n // criterion.\n _.countBy = group(function(result, value, key) {\n if (_.has(result, key)) result[key]++; else result[key] = 1;\n });\n\n // Safely create a real, live array from anything iterable.\n _.toArray = function(obj) {\n if (!obj) return [];\n if (_.isArray(obj)) return slice.call(obj);\n if (isArrayLike(obj)) return _.map(obj, _.identity);\n return _.values(obj);\n };\n\n // Return the number of elements in an object.\n _.size = function(obj) {\n if (obj == null) return 0;\n return isArrayLike(obj) ? obj.length : _.keys(obj).length;\n };\n\n // Split a collection into two arrays: one whose elements all satisfy the given\n // predicate, and one whose elements all do not satisfy the predicate.\n _.partition = function(obj, predicate, context) {\n predicate = cb(predicate, context);\n var pass = [], fail = [];\n _.each(obj, function(value, key, obj) {\n (predicate(value, key, obj) ? pass : fail).push(value);\n });\n return [pass, fail];\n };\n\n // Array Functions\n // ---------------\n\n // Get the first element of an array. Passing **n** will return the first N\n // values in the array. Aliased as `head` and `take`. The **guard** check\n // allows it to work with `_.map`.\n _.first = _.head = _.take = function(array, n, guard) {\n if (array == null) return void 0;\n if (n == null || guard) return array[0];\n return _.initial(array, array.length - n);\n };\n\n // Returns everything but the last entry of the array. Especially useful on\n // the arguments object. Passing **n** will return all the values in\n // the array, excluding the last N.\n _.initial = function(array, n, guard) {\n return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));\n };\n\n // Get the last element of an array. Passing **n** will return the last N\n // values in the array.\n _.last = function(array, n, guard) {\n if (array == null) return void 0;\n if (n == null || guard) return array[array.length - 1];\n return _.rest(array, Math.max(0, array.length - n));\n };\n\n // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.\n // Especially useful on the arguments object. Passing an **n** will return\n // the rest N values in the array.\n _.rest = _.tail = _.drop = function(array, n, guard) {\n return slice.call(array, n == null || guard ? 1 : n);\n };\n\n // Trim out all falsy values from an array.\n _.compact = function(array) {\n return _.filter(array, _.identity);\n };\n\n // Internal implementation of a recursive `flatten` function.\n var flatten = function(input, shallow, strict, startIndex) {\n var output = [], idx = 0;\n for (var i = startIndex || 0, length = getLength(input); i < length; i++) {\n var value = input[i];\n if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {\n //flatten current level of array or arguments object\n if (!shallow) value = flatten(value, shallow, strict);\n var j = 0, len = value.length;\n output.length += len;\n while (j < len) {\n output[idx++] = value[j++];\n }\n } else if (!strict) {\n output[idx++] = value;\n }\n }\n return output;\n };\n\n // Flatten out an array, either recursively (by default), or just one level.\n _.flatten = function(array, shallow) {\n return flatten(array, shallow, false);\n };\n\n // Return a version of the array that does not contain the specified value(s).\n _.without = function(array) {\n return _.difference(array, slice.call(arguments, 1));\n };\n\n // Produce a duplicate-free version of the array. If the array has already\n // been sorted, you have the option of using a faster algorithm.\n // Aliased as `unique`.\n _.uniq = _.unique = function(array, isSorted, iteratee, context) {\n if (!_.isBoolean(isSorted)) {\n context = iteratee;\n iteratee = isSorted;\n isSorted = false;\n }\n if (iteratee != null) iteratee = cb(iteratee, context);\n var result = [];\n var seen = [];\n for (var i = 0, length = getLength(array); i < length; i++) {\n var value = array[i],\n computed = iteratee ? iteratee(value, i, array) : value;\n if (isSorted) {\n if (!i || seen !== computed) result.push(value);\n seen = computed;\n } else if (iteratee) {\n if (!_.contains(seen, computed)) {\n seen.push(computed);\n result.push(value);\n }\n } else if (!_.contains(result, value)) {\n result.push(value);\n }\n }\n return result;\n };\n\n // Produce an array that contains the union: each distinct element from all of\n // the passed-in arrays.\n _.union = function() {\n return _.uniq(flatten(arguments, true, true));\n };\n\n // Produce an array that contains every item shared between all the\n // passed-in arrays.\n _.intersection = function(array) {\n var result = [];\n var argsLength = arguments.length;\n for (var i = 0, length = getLength(array); i < length; i++) {\n var item = array[i];\n if (_.contains(result, item)) continue;\n for (var j = 1; j < argsLength; j++) {\n if (!_.contains(arguments[j], item)) break;\n }\n if (j === argsLength) result.push(item);\n }\n return result;\n };\n\n // Take the difference between one array and a number of other arrays.\n // Only the elements present in just the first array will remain.\n _.difference = function(array) {\n var rest = flatten(arguments, true, true, 1);\n return _.filter(array, function(value){\n return !_.contains(rest, value);\n });\n };\n\n // Zip together multiple lists into a single array -- elements that share\n // an index go together.\n _.zip = function() {\n return _.unzip(arguments);\n };\n\n // Complement of _.zip. Unzip accepts an array of arrays and groups\n // each array's elements on shared indices\n _.unzip = function(array) {\n var length = array && _.max(array, getLength).length || 0;\n var result = Array(length);\n\n for (var index = 0; index < length; index++) {\n result[index] = _.pluck(array, index);\n }\n return result;\n };\n\n // Converts lists into objects. Pass either a single array of `[key, value]`\n // pairs, or two parallel arrays of the same length -- one of keys, and one of\n // the corresponding values.\n _.object = function(list, values) {\n var result = {};\n for (var i = 0, length = getLength(list); i < length; i++) {\n if (values) {\n result[list[i]] = values[i];\n } else {\n result[list[i][0]] = list[i][1];\n }\n }\n return result;\n };\n\n // Generator function to create the findIndex and findLastIndex functions\n function createPredicateIndexFinder(dir) {\n return function(array, predicate, context) {\n predicate = cb(predicate, context);\n var length = getLength(array);\n var index = dir > 0 ? 0 : length - 1;\n for (; index >= 0 && index < length; index += dir) {\n if (predicate(array[index], index, array)) return index;\n }\n return -1;\n };\n }\n\n // Returns the first index on an array-like that passes a predicate test\n _.findIndex = createPredicateIndexFinder(1);\n _.findLastIndex = createPredicateIndexFinder(-1);\n\n // Use a comparator function to figure out the smallest index at which\n // an object should be inserted so as to maintain order. Uses binary search.\n _.sortedIndex = function(array, obj, iteratee, context) {\n iteratee = cb(iteratee, context, 1);\n var value = iteratee(obj);\n var low = 0, high = getLength(array);\n while (low < high) {\n var mid = Math.floor((low + high) / 2);\n if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;\n }\n return low;\n };\n\n // Generator function to create the indexOf and lastIndexOf functions\n function createIndexFinder(dir, predicateFind, sortedIndex) {\n return function(array, item, idx) {\n var i = 0, length = getLength(array);\n if (typeof idx == 'number') {\n if (dir > 0) {\n i = idx >= 0 ? idx : Math.max(idx + length, i);\n } else {\n length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;\n }\n } else if (sortedIndex && idx && length) {\n idx = sortedIndex(array, item);\n return array[idx] === item ? idx : -1;\n }\n if (item !== item) {\n idx = predicateFind(slice.call(array, i, length), _.isNaN);\n return idx >= 0 ? idx + i : -1;\n }\n for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {\n if (array[idx] === item) return idx;\n }\n return -1;\n };\n }\n\n // Return the position of the first occurrence of an item in an array,\n // or -1 if the item is not included in the array.\n // If the array is large and already in sort order, pass `true`\n // for **isSorted** to use binary search.\n _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);\n _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);\n\n // Generate an integer Array containing an arithmetic progression. A port of\n // the native Python `range()` function. See\n // [the Python documentation](http://docs.python.org/library/functions.html#range).\n _.range = function(start, stop, step) {\n if (stop == null) {\n stop = start || 0;\n start = 0;\n }\n step = step || 1;\n\n var length = Math.max(Math.ceil((stop - start) / step), 0);\n var range = Array(length);\n\n for (var idx = 0; idx < length; idx++, start += step) {\n range[idx] = start;\n }\n\n return range;\n };\n\n // Function (ahem) Functions\n // ------------------\n\n // Determines whether to execute a function as a constructor\n // or a normal function with the provided arguments\n var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {\n if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);\n var self = baseCreate(sourceFunc.prototype);\n var result = sourceFunc.apply(self, args);\n if (_.isObject(result)) return result;\n return self;\n };\n\n // Create a function bound to a given object (assigning `this`, and arguments,\n // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if\n // available.\n _.bind = function(func, context) {\n if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));\n if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');\n var args = slice.call(arguments, 2);\n var bound = function() {\n return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));\n };\n return bound;\n };\n\n // Partially apply a function by creating a version that has had some of its\n // arguments pre-filled, without changing its dynamic `this` context. _ acts\n // as a placeholder, allowing any combination of arguments to be pre-filled.\n _.partial = function(func) {\n var boundArgs = slice.call(arguments, 1);\n var bound = function() {\n var position = 0, length = boundArgs.length;\n var args = Array(length);\n for (var i = 0; i < length; i++) {\n args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];\n }\n while (position < arguments.length) args.push(arguments[position++]);\n return executeBound(func, bound, this, this, args);\n };\n return bound;\n };\n\n // Bind a number of an object's methods to that object. Remaining arguments\n // are the method names to be bound. Useful for ensuring that all callbacks\n // defined on an object belong to it.\n _.bindAll = function(obj) {\n var i, length = arguments.length, key;\n if (length <= 1) throw new Error('bindAll must be passed function names');\n for (i = 1; i < length; i++) {\n key = arguments[i];\n obj[key] = _.bind(obj[key], obj);\n }\n return obj;\n };\n\n // Memoize an expensive function by storing its results.\n _.memoize = function(func, hasher) {\n var memoize = function(key) {\n var cache = memoize.cache;\n var address = '' + (hasher ? hasher.apply(this, arguments) : key);\n if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);\n return cache[address];\n };\n memoize.cache = {};\n return memoize;\n };\n\n // Delays a function for the given number of milliseconds, and then calls\n // it with the arguments supplied.\n _.delay = function(func, wait) {\n var args = slice.call(arguments, 2);\n return setTimeout(function(){\n return func.apply(null, args);\n }, wait);\n };\n\n // Defers a function, scheduling it to run after the current call stack has\n // cleared.\n _.defer = _.partial(_.delay, _, 1);\n\n // Returns a function, that, when invoked, will only be triggered at most once\n // during a given window of time. Normally, the throttled function will run\n // as much as it can, without ever going more than once per `wait` duration;\n // but if you'd like to disable the execution on the leading edge, pass\n // `{leading: false}`. To disable execution on the trailing edge, ditto.\n _.throttle = function(func, wait, options) {\n var context, args, result;\n var timeout = null;\n var previous = 0;\n if (!options) options = {};\n var later = function() {\n previous = options.leading === false ? 0 : _.now();\n timeout = null;\n result = func.apply(context, args);\n if (!timeout) context = args = null;\n };\n return function() {\n var now = _.now();\n if (!previous && options.leading === false) previous = now;\n var remaining = wait - (now - previous);\n context = this;\n args = arguments;\n if (remaining <= 0 || remaining > wait) {\n if (timeout) {\n clearTimeout(timeout);\n timeout = null;\n }\n previous = now;\n result = func.apply(context, args);\n if (!timeout) context = args = null;\n } else if (!timeout && options.trailing !== false) {\n timeout = setTimeout(later, remaining);\n }\n return result;\n };\n };\n\n // Returns a function, that, as long as it continues to be invoked, will not\n // be triggered. The function will be called after it stops being called for\n // N milliseconds. If `immediate` is passed, trigger the function on the\n // leading edge, instead of the trailing.\n _.debounce = function(func, wait, immediate) {\n var timeout, args, context, timestamp, result;\n\n var later = function() {\n var last = _.now() - timestamp;\n\n if (last < wait && last >= 0) {\n timeout = setTimeout(later, wait - last);\n } else {\n timeout = null;\n if (!immediate) {\n result = func.apply(context, args);\n if (!timeout) context = args = null;\n }\n }\n };\n\n return function() {\n context = this;\n args = arguments;\n timestamp = _.now();\n var callNow = immediate && !timeout;\n if (!timeout) timeout = setTimeout(later, wait);\n if (callNow) {\n result = func.apply(context, args);\n context = args = null;\n }\n\n return result;\n };\n };\n\n // Returns the first function passed as an argument to the second,\n // allowing you to adjust arguments, run code before and after, and\n // conditionally execute the original function.\n _.wrap = function(func, wrapper) {\n return _.partial(wrapper, func);\n };\n\n // Returns a negated version of the passed-in predicate.\n _.negate = function(predicate) {\n return function() {\n return !predicate.apply(this, arguments);\n };\n };\n\n // Returns a function that is the composition of a list of functions, each\n // consuming the return value of the function that follows.\n _.compose = function() {\n var args = arguments;\n var start = args.length - 1;\n return function() {\n var i = start;\n var result = args[start].apply(this, arguments);\n while (i--) result = args[i].call(this, result);\n return result;\n };\n };\n\n // Returns a function that will only be executed on and after the Nth call.\n _.after = function(times, func) {\n return function() {\n if (--times < 1) {\n return func.apply(this, arguments);\n }\n };\n };\n\n // Returns a function that will only be executed up to (but not including) the Nth call.\n _.before = function(times, func) {\n var memo;\n return function() {\n if (--times > 0) {\n memo = func.apply(this, arguments);\n }\n if (times <= 1) func = null;\n return memo;\n };\n };\n\n // Returns a function that will be executed at most one time, no matter how\n // often you call it. Useful for lazy initialization.\n _.once = _.partial(_.before, 2);\n\n // Object Functions\n // ----------------\n\n // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.\n var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');\n var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',\n 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];\n\n function collectNonEnumProps(obj, keys) {\n var nonEnumIdx = nonEnumerableProps.length;\n var constructor = obj.constructor;\n var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;\n\n // Constructor is a special case.\n var prop = 'constructor';\n if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);\n\n while (nonEnumIdx--) {\n prop = nonEnumerableProps[nonEnumIdx];\n if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {\n keys.push(prop);\n }\n }\n }\n\n // Retrieve the names of an object's own properties.\n // Delegates to **ECMAScript 5**'s native `Object.keys`\n _.keys = function(obj) {\n if (!_.isObject(obj)) return [];\n if (nativeKeys) return nativeKeys(obj);\n var keys = [];\n for (var key in obj) if (_.has(obj, key)) keys.push(key);\n // Ahem, IE < 9.\n if (hasEnumBug) collectNonEnumProps(obj, keys);\n return keys;\n };\n\n // Retrieve all the property names of an object.\n _.allKeys = function(obj) {\n if (!_.isObject(obj)) return [];\n var keys = [];\n for (var key in obj) keys.push(key);\n // Ahem, IE < 9.\n if (hasEnumBug) collectNonEnumProps(obj, keys);\n return keys;\n };\n\n // Retrieve the values of an object's properties.\n _.values = function(obj) {\n var keys = _.keys(obj);\n var length = keys.length;\n var values = Array(length);\n for (var i = 0; i < length; i++) {\n values[i] = obj[keys[i]];\n }\n return values;\n };\n\n // Returns the results of applying the iteratee to each element of the object\n // In contrast to _.map it returns an object\n _.mapObject = function(obj, iteratee, context) {\n iteratee = cb(iteratee, context);\n var keys = _.keys(obj),\n length = keys.length,\n results = {},\n currentKey;\n for (var index = 0; index < length; index++) {\n currentKey = keys[index];\n results[currentKey] = iteratee(obj[currentKey], currentKey, obj);\n }\n return results;\n };\n\n // Convert an object into a list of `[key, value]` pairs.\n _.pairs = function(obj) {\n var keys = _.keys(obj);\n var length = keys.length;\n var pairs = Array(length);\n for (var i = 0; i < length; i++) {\n pairs[i] = [keys[i], obj[keys[i]]];\n }\n return pairs;\n };\n\n // Invert the keys and values of an object. The values must be serializable.\n _.invert = function(obj) {\n var result = {};\n var keys = _.keys(obj);\n for (var i = 0, length = keys.length; i < length; i++) {\n result[obj[keys[i]]] = keys[i];\n }\n return result;\n };\n\n // Return a sorted list of the function names available on the object.\n // Aliased as `methods`\n _.functions = _.methods = function(obj) {\n var names = [];\n for (var key in obj) {\n if (_.isFunction(obj[key])) names.push(key);\n }\n return names.sort();\n };\n\n // Extend a given object with all the properties in passed-in object(s).\n _.extend = createAssigner(_.allKeys);\n\n // Assigns a given object with all the own properties in the passed-in object(s)\n // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)\n _.extendOwn = _.assign = createAssigner(_.keys);\n\n // Returns the first key on an object that passes a predicate test\n _.findKey = function(obj, predicate, context) {\n predicate = cb(predicate, context);\n var keys = _.keys(obj), key;\n for (var i = 0, length = keys.length; i < length; i++) {\n key = keys[i];\n if (predicate(obj[key], key, obj)) return key;\n }\n };\n\n // Return a copy of the object only containing the whitelisted properties.\n _.pick = function(object, oiteratee, context) {\n var result = {}, obj = object, iteratee, keys;\n if (obj == null) return result;\n if (_.isFunction(oiteratee)) {\n keys = _.allKeys(obj);\n iteratee = optimizeCb(oiteratee, context);\n } else {\n keys = flatten(arguments, false, false, 1);\n iteratee = function(value, key, obj) { return key in obj; };\n obj = Object(obj);\n }\n for (var i = 0, length = keys.length; i < length; i++) {\n var key = keys[i];\n var value = obj[key];\n if (iteratee(value, key, obj)) result[key] = value;\n }\n return result;\n };\n\n // Return a copy of the object without the blacklisted properties.\n _.omit = function(obj, iteratee, context) {\n if (_.isFunction(iteratee)) {\n iteratee = _.negate(iteratee);\n } else {\n var keys = _.map(flatten(arguments, false, false, 1), String);\n iteratee = function(value, key) {\n return !_.contains(keys, key);\n };\n }\n return _.pick(obj, iteratee, context);\n };\n\n // Fill in a given object with default properties.\n _.defaults = createAssigner(_.allKeys, true);\n\n // Creates an object that inherits from the given prototype object.\n // If additional properties are provided then they will be added to the\n // created object.\n _.create = function(prototype, props) {\n var result = baseCreate(prototype);\n if (props) _.extendOwn(result, props);\n return result;\n };\n\n // Create a (shallow-cloned) duplicate of an object.\n _.clone = function(obj) {\n if (!_.isObject(obj)) return obj;\n return _.isArray(obj) ? obj.slice() : _.extend({}, obj);\n };\n\n // Invokes interceptor with the obj, and then returns obj.\n // The primary purpose of this method is to \"tap into\" a method chain, in\n // order to perform operations on intermediate results within the chain.\n _.tap = function(obj, interceptor) {\n interceptor(obj);\n return obj;\n };\n\n // Returns whether an object has a given set of `key:value` pairs.\n _.isMatch = function(object, attrs) {\n var keys = _.keys(attrs), length = keys.length;\n if (object == null) return !length;\n var obj = Object(object);\n for (var i = 0; i < length; i++) {\n var key = keys[i];\n if (attrs[key] !== obj[key] || !(key in obj)) return false;\n }\n return true;\n };\n\n\n // Internal recursive comparison function for `isEqual`.\n var eq = function(a, b, aStack, bStack) {\n // Identical objects are equal. `0 === -0`, but they aren't identical.\n // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).\n if (a === b) return a !== 0 || 1 / a === 1 / b;\n // A strict comparison is necessary because `null == undefined`.\n if (a == null || b == null) return a === b;\n // Unwrap any wrapped objects.\n if (a instanceof _) a = a._wrapped;\n if (b instanceof _) b = b._wrapped;\n // Compare `[[Class]]` names.\n var className = toString.call(a);\n if (className !== toString.call(b)) return false;\n switch (className) {\n // Strings, numbers, regular expressions, dates, and booleans are compared by value.\n case '[object RegExp]':\n // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')\n case '[object String]':\n // Primitives and their corresponding object wrappers are equivalent; thus, `\"5\"` is\n // equivalent to `new String(\"5\")`.\n return '' + a === '' + b;\n case '[object Number]':\n // `NaN`s are equivalent, but non-reflexive.\n // Object(NaN) is equivalent to NaN\n if (+a !== +a) return +b !== +b;\n // An `egal` comparison is performed for other numeric values.\n return +a === 0 ? 1 / +a === 1 / b : +a === +b;\n case '[object Date]':\n case '[object Boolean]':\n // Coerce dates and booleans to numeric primitive values. Dates are compared by their\n // millisecond representations. Note that invalid dates with millisecond representations\n // of `NaN` are not equivalent.\n return +a === +b;\n }\n\n var areArrays = className === '[object Array]';\n if (!areArrays) {\n if (typeof a != 'object' || typeof b != 'object') return false;\n\n // Objects with different constructors are not equivalent, but `Object`s or `Array`s\n // from different frames are.\n var aCtor = a.constructor, bCtor = b.constructor;\n if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&\n _.isFunction(bCtor) && bCtor instanceof bCtor)\n && ('constructor' in a && 'constructor' in b)) {\n return false;\n }\n }\n // Assume equality for cyclic structures. The algorithm for detecting cyclic\n // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.\n\n // Initializing stack of traversed objects.\n // It's done here since we only need them for objects and arrays comparison.\n aStack = aStack || [];\n bStack = bStack || [];\n var length = aStack.length;\n while (length--) {\n // Linear search. Performance is inversely proportional to the number of\n // unique nested structures.\n if (aStack[length] === a) return bStack[length] === b;\n }\n\n // Add the first object to the stack of traversed objects.\n aStack.push(a);\n bStack.push(b);\n\n // Recursively compare objects and arrays.\n if (areArrays) {\n // Compare array lengths to determine if a deep comparison is necessary.\n length = a.length;\n if (length !== b.length) return false;\n // Deep compare the contents, ignoring non-numeric properties.\n while (length--) {\n if (!eq(a[length], b[length], aStack, bStack)) return false;\n }\n } else {\n // Deep compare objects.\n var keys = _.keys(a), key;\n length = keys.length;\n // Ensure that both objects contain the same number of properties before comparing deep equality.\n if (_.keys(b).length !== length) return false;\n while (length--) {\n // Deep compare each member\n key = keys[length];\n if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;\n }\n }\n // Remove the first object from the stack of traversed objects.\n aStack.pop();\n bStack.pop();\n return true;\n };\n\n // Perform a deep comparison to check if two objects are equal.\n _.isEqual = function(a, b) {\n return eq(a, b);\n };\n\n // Is a given array, string, or object empty?\n // An \"empty\" object has no enumerable own-properties.\n _.isEmpty = function(obj) {\n if (obj == null) return true;\n if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;\n return _.keys(obj).length === 0;\n };\n\n // Is a given value a DOM element?\n _.isElement = function(obj) {\n return !!(obj && obj.nodeType === 1);\n };\n\n // Is a given value an array?\n // Delegates to ECMA5's native Array.isArray\n _.isArray = nativeIsArray || function(obj) {\n return toString.call(obj) === '[object Array]';\n };\n\n // Is a given variable an object?\n _.isObject = function(obj) {\n var type = typeof obj;\n return type === 'function' || type === 'object' && !!obj;\n };\n\n // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.\n _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {\n _['is' + name] = function(obj) {\n return toString.call(obj) === '[object ' + name + ']';\n };\n });\n\n // Define a fallback version of the method in browsers (ahem, IE < 9), where\n // there isn't any inspectable \"Arguments\" type.\n if (!_.isArguments(arguments)) {\n _.isArguments = function(obj) {\n return _.has(obj, 'callee');\n };\n }\n\n // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,\n // IE 11 (#1621), and in Safari 8 (#1929).\n if (typeof /./ != 'function' && typeof Int8Array != 'object') {\n _.isFunction = function(obj) {\n return typeof obj == 'function' || false;\n };\n }\n\n // Is a given object a finite number?\n _.isFinite = function(obj) {\n return isFinite(obj) && !isNaN(parseFloat(obj));\n };\n\n // Is the given value `NaN`? (NaN is the only number which does not equal itself).\n _.isNaN = function(obj) {\n return _.isNumber(obj) && obj !== +obj;\n };\n\n // Is a given value a boolean?\n _.isBoolean = function(obj) {\n return obj === true || obj === false || toString.call(obj) === '[object Boolean]';\n };\n\n // Is a given value equal to null?\n _.isNull = function(obj) {\n return obj === null;\n };\n\n // Is a given variable undefined?\n _.isUndefined = function(obj) {\n return obj === void 0;\n };\n\n // Shortcut function for checking if an object has a given property directly\n // on itself (in other words, not on a prototype).\n _.has = function(obj, key) {\n return obj != null && hasOwnProperty.call(obj, key);\n };\n\n // Utility Functions\n // -----------------\n\n // Run Underscore.js in *noConflict* mode, returning the `_` variable to its\n // previous owner. Returns a reference to the Underscore object.\n _.noConflict = function() {\n root._ = previousUnderscore;\n return this;\n };\n\n // Keep the identity function around for default iteratees.\n _.identity = function(value) {\n return value;\n };\n\n // Predicate-generating functions. Often useful outside of Underscore.\n _.constant = function(value) {\n return function() {\n return value;\n };\n };\n\n _.noop = function(){};\n\n _.property = property;\n\n // Generates a function for a given object that returns a given property.\n _.propertyOf = function(obj) {\n return obj == null ? function(){} : function(key) {\n return obj[key];\n };\n };\n\n // Returns a predicate for checking whether an object has a given set of\n // `key:value` pairs.\n _.matcher = _.matches = function(attrs) {\n attrs = _.extendOwn({}, attrs);\n return function(obj) {\n return _.isMatch(obj, attrs);\n };\n };\n\n // Run a function **n** times.\n _.times = function(n, iteratee, context) {\n var accum = Array(Math.max(0, n));\n iteratee = optimizeCb(iteratee, context, 1);\n for (var i = 0; i < n; i++) accum[i] = iteratee(i);\n return accum;\n };\n\n // Return a random integer between min and max (inclusive).\n _.random = function(min, max) {\n if (max == null) {\n max = min;\n min = 0;\n }\n return min + Math.floor(Math.random() * (max - min + 1));\n };\n\n // A (possibly faster) way to get the current timestamp as an integer.\n _.now = Date.now || function() {\n return new Date().getTime();\n };\n\n // List of HTML entities for escaping.\n var escapeMap = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n '`': '`'\n };\n var unescapeMap = _.invert(escapeMap);\n\n // Functions for escaping and unescaping strings to/from HTML interpolation.\n var createEscaper = function(map) {\n var escaper = function(match) {\n return map[match];\n };\n // Regexes for identifying a key that needs to be escaped\n var source = '(?:' + _.keys(map).join('|') + ')';\n var testRegexp = RegExp(source);\n var replaceRegexp = RegExp(source, 'g');\n return function(string) {\n string = string == null ? '' : '' + string;\n return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;\n };\n };\n _.escape = createEscaper(escapeMap);\n _.unescape = createEscaper(unescapeMap);\n\n // If the value of the named `property` is a function then invoke it with the\n // `object` as context; otherwise, return it.\n _.result = function(object, property, fallback) {\n var value = object == null ? void 0 : object[property];\n if (value === void 0) {\n value = fallback;\n }\n return _.isFunction(value) ? value.call(object) : value;\n };\n\n // Generate a unique integer id (unique within the entire client session).\n // Useful for temporary DOM ids.\n var idCounter = 0;\n _.uniqueId = function(prefix) {\n var id = ++idCounter + '';\n return prefix ? prefix + id : id;\n };\n\n // By default, Underscore uses ERB-style template delimiters, change the\n // following template settings to use alternative delimiters.\n _.templateSettings = {\n evaluate : /<%([\\s\\S]+?)%>/g,\n interpolate : /<%=([\\s\\S]+?)%>/g,\n escape : /<%-([\\s\\S]+?)%>/g\n };\n\n // When customizing `templateSettings`, if you don't want to define an\n // interpolation, evaluation or escaping regex, we need one that is\n // guaranteed not to match.\n var noMatch = /(.)^/;\n\n // Certain characters need to be escaped so that they can be put into a\n // string literal.\n var escapes = {\n \"'\": \"'\",\n '\\\\': '\\\\',\n '\\r': 'r',\n '\\n': 'n',\n '\\u2028': 'u2028',\n '\\u2029': 'u2029'\n };\n\n var escaper = /\\\\|'|\\r|\\n|\\u2028|\\u2029/g;\n\n var escapeChar = function(match) {\n return '\\\\' + escapes[match];\n };\n\n // JavaScript micro-templating, similar to John Resig's implementation.\n // Underscore templating handles arbitrary delimiters, preserves whitespace,\n // and correctly escapes quotes within interpolated code.\n // NB: `oldSettings` only exists for backwards compatibility.\n _.template = function(text, settings, oldSettings) {\n if (!settings && oldSettings) settings = oldSettings;\n settings = _.defaults({}, settings, _.templateSettings);\n\n // Combine delimiters into one regular expression via alternation.\n var matcher = RegExp([\n (settings.escape || noMatch).source,\n (settings.interpolate || noMatch).source,\n (settings.evaluate || noMatch).source\n ].join('|') + '|$', 'g');\n\n // Compile the template source, escaping string literals appropriately.\n var index = 0;\n var source = \"__p+='\";\n text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {\n source += text.slice(index, offset).replace(escaper, escapeChar);\n index = offset + match.length;\n\n if (escape) {\n source += \"'+\\n((__t=(\" + escape + \"))==null?'':_.escape(__t))+\\n'\";\n } else if (interpolate) {\n source += \"'+\\n((__t=(\" + interpolate + \"))==null?'':__t)+\\n'\";\n } else if (evaluate) {\n source += \"';\\n\" + evaluate + \"\\n__p+='\";\n }\n\n // Adobe VMs need the match returned to produce the correct offest.\n return match;\n });\n source += \"';\\n\";\n\n // If a variable is not specified, place data values in local scope.\n if (!settings.variable) source = 'with(obj||{}){\\n' + source + '}\\n';\n\n source = \"var __t,__p='',__j=Array.prototype.join,\" +\n \"print=function(){__p+=__j.call(arguments,'');};\\n\" +\n source + 'return __p;\\n';\n\n try {\n var render = new Function(settings.variable || 'obj', '_', source);\n } catch (e) {\n e.source = source;\n throw e;\n }\n\n var template = function(data) {\n return render.call(this, data, _);\n };\n\n // Provide the compiled source as a convenience for precompilation.\n var argument = settings.variable || 'obj';\n template.source = 'function(' + argument + '){\\n' + source + '}';\n\n return template;\n };\n\n // Add a \"chain\" function. Start chaining a wrapped Underscore object.\n _.chain = function(obj) {\n var instance = _(obj);\n instance._chain = true;\n return instance;\n };\n\n // OOP\n // ---------------\n // If Underscore is called as a function, it returns a wrapped object that\n // can be used OO-style. This wrapper holds altered versions of all the\n // underscore functions. Wrapped objects may be chained.\n\n // Helper function to continue chaining intermediate results.\n var result = function(instance, obj) {\n return instance._chain ? _(obj).chain() : obj;\n };\n\n // Add your own custom functions to the Underscore object.\n _.mixin = function(obj) {\n _.each(_.functions(obj), function(name) {\n var func = _[name] = obj[name];\n _.prototype[name] = function() {\n var args = [this._wrapped];\n push.apply(args, arguments);\n return result(this, func.apply(_, args));\n };\n });\n };\n\n // Add all of the Underscore functions to the wrapper object.\n _.mixin(_);\n\n // Add all mutator Array functions to the wrapper.\n _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {\n var method = ArrayProto[name];\n _.prototype[name] = function() {\n var obj = this._wrapped;\n method.apply(obj, arguments);\n if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];\n return result(this, obj);\n };\n });\n\n // Add all accessor Array functions to the wrapper.\n _.each(['concat', 'join', 'slice'], function(name) {\n var method = ArrayProto[name];\n _.prototype[name] = function() {\n return result(this, method.apply(this._wrapped, arguments));\n };\n });\n\n // Extracts the result from a wrapped and chained object.\n _.prototype.value = function() {\n return this._wrapped;\n };\n\n // Provide unwrapping proxy for some methods used in engine operations\n // such as arithmetic and JSON stringification.\n _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;\n\n _.prototype.toString = function() {\n return '' + this._wrapped;\n };\n\n // AMD registration happens at the end for compatibility with AMD loaders\n // that may not enforce next-turn semantics on modules. Even though general\n // practice for AMD registration is to be anonymous, underscore registers\n // as a named module because, like jQuery, it is a base library that is\n // popular enough to be bundled in a third party lib, but not be part of\n // an AMD load request. Those cases could generate an error when an\n // anonymous define() is called outside of a loader request.\n if (typeof define === 'function' && define.amd) {\n define('underscore', [], function() {\n return _;\n });\n }\n}.call(this));\n\n","//! moment.js\n//! version : 2.9.0\n//! authors : Tim Wood, Iskren Chernev, Moment.js contributors\n//! license : MIT\n//! momentjs.com\n\n(function (undefined) {\n /************************************\n Constants\n ************************************/\n\n var moment,\n VERSION = '2.9.0',\n // the global-scope this is NOT the global object in Node.js\n globalScope = (typeof global !== 'undefined' && (typeof window === 'undefined' || window === global.window)) ? global : this,\n oldGlobalMoment,\n round = Math.round,\n hasOwnProperty = Object.prototype.hasOwnProperty,\n i,\n\n YEAR = 0,\n MONTH = 1,\n DATE = 2,\n HOUR = 3,\n MINUTE = 4,\n SECOND = 5,\n MILLISECOND = 6,\n\n // internal storage for locale config files\n locales = {},\n\n // extra moment internal properties (plugins register props here)\n momentProperties = [],\n\n // check for nodeJS\n hasModule = (typeof module !== 'undefined' && module && module.exports),\n\n // ASP.NET json date format regex\n aspNetJsonRegex = /^\\/?Date\\((\\-?\\d+)/i,\n aspNetTimeSpanJsonRegex = /(\\-)?(?:(\\d*)\\.)?(\\d+)\\:(\\d+)(?:\\:(\\d+)\\.?(\\d{3})?)?/,\n\n // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html\n // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere\n isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,\n\n // format tokens\n formattingTokens = /(\\[[^\\[]*\\])|(\\\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g,\n localFormattingTokens = /(\\[[^\\[]*\\])|(\\\\)?(LTS|LT|LL?L?L?|l{1,4})/g,\n\n // parsing token regexes\n parseTokenOneOrTwoDigits = /\\d\\d?/, // 0 - 99\n parseTokenOneToThreeDigits = /\\d{1,3}/, // 0 - 999\n parseTokenOneToFourDigits = /\\d{1,4}/, // 0 - 9999\n parseTokenOneToSixDigits = /[+\\-]?\\d{1,6}/, // -999,999 - 999,999\n parseTokenDigits = /\\d+/, // nonzero number of digits\n parseTokenWord = /[0-9]*['a-z\\u00A0-\\u05FF\\u0700-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]+|[\\u0600-\\u06FF\\/]+(\\s*?[\\u0600-\\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic.\n parseTokenTimezone = /Z|[\\+\\-]\\d\\d:?\\d\\d/gi, // +00:00 -00:00 +0000 -0000 or Z\n parseTokenT = /T/i, // T (ISO separator)\n parseTokenOffsetMs = /[\\+\\-]?\\d+/, // 1234567890123\n parseTokenTimestampMs = /[\\+\\-]?\\d+(\\.\\d{1,3})?/, // 123456789 123456789.123\n\n //strict parsing regexes\n parseTokenOneDigit = /\\d/, // 0 - 9\n parseTokenTwoDigits = /\\d\\d/, // 00 - 99\n parseTokenThreeDigits = /\\d{3}/, // 000 - 999\n parseTokenFourDigits = /\\d{4}/, // 0000 - 9999\n parseTokenSixDigits = /[+-]?\\d{6}/, // -999,999 - 999,999\n parseTokenSignedNumber = /[+-]?\\d+/, // -inf - inf\n\n // iso 8601 regex\n // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)\n isoRegex = /^\\s*(?:[+-]\\d{6}|\\d{4})-(?:(\\d\\d-\\d\\d)|(W\\d\\d$)|(W\\d\\d-\\d)|(\\d\\d\\d))((T| )(\\d\\d(:\\d\\d(:\\d\\d(\\.\\d+)?)?)?)?([\\+\\-]\\d\\d(?::?\\d\\d)?|\\s*Z)?)?$/,\n\n isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',\n\n isoDates = [\n ['YYYYYY-MM-DD', /[+-]\\d{6}-\\d{2}-\\d{2}/],\n ['YYYY-MM-DD', /\\d{4}-\\d{2}-\\d{2}/],\n ['GGGG-[W]WW-E', /\\d{4}-W\\d{2}-\\d/],\n ['GGGG-[W]WW', /\\d{4}-W\\d{2}/],\n ['YYYY-DDD', /\\d{4}-\\d{3}/]\n ],\n\n // iso time formats and regexes\n isoTimes = [\n ['HH:mm:ss.SSSS', /(T| )\\d\\d:\\d\\d:\\d\\d\\.\\d+/],\n ['HH:mm:ss', /(T| )\\d\\d:\\d\\d:\\d\\d/],\n ['HH:mm', /(T| )\\d\\d:\\d\\d/],\n ['HH', /(T| )\\d\\d/]\n ],\n\n // timezone chunker '+10:00' > ['10', '00'] or '-1530' > ['-', '15', '30']\n parseTimezoneChunker = /([\\+\\-]|\\d\\d)/gi,\n\n // getter and setter names\n proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),\n unitMillisecondFactors = {\n 'Milliseconds' : 1,\n 'Seconds' : 1e3,\n 'Minutes' : 6e4,\n 'Hours' : 36e5,\n 'Days' : 864e5,\n 'Months' : 2592e6,\n 'Years' : 31536e6\n },\n\n unitAliases = {\n ms : 'millisecond',\n s : 'second',\n m : 'minute',\n h : 'hour',\n d : 'day',\n D : 'date',\n w : 'week',\n W : 'isoWeek',\n M : 'month',\n Q : 'quarter',\n y : 'year',\n DDD : 'dayOfYear',\n e : 'weekday',\n E : 'isoWeekday',\n gg: 'weekYear',\n GG: 'isoWeekYear'\n },\n\n camelFunctions = {\n dayofyear : 'dayOfYear',\n isoweekday : 'isoWeekday',\n isoweek : 'isoWeek',\n weekyear : 'weekYear',\n isoweekyear : 'isoWeekYear'\n },\n\n // format function strings\n formatFunctions = {},\n\n // default relative time thresholds\n relativeTimeThresholds = {\n s: 45, // seconds to minute\n m: 45, // minutes to hour\n h: 22, // hours to day\n d: 26, // days to month\n M: 11 // months to year\n },\n\n // tokens to ordinalize and pad\n ordinalizeTokens = 'DDD w W M D d'.split(' '),\n paddedTokens = 'M D H h m s w W'.split(' '),\n\n formatTokenFunctions = {\n M : function () {\n return this.month() + 1;\n },\n MMM : function (format) {\n return this.localeData().monthsShort(this, format);\n },\n MMMM : function (format) {\n return this.localeData().months(this, format);\n },\n D : function () {\n return this.date();\n },\n DDD : function () {\n return this.dayOfYear();\n },\n d : function () {\n return this.day();\n },\n dd : function (format) {\n return this.localeData().weekdaysMin(this, format);\n },\n ddd : function (format) {\n return this.localeData().weekdaysShort(this, format);\n },\n dddd : function (format) {\n return this.localeData().weekdays(this, format);\n },\n w : function () {\n return this.week();\n },\n W : function () {\n return this.isoWeek();\n },\n YY : function () {\n return leftZeroFill(this.year() % 100, 2);\n },\n YYYY : function () {\n return leftZeroFill(this.year(), 4);\n },\n YYYYY : function () {\n return leftZeroFill(this.year(), 5);\n },\n YYYYYY : function () {\n var y = this.year(), sign = y >= 0 ? '+' : '-';\n return sign + leftZeroFill(Math.abs(y), 6);\n },\n gg : function () {\n return leftZeroFill(this.weekYear() % 100, 2);\n },\n gggg : function () {\n return leftZeroFill(this.weekYear(), 4);\n },\n ggggg : function () {\n return leftZeroFill(this.weekYear(), 5);\n },\n GG : function () {\n return leftZeroFill(this.isoWeekYear() % 100, 2);\n },\n GGGG : function () {\n return leftZeroFill(this.isoWeekYear(), 4);\n },\n GGGGG : function () {\n return leftZeroFill(this.isoWeekYear(), 5);\n },\n e : function () {\n return this.weekday();\n },\n E : function () {\n return this.isoWeekday();\n },\n a : function () {\n return this.localeData().meridiem(this.hours(), this.minutes(), true);\n },\n A : function () {\n return this.localeData().meridiem(this.hours(), this.minutes(), false);\n },\n H : function () {\n return this.hours();\n },\n h : function () {\n return this.hours() % 12 || 12;\n },\n m : function () {\n return this.minutes();\n },\n s : function () {\n return this.seconds();\n },\n S : function () {\n return toInt(this.milliseconds() / 100);\n },\n SS : function () {\n return leftZeroFill(toInt(this.milliseconds() / 10), 2);\n },\n SSS : function () {\n return leftZeroFill(this.milliseconds(), 3);\n },\n SSSS : function () {\n return leftZeroFill(this.milliseconds(), 3);\n },\n Z : function () {\n var a = this.utcOffset(),\n b = '+';\n if (a < 0) {\n a = -a;\n b = '-';\n }\n return b + leftZeroFill(toInt(a / 60), 2) + ':' + leftZeroFill(toInt(a) % 60, 2);\n },\n ZZ : function () {\n var a = this.utcOffset(),\n b = '+';\n if (a < 0) {\n a = -a;\n b = '-';\n }\n return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);\n },\n z : function () {\n return this.zoneAbbr();\n },\n zz : function () {\n return this.zoneName();\n },\n x : function () {\n return this.valueOf();\n },\n X : function () {\n return this.unix();\n },\n Q : function () {\n return this.quarter();\n }\n },\n\n deprecations = {},\n\n lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'],\n\n updateInProgress = false;\n\n // Pick the first defined of two or three arguments. dfl comes from\n // default.\n function dfl(a, b, c) {\n switch (arguments.length) {\n case 2: return a != null ? a : b;\n case 3: return a != null ? a : b != null ? b : c;\n default: throw new Error('Implement me');\n }\n }\n\n function hasOwnProp(a, b) {\n return hasOwnProperty.call(a, b);\n }\n\n function defaultParsingFlags() {\n // We need to deep clone this object, and es5 standard is not very\n // helpful.\n return {\n empty : false,\n unusedTokens : [],\n unusedInput : [],\n overflow : -2,\n charsLeftOver : 0,\n nullInput : false,\n invalidMonth : null,\n invalidFormat : false,\n userInvalidated : false,\n iso: false\n };\n }\n\n function printMsg(msg) {\n if (moment.suppressDeprecationWarnings === false &&\n typeof console !== 'undefined' && console.warn) {\n console.warn('Deprecation warning: ' + msg);\n }\n }\n\n function deprecate(msg, fn) {\n var firstTime = true;\n return extend(function () {\n if (firstTime) {\n printMsg(msg);\n firstTime = false;\n }\n return fn.apply(this, arguments);\n }, fn);\n }\n\n function deprecateSimple(name, msg) {\n if (!deprecations[name]) {\n printMsg(msg);\n deprecations[name] = true;\n }\n }\n\n function padToken(func, count) {\n return function (a) {\n return leftZeroFill(func.call(this, a), count);\n };\n }\n function ordinalizeToken(func, period) {\n return function (a) {\n return this.localeData().ordinal(func.call(this, a), period);\n };\n }\n\n function monthDiff(a, b) {\n // difference in months\n var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),\n // b is in (anchor - 1 month, anchor + 1 month)\n anchor = a.clone().add(wholeMonthDiff, 'months'),\n anchor2, adjust;\n\n if (b - anchor < 0) {\n anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');\n // linear across the month\n adjust = (b - anchor) / (anchor - anchor2);\n } else {\n anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');\n // linear across the month\n adjust = (b - anchor) / (anchor2 - anchor);\n }\n\n return -(wholeMonthDiff + adjust);\n }\n\n while (ordinalizeTokens.length) {\n i = ordinalizeTokens.pop();\n formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);\n }\n while (paddedTokens.length) {\n i = paddedTokens.pop();\n formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);\n }\n formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);\n\n\n function meridiemFixWrap(locale, hour, meridiem) {\n var isPm;\n\n if (meridiem == null) {\n // nothing to do\n return hour;\n }\n if (locale.meridiemHour != null) {\n return locale.meridiemHour(hour, meridiem);\n } else if (locale.isPM != null) {\n // Fallback\n isPm = locale.isPM(meridiem);\n if (isPm && hour < 12) {\n hour += 12;\n }\n if (!isPm && hour === 12) {\n hour = 0;\n }\n return hour;\n } else {\n // thie is not supposed to happen\n return hour;\n }\n }\n\n /************************************\n Constructors\n ************************************/\n\n function Locale() {\n }\n\n // Moment prototype object\n function Moment(config, skipOverflow) {\n if (skipOverflow !== false) {\n checkOverflow(config);\n }\n copyConfig(this, config);\n this._d = new Date(+config._d);\n // Prevent infinite loop in case updateOffset creates new moment\n // objects.\n if (updateInProgress === false) {\n updateInProgress = true;\n moment.updateOffset(this);\n updateInProgress = false;\n }\n }\n\n // Duration Constructor\n function Duration(duration) {\n var normalizedInput = normalizeObjectUnits(duration),\n years = normalizedInput.year || 0,\n quarters = normalizedInput.quarter || 0,\n months = normalizedInput.month || 0,\n weeks = normalizedInput.week || 0,\n days = normalizedInput.day || 0,\n hours = normalizedInput.hour || 0,\n minutes = normalizedInput.minute || 0,\n seconds = normalizedInput.second || 0,\n milliseconds = normalizedInput.millisecond || 0;\n\n // representation for dateAddRemove\n this._milliseconds = +milliseconds +\n seconds * 1e3 + // 1000\n minutes * 6e4 + // 1000 * 60\n hours * 36e5; // 1000 * 60 * 60\n // Because of dateAddRemove treats 24 hours as different from a\n // day when working around DST, we need to store them separately\n this._days = +days +\n weeks * 7;\n // It is impossible translate months into days without knowing\n // which months you are are talking about, so we have to store\n // it separately.\n this._months = +months +\n quarters * 3 +\n years * 12;\n\n this._data = {};\n\n this._locale = moment.localeData();\n\n this._bubble();\n }\n\n /************************************\n Helpers\n ************************************/\n\n\n function extend(a, b) {\n for (var i in b) {\n if (hasOwnProp(b, i)) {\n a[i] = b[i];\n }\n }\n\n if (hasOwnProp(b, 'toString')) {\n a.toString = b.toString;\n }\n\n if (hasOwnProp(b, 'valueOf')) {\n a.valueOf = b.valueOf;\n }\n\n return a;\n }\n\n function copyConfig(to, from) {\n var i, prop, val;\n\n if (typeof from._isAMomentObject !== 'undefined') {\n to._isAMomentObject = from._isAMomentObject;\n }\n if (typeof from._i !== 'undefined') {\n to._i = from._i;\n }\n if (typeof from._f !== 'undefined') {\n to._f = from._f;\n }\n if (typeof from._l !== 'undefined') {\n to._l = from._l;\n }\n if (typeof from._strict !== 'undefined') {\n to._strict = from._strict;\n }\n if (typeof from._tzm !== 'undefined') {\n to._tzm = from._tzm;\n }\n if (typeof from._isUTC !== 'undefined') {\n to._isUTC = from._isUTC;\n }\n if (typeof from._offset !== 'undefined') {\n to._offset = from._offset;\n }\n if (typeof from._pf !== 'undefined') {\n to._pf = from._pf;\n }\n if (typeof from._locale !== 'undefined') {\n to._locale = from._locale;\n }\n\n if (momentProperties.length > 0) {\n for (i in momentProperties) {\n prop = momentProperties[i];\n val = from[prop];\n if (typeof val !== 'undefined') {\n to[prop] = val;\n }\n }\n }\n\n return to;\n }\n\n function absRound(number) {\n if (number < 0) {\n return Math.ceil(number);\n } else {\n return Math.floor(number);\n }\n }\n\n // left zero fill a number\n // see http://jsperf.com/left-zero-filling for performance comparison\n function leftZeroFill(number, targetLength, forceSign) {\n var output = '' + Math.abs(number),\n sign = number >= 0;\n\n while (output.length < targetLength) {\n output = '0' + output;\n }\n return (sign ? (forceSign ? '+' : '') : '-') + output;\n }\n\n function positiveMomentsDifference(base, other) {\n var res = {milliseconds: 0, months: 0};\n\n res.months = other.month() - base.month() +\n (other.year() - base.year()) * 12;\n if (base.clone().add(res.months, 'M').isAfter(other)) {\n --res.months;\n }\n\n res.milliseconds = +other - +(base.clone().add(res.months, 'M'));\n\n return res;\n }\n\n function momentsDifference(base, other) {\n var res;\n other = makeAs(other, base);\n if (base.isBefore(other)) {\n res = positiveMomentsDifference(base, other);\n } else {\n res = positiveMomentsDifference(other, base);\n res.milliseconds = -res.milliseconds;\n res.months = -res.months;\n }\n\n return res;\n }\n\n // TODO: remove 'name' arg after deprecation is removed\n function createAdder(direction, name) {\n return function (val, period) {\n var dur, tmp;\n //invert the arguments, but complain about it\n if (period !== null && !isNaN(+period)) {\n deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');\n tmp = val; val = period; period = tmp;\n }\n\n val = typeof val === 'string' ? +val : val;\n dur = moment.duration(val, period);\n addOrSubtractDurationFromMoment(this, dur, direction);\n return this;\n };\n }\n\n function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) {\n var milliseconds = duration._milliseconds,\n days = duration._days,\n months = duration._months;\n updateOffset = updateOffset == null ? true : updateOffset;\n\n if (milliseconds) {\n mom._d.setTime(+mom._d + milliseconds * isAdding);\n }\n if (days) {\n rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding);\n }\n if (months) {\n rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding);\n }\n if (updateOffset) {\n moment.updateOffset(mom, days || months);\n }\n }\n\n // check if is an array\n function isArray(input) {\n return Object.prototype.toString.call(input) === '[object Array]';\n }\n\n function isDate(input) {\n return Object.prototype.toString.call(input) === '[object Date]' ||\n input instanceof Date;\n }\n\n // compare two arrays, return the number of differences\n function compareArrays(array1, array2, dontConvert) {\n var len = Math.min(array1.length, array2.length),\n lengthDiff = Math.abs(array1.length - array2.length),\n diffs = 0,\n i;\n for (i = 0; i < len; i++) {\n if ((dontConvert && array1[i] !== array2[i]) ||\n (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {\n diffs++;\n }\n }\n return diffs + lengthDiff;\n }\n\n function normalizeUnits(units) {\n if (units) {\n var lowered = units.toLowerCase().replace(/(.)s$/, '$1');\n units = unitAliases[units] || camelFunctions[lowered] || lowered;\n }\n return units;\n }\n\n function normalizeObjectUnits(inputObject) {\n var normalizedInput = {},\n normalizedProp,\n prop;\n\n for (prop in inputObject) {\n if (hasOwnProp(inputObject, prop)) {\n normalizedProp = normalizeUnits(prop);\n if (normalizedProp) {\n normalizedInput[normalizedProp] = inputObject[prop];\n }\n }\n }\n\n return normalizedInput;\n }\n\n function makeList(field) {\n var count, setter;\n\n if (field.indexOf('week') === 0) {\n count = 7;\n setter = 'day';\n }\n else if (field.indexOf('month') === 0) {\n count = 12;\n setter = 'month';\n }\n else {\n return;\n }\n\n moment[field] = function (format, index) {\n var i, getter,\n method = moment._locale[field],\n results = [];\n\n if (typeof format === 'number') {\n index = format;\n format = undefined;\n }\n\n getter = function (i) {\n var m = moment().utc().set(setter, i);\n return method.call(moment._locale, m, format || '');\n };\n\n if (index != null) {\n return getter(index);\n }\n else {\n for (i = 0; i < count; i++) {\n results.push(getter(i));\n }\n return results;\n }\n };\n }\n\n function toInt(argumentForCoercion) {\n var coercedNumber = +argumentForCoercion,\n value = 0;\n\n if (coercedNumber !== 0 && isFinite(coercedNumber)) {\n if (coercedNumber >= 0) {\n value = Math.floor(coercedNumber);\n } else {\n value = Math.ceil(coercedNumber);\n }\n }\n\n return value;\n }\n\n function daysInMonth(year, month) {\n return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();\n }\n\n function weeksInYear(year, dow, doy) {\n return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week;\n }\n\n function daysInYear(year) {\n return isLeapYear(year) ? 366 : 365;\n }\n\n function isLeapYear(year) {\n return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\n }\n\n function checkOverflow(m) {\n var overflow;\n if (m._a && m._pf.overflow === -2) {\n overflow =\n m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :\n m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :\n m._a[HOUR] < 0 || m._a[HOUR] > 24 ||\n (m._a[HOUR] === 24 && (m._a[MINUTE] !== 0 ||\n m._a[SECOND] !== 0 ||\n m._a[MILLISECOND] !== 0)) ? HOUR :\n m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :\n m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :\n m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :\n -1;\n\n if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {\n overflow = DATE;\n }\n\n m._pf.overflow = overflow;\n }\n }\n\n function isValid(m) {\n if (m._isValid == null) {\n m._isValid = !isNaN(m._d.getTime()) &&\n m._pf.overflow < 0 &&\n !m._pf.empty &&\n !m._pf.invalidMonth &&\n !m._pf.nullInput &&\n !m._pf.invalidFormat &&\n !m._pf.userInvalidated;\n\n if (m._strict) {\n m._isValid = m._isValid &&\n m._pf.charsLeftOver === 0 &&\n m._pf.unusedTokens.length === 0 &&\n m._pf.bigHour === undefined;\n }\n }\n return m._isValid;\n }\n\n function normalizeLocale(key) {\n return key ? key.toLowerCase().replace('_', '-') : key;\n }\n\n // pick the locale from the array\n // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each\n // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root\n function chooseLocale(names) {\n var i = 0, j, next, locale, split;\n\n while (i < names.length) {\n split = normalizeLocale(names[i]).split('-');\n j = split.length;\n next = normalizeLocale(names[i + 1]);\n next = next ? next.split('-') : null;\n while (j > 0) {\n locale = loadLocale(split.slice(0, j).join('-'));\n if (locale) {\n return locale;\n }\n if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {\n //the next array item is better than a shallower substring of this one\n break;\n }\n j--;\n }\n i++;\n }\n return null;\n }\n\n function loadLocale(name) {\n var oldLocale = null;\n if (!locales[name] && hasModule) {\n try {\n oldLocale = moment.locale();\n require('./locale/' + name);\n // because defineLocale currently also sets the global locale, we want to undo that for lazy loaded locales\n moment.locale(oldLocale);\n } catch (e) { }\n }\n return locales[name];\n }\n\n // Return a moment from input, that is local/utc/utcOffset equivalent to\n // model.\n function makeAs(input, model) {\n var res, diff;\n if (model._isUTC) {\n res = model.clone();\n diff = (moment.isMoment(input) || isDate(input) ?\n +input : +moment(input)) - (+res);\n // Use low-level api, because this fn is low-level api.\n res._d.setTime(+res._d + diff);\n moment.updateOffset(res, false);\n return res;\n } else {\n return moment(input).local();\n }\n }\n\n /************************************\n Locale\n ************************************/\n\n\n extend(Locale.prototype, {\n\n set : function (config) {\n var prop, i;\n for (i in config) {\n prop = config[i];\n if (typeof prop === 'function') {\n this[i] = prop;\n } else {\n this['_' + i] = prop;\n }\n }\n // Lenient ordinal parsing accepts just a number in addition to\n // number + (possibly) stuff coming from _ordinalParseLenient.\n this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + /\\d{1,2}/.source);\n },\n\n _months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),\n months : function (m) {\n return this._months[m.month()];\n },\n\n _monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),\n monthsShort : function (m) {\n return this._monthsShort[m.month()];\n },\n\n monthsParse : function (monthName, format, strict) {\n var i, mom, regex;\n\n if (!this._monthsParse) {\n this._monthsParse = [];\n this._longMonthsParse = [];\n this._shortMonthsParse = [];\n }\n\n for (i = 0; i < 12; i++) {\n // make the regex if we don't have it already\n mom = moment.utc([2000, i]);\n if (strict && !this._longMonthsParse[i]) {\n this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');\n this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');\n }\n if (!strict && !this._monthsParse[i]) {\n regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');\n this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');\n }\n // test the regex\n if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {\n return i;\n } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {\n return i;\n } else if (!strict && this._monthsParse[i].test(monthName)) {\n return i;\n }\n }\n },\n\n _weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),\n weekdays : function (m) {\n return this._weekdays[m.day()];\n },\n\n _weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),\n weekdaysShort : function (m) {\n return this._weekdaysShort[m.day()];\n },\n\n _weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),\n weekdaysMin : function (m) {\n return this._weekdaysMin[m.day()];\n },\n\n weekdaysParse : function (weekdayName) {\n var i, mom, regex;\n\n if (!this._weekdaysParse) {\n this._weekdaysParse = [];\n }\n\n for (i = 0; i < 7; i++) {\n // make the regex if we don't have it already\n if (!this._weekdaysParse[i]) {\n mom = moment([2000, 1]).day(i);\n regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');\n this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');\n }\n // test the regex\n if (this._weekdaysParse[i].test(weekdayName)) {\n return i;\n }\n }\n },\n\n _longDateFormat : {\n LTS : 'h:mm:ss A',\n LT : 'h:mm A',\n L : 'MM/DD/YYYY',\n LL : 'MMMM D, YYYY',\n LLL : 'MMMM D, YYYY LT',\n LLLL : 'dddd, MMMM D, YYYY LT'\n },\n longDateFormat : function (key) {\n var output = this._longDateFormat[key];\n if (!output && this._longDateFormat[key.toUpperCase()]) {\n output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {\n return val.slice(1);\n });\n this._longDateFormat[key] = output;\n }\n return output;\n },\n\n isPM : function (input) {\n // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays\n // Using charAt should be more compatible.\n return ((input + '').toLowerCase().charAt(0) === 'p');\n },\n\n _meridiemParse : /[ap]\\.?m?\\.?/i,\n meridiem : function (hours, minutes, isLower) {\n if (hours > 11) {\n return isLower ? 'pm' : 'PM';\n } else {\n return isLower ? 'am' : 'AM';\n }\n },\n\n\n _calendar : {\n sameDay : '[Today at] LT',\n nextDay : '[Tomorrow at] LT',\n nextWeek : 'dddd [at] LT',\n lastDay : '[Yesterday at] LT',\n lastWeek : '[Last] dddd [at] LT',\n sameElse : 'L'\n },\n calendar : function (key, mom, now) {\n var output = this._calendar[key];\n return typeof output === 'function' ? output.apply(mom, [now]) : output;\n },\n\n _relativeTime : {\n future : 'in %s',\n past : '%s ago',\n s : 'a few seconds',\n m : 'a minute',\n mm : '%d minutes',\n h : 'an hour',\n hh : '%d hours',\n d : 'a day',\n dd : '%d days',\n M : 'a month',\n MM : '%d months',\n y : 'a year',\n yy : '%d years'\n },\n\n relativeTime : function (number, withoutSuffix, string, isFuture) {\n var output = this._relativeTime[string];\n return (typeof output === 'function') ?\n output(number, withoutSuffix, string, isFuture) :\n output.replace(/%d/i, number);\n },\n\n pastFuture : function (diff, output) {\n var format = this._relativeTime[diff > 0 ? 'future' : 'past'];\n return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);\n },\n\n ordinal : function (number) {\n return this._ordinal.replace('%d', number);\n },\n _ordinal : '%d',\n _ordinalParse : /\\d{1,2}/,\n\n preparse : function (string) {\n return string;\n },\n\n postformat : function (string) {\n return string;\n },\n\n week : function (mom) {\n return weekOfYear(mom, this._week.dow, this._week.doy).week;\n },\n\n _week : {\n dow : 0, // Sunday is the first day of the week.\n doy : 6 // The week that contains Jan 1st is the first week of the year.\n },\n\n firstDayOfWeek : function () {\n return this._week.dow;\n },\n\n firstDayOfYear : function () {\n return this._week.doy;\n },\n\n _invalidDate: 'Invalid date',\n invalidDate: function () {\n return this._invalidDate;\n }\n });\n\n /************************************\n Formatting\n ************************************/\n\n\n function removeFormattingTokens(input) {\n if (input.match(/\\[[\\s\\S]/)) {\n return input.replace(/^\\[|\\]$/g, '');\n }\n return input.replace(/\\\\/g, '');\n }\n\n function makeFormatFunction(format) {\n var array = format.match(formattingTokens), i, length;\n\n for (i = 0, length = array.length; i < length; i++) {\n if (formatTokenFunctions[array[i]]) {\n array[i] = formatTokenFunctions[array[i]];\n } else {\n array[i] = removeFormattingTokens(array[i]);\n }\n }\n\n return function (mom) {\n var output = '';\n for (i = 0; i < length; i++) {\n output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];\n }\n return output;\n };\n }\n\n // format date using native date object\n function formatMoment(m, format) {\n if (!m.isValid()) {\n return m.localeData().invalidDate();\n }\n\n format = expandFormat(format, m.localeData());\n\n if (!formatFunctions[format]) {\n formatFunctions[format] = makeFormatFunction(format);\n }\n\n return formatFunctions[format](m);\n }\n\n function expandFormat(format, locale) {\n var i = 5;\n\n function replaceLongDateFormatTokens(input) {\n return locale.longDateFormat(input) || input;\n }\n\n localFormattingTokens.lastIndex = 0;\n while (i >= 0 && localFormattingTokens.test(format)) {\n format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);\n localFormattingTokens.lastIndex = 0;\n i -= 1;\n }\n\n return format;\n }\n\n\n /************************************\n Parsing\n ************************************/\n\n\n // get the regex to find the next token\n function getParseRegexForToken(token, config) {\n var a, strict = config._strict;\n switch (token) {\n case 'Q':\n return parseTokenOneDigit;\n case 'DDDD':\n return parseTokenThreeDigits;\n case 'YYYY':\n case 'GGGG':\n case 'gggg':\n return strict ? parseTokenFourDigits : parseTokenOneToFourDigits;\n case 'Y':\n case 'G':\n case 'g':\n return parseTokenSignedNumber;\n case 'YYYYYY':\n case 'YYYYY':\n case 'GGGGG':\n case 'ggggg':\n return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;\n case 'S':\n if (strict) {\n return parseTokenOneDigit;\n }\n /* falls through */\n case 'SS':\n if (strict) {\n return parseTokenTwoDigits;\n }\n /* falls through */\n case 'SSS':\n if (strict) {\n return parseTokenThreeDigits;\n }\n /* falls through */\n case 'DDD':\n return parseTokenOneToThreeDigits;\n case 'MMM':\n case 'MMMM':\n case 'dd':\n case 'ddd':\n case 'dddd':\n return parseTokenWord;\n case 'a':\n case 'A':\n return config._locale._meridiemParse;\n case 'x':\n return parseTokenOffsetMs;\n case 'X':\n return parseTokenTimestampMs;\n case 'Z':\n case 'ZZ':\n return parseTokenTimezone;\n case 'T':\n return parseTokenT;\n case 'SSSS':\n return parseTokenDigits;\n case 'MM':\n case 'DD':\n case 'YY':\n case 'GG':\n case 'gg':\n case 'HH':\n case 'hh':\n case 'mm':\n case 'ss':\n case 'ww':\n case 'WW':\n return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits;\n case 'M':\n case 'D':\n case 'd':\n case 'H':\n case 'h':\n case 'm':\n case 's':\n case 'w':\n case 'W':\n case 'e':\n case 'E':\n return parseTokenOneOrTwoDigits;\n case 'Do':\n return strict ? config._locale._ordinalParse : config._locale._ordinalParseLenient;\n default :\n a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\\\', '')), 'i'));\n return a;\n }\n }\n\n function utcOffsetFromString(string) {\n string = string || '';\n var possibleTzMatches = (string.match(parseTokenTimezone) || []),\n tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],\n parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],\n minutes = +(parts[1] * 60) + toInt(parts[2]);\n\n return parts[0] === '+' ? minutes : -minutes;\n }\n\n // function to convert string input to date\n function addTimeToArrayFromToken(token, input, config) {\n var a, datePartArray = config._a;\n\n switch (token) {\n // QUARTER\n case 'Q':\n if (input != null) {\n datePartArray[MONTH] = (toInt(input) - 1) * 3;\n }\n break;\n // MONTH\n case 'M' : // fall through to MM\n case 'MM' :\n if (input != null) {\n datePartArray[MONTH] = toInt(input) - 1;\n }\n break;\n case 'MMM' : // fall through to MMMM\n case 'MMMM' :\n a = config._locale.monthsParse(input, token, config._strict);\n // if we didn't find a month name, mark the date as invalid.\n if (a != null) {\n datePartArray[MONTH] = a;\n } else {\n config._pf.invalidMonth = input;\n }\n break;\n // DAY OF MONTH\n case 'D' : // fall through to DD\n case 'DD' :\n if (input != null) {\n datePartArray[DATE] = toInt(input);\n }\n break;\n case 'Do' :\n if (input != null) {\n datePartArray[DATE] = toInt(parseInt(\n input.match(/\\d{1,2}/)[0], 10));\n }\n break;\n // DAY OF YEAR\n case 'DDD' : // fall through to DDDD\n case 'DDDD' :\n if (input != null) {\n config._dayOfYear = toInt(input);\n }\n\n break;\n // YEAR\n case 'YY' :\n datePartArray[YEAR] = moment.parseTwoDigitYear(input);\n break;\n case 'YYYY' :\n case 'YYYYY' :\n case 'YYYYYY' :\n datePartArray[YEAR] = toInt(input);\n break;\n // AM / PM\n case 'a' : // fall through to A\n case 'A' :\n config._meridiem = input;\n // config._isPm = config._locale.isPM(input);\n break;\n // HOUR\n case 'h' : // fall through to hh\n case 'hh' :\n config._pf.bigHour = true;\n /* falls through */\n case 'H' : // fall through to HH\n case 'HH' :\n datePartArray[HOUR] = toInt(input);\n break;\n // MINUTE\n case 'm' : // fall through to mm\n case 'mm' :\n datePartArray[MINUTE] = toInt(input);\n break;\n // SECOND\n case 's' : // fall through to ss\n case 'ss' :\n datePartArray[SECOND] = toInt(input);\n break;\n // MILLISECOND\n case 'S' :\n case 'SS' :\n case 'SSS' :\n case 'SSSS' :\n datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);\n break;\n // UNIX OFFSET (MILLISECONDS)\n case 'x':\n config._d = new Date(toInt(input));\n break;\n // UNIX TIMESTAMP WITH MS\n case 'X':\n config._d = new Date(parseFloat(input) * 1000);\n break;\n // TIMEZONE\n case 'Z' : // fall through to ZZ\n case 'ZZ' :\n config._useUTC = true;\n config._tzm = utcOffsetFromString(input);\n break;\n // WEEKDAY - human\n case 'dd':\n case 'ddd':\n case 'dddd':\n a = config._locale.weekdaysParse(input);\n // if we didn't get a weekday name, mark the date as invalid\n if (a != null) {\n config._w = config._w || {};\n config._w['d'] = a;\n } else {\n config._pf.invalidWeekday = input;\n }\n break;\n // WEEK, WEEK DAY - numeric\n case 'w':\n case 'ww':\n case 'W':\n case 'WW':\n case 'd':\n case 'e':\n case 'E':\n token = token.substr(0, 1);\n /* falls through */\n case 'gggg':\n case 'GGGG':\n case 'GGGGG':\n token = token.substr(0, 2);\n if (input) {\n config._w = config._w || {};\n config._w[token] = toInt(input);\n }\n break;\n case 'gg':\n case 'GG':\n config._w = config._w || {};\n config._w[token] = moment.parseTwoDigitYear(input);\n }\n }\n\n function dayOfYearFromWeekInfo(config) {\n var w, weekYear, week, weekday, dow, doy, temp;\n\n w = config._w;\n if (w.GG != null || w.W != null || w.E != null) {\n dow = 1;\n doy = 4;\n\n // TODO: We need to take the current isoWeekYear, but that depends on\n // how we interpret now (local, utc, fixed offset). So create\n // a now version of current config (take local/utc/offset flags, and\n // create now).\n weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year);\n week = dfl(w.W, 1);\n weekday = dfl(w.E, 1);\n } else {\n dow = config._locale._week.dow;\n doy = config._locale._week.doy;\n\n weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year);\n week = dfl(w.w, 1);\n\n if (w.d != null) {\n // weekday -- low day numbers are considered next week\n weekday = w.d;\n if (weekday < dow) {\n ++week;\n }\n } else if (w.e != null) {\n // local weekday -- counting starts from begining of week\n weekday = w.e + dow;\n } else {\n // default to begining of week\n weekday = dow;\n }\n }\n temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow);\n\n config._a[YEAR] = temp.year;\n config._dayOfYear = temp.dayOfYear;\n }\n\n // convert an array to a date.\n // the array should mirror the parameters below\n // note: all values past the year are optional and will default to the lowest possible value.\n // [year, month, day , hour, minute, second, millisecond]\n function dateFromConfig(config) {\n var i, date, input = [], currentDate, yearToUse;\n\n if (config._d) {\n return;\n }\n\n currentDate = currentDateArray(config);\n\n //compute day of the year from weeks and weekdays\n if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {\n dayOfYearFromWeekInfo(config);\n }\n\n //if the day of the year is set, figure out what it is\n if (config._dayOfYear) {\n yearToUse = dfl(config._a[YEAR], currentDate[YEAR]);\n\n if (config._dayOfYear > daysInYear(yearToUse)) {\n config._pf._overflowDayOfYear = true;\n }\n\n date = makeUTCDate(yearToUse, 0, config._dayOfYear);\n config._a[MONTH] = date.getUTCMonth();\n config._a[DATE] = date.getUTCDate();\n }\n\n // Default to current date.\n // * if no year, month, day of month are given, default to today\n // * if day of month is given, default month and year\n // * if month is given, default only year\n // * if year is given, don't default anything\n for (i = 0; i < 3 && config._a[i] == null; ++i) {\n config._a[i] = input[i] = currentDate[i];\n }\n\n // Zero out whatever was not defaulted, including time\n for (; i < 7; i++) {\n config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];\n }\n\n // Check for 24:00:00.000\n if (config._a[HOUR] === 24 &&\n config._a[MINUTE] === 0 &&\n config._a[SECOND] === 0 &&\n config._a[MILLISECOND] === 0) {\n config._nextDay = true;\n config._a[HOUR] = 0;\n }\n\n config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);\n // Apply timezone offset from input. The actual utcOffset can be changed\n // with parseZone.\n if (config._tzm != null) {\n config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);\n }\n\n if (config._nextDay) {\n config._a[HOUR] = 24;\n }\n }\n\n function dateFromObject(config) {\n var normalizedInput;\n\n if (config._d) {\n return;\n }\n\n normalizedInput = normalizeObjectUnits(config._i);\n config._a = [\n normalizedInput.year,\n normalizedInput.month,\n normalizedInput.day || normalizedInput.date,\n normalizedInput.hour,\n normalizedInput.minute,\n normalizedInput.second,\n normalizedInput.millisecond\n ];\n\n dateFromConfig(config);\n }\n\n function currentDateArray(config) {\n var now = new Date();\n if (config._useUTC) {\n return [\n now.getUTCFullYear(),\n now.getUTCMonth(),\n now.getUTCDate()\n ];\n } else {\n return [now.getFullYear(), now.getMonth(), now.getDate()];\n }\n }\n\n // date from string and format string\n function makeDateFromStringAndFormat(config) {\n if (config._f === moment.ISO_8601) {\n parseISO(config);\n return;\n }\n\n config._a = [];\n config._pf.empty = true;\n\n // This array is used to make a Date, either with `new Date` or `Date.UTC`\n var string = '' + config._i,\n i, parsedInput, tokens, token, skipped,\n stringLength = string.length,\n totalParsedInputLength = 0;\n\n tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];\n\n for (i = 0; i < tokens.length; i++) {\n token = tokens[i];\n parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];\n if (parsedInput) {\n skipped = string.substr(0, string.indexOf(parsedInput));\n if (skipped.length > 0) {\n config._pf.unusedInput.push(skipped);\n }\n string = string.slice(string.indexOf(parsedInput) + parsedInput.length);\n totalParsedInputLength += parsedInput.length;\n }\n // don't parse if it's not a known token\n if (formatTokenFunctions[token]) {\n if (parsedInput) {\n config._pf.empty = false;\n }\n else {\n config._pf.unusedTokens.push(token);\n }\n addTimeToArrayFromToken(token, parsedInput, config);\n }\n else if (config._strict && !parsedInput) {\n config._pf.unusedTokens.push(token);\n }\n }\n\n // add remaining unparsed input length to the string\n config._pf.charsLeftOver = stringLength - totalParsedInputLength;\n if (string.length > 0) {\n config._pf.unusedInput.push(string);\n }\n\n // clear _12h flag if hour is <= 12\n if (config._pf.bigHour === true && config._a[HOUR] <= 12) {\n config._pf.bigHour = undefined;\n }\n // handle meridiem\n config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR],\n config._meridiem);\n dateFromConfig(config);\n checkOverflow(config);\n }\n\n function unescapeFormat(s) {\n return s.replace(/\\\\(\\[)|\\\\(\\])|\\[([^\\]\\[]*)\\]|\\\\(.)/g, function (matched, p1, p2, p3, p4) {\n return p1 || p2 || p3 || p4;\n });\n }\n\n // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript\n function regexpEscape(s) {\n return s.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n }\n\n // date from string and array of format strings\n function makeDateFromStringAndArray(config) {\n var tempConfig,\n bestMoment,\n\n scoreToBeat,\n i,\n currentScore;\n\n if (config._f.length === 0) {\n config._pf.invalidFormat = true;\n config._d = new Date(NaN);\n return;\n }\n\n for (i = 0; i < config._f.length; i++) {\n currentScore = 0;\n tempConfig = copyConfig({}, config);\n if (config._useUTC != null) {\n tempConfig._useUTC = config._useUTC;\n }\n tempConfig._pf = defaultParsingFlags();\n tempConfig._f = config._f[i];\n makeDateFromStringAndFormat(tempConfig);\n\n if (!isValid(tempConfig)) {\n continue;\n }\n\n // if there is any input that was not parsed add a penalty for that format\n currentScore += tempConfig._pf.charsLeftOver;\n\n //or tokens\n currentScore += tempConfig._pf.unusedTokens.length * 10;\n\n tempConfig._pf.score = currentScore;\n\n if (scoreToBeat == null || currentScore < scoreToBeat) {\n scoreToBeat = currentScore;\n bestMoment = tempConfig;\n }\n }\n\n extend(config, bestMoment || tempConfig);\n }\n\n // date from iso format\n function parseISO(config) {\n var i, l,\n string = config._i,\n match = isoRegex.exec(string);\n\n if (match) {\n config._pf.iso = true;\n for (i = 0, l = isoDates.length; i < l; i++) {\n if (isoDates[i][1].exec(string)) {\n // match[5] should be 'T' or undefined\n config._f = isoDates[i][0] + (match[6] || ' ');\n break;\n }\n }\n for (i = 0, l = isoTimes.length; i < l; i++) {\n if (isoTimes[i][1].exec(string)) {\n config._f += isoTimes[i][0];\n break;\n }\n }\n if (string.match(parseTokenTimezone)) {\n config._f += 'Z';\n }\n makeDateFromStringAndFormat(config);\n } else {\n config._isValid = false;\n }\n }\n\n // date from iso format or fallback\n function makeDateFromString(config) {\n parseISO(config);\n if (config._isValid === false) {\n delete config._isValid;\n moment.createFromInputFallback(config);\n }\n }\n\n function map(arr, fn) {\n var res = [], i;\n for (i = 0; i < arr.length; ++i) {\n res.push(fn(arr[i], i));\n }\n return res;\n }\n\n function makeDateFromInput(config) {\n var input = config._i, matched;\n if (input === undefined) {\n config._d = new Date();\n } else if (isDate(input)) {\n config._d = new Date(+input);\n } else if ((matched = aspNetJsonRegex.exec(input)) !== null) {\n config._d = new Date(+matched[1]);\n } else if (typeof input === 'string') {\n makeDateFromString(config);\n } else if (isArray(input)) {\n config._a = map(input.slice(0), function (obj) {\n return parseInt(obj, 10);\n });\n dateFromConfig(config);\n } else if (typeof(input) === 'object') {\n dateFromObject(config);\n } else if (typeof(input) === 'number') {\n // from milliseconds\n config._d = new Date(input);\n } else {\n moment.createFromInputFallback(config);\n }\n }\n\n function makeDate(y, m, d, h, M, s, ms) {\n //can't just apply() to create a date:\n //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply\n var date = new Date(y, m, d, h, M, s, ms);\n\n //the date constructor doesn't accept years < 1970\n if (y < 1970) {\n date.setFullYear(y);\n }\n return date;\n }\n\n function makeUTCDate(y) {\n var date = new Date(Date.UTC.apply(null, arguments));\n if (y < 1970) {\n date.setUTCFullYear(y);\n }\n return date;\n }\n\n function parseWeekday(input, locale) {\n if (typeof input === 'string') {\n if (!isNaN(input)) {\n input = parseInt(input, 10);\n }\n else {\n input = locale.weekdaysParse(input);\n if (typeof input !== 'number') {\n return null;\n }\n }\n }\n return input;\n }\n\n /************************************\n Relative Time\n ************************************/\n\n\n // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize\n function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {\n return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);\n }\n\n function relativeTime(posNegDuration, withoutSuffix, locale) {\n var duration = moment.duration(posNegDuration).abs(),\n seconds = round(duration.as('s')),\n minutes = round(duration.as('m')),\n hours = round(duration.as('h')),\n days = round(duration.as('d')),\n months = round(duration.as('M')),\n years = round(duration.as('y')),\n\n args = seconds < relativeTimeThresholds.s && ['s', seconds] ||\n minutes === 1 && ['m'] ||\n minutes < relativeTimeThresholds.m && ['mm', minutes] ||\n hours === 1 && ['h'] ||\n hours < relativeTimeThresholds.h && ['hh', hours] ||\n days === 1 && ['d'] ||\n days < relativeTimeThresholds.d && ['dd', days] ||\n months === 1 && ['M'] ||\n months < relativeTimeThresholds.M && ['MM', months] ||\n years === 1 && ['y'] || ['yy', years];\n\n args[2] = withoutSuffix;\n args[3] = +posNegDuration > 0;\n args[4] = locale;\n return substituteTimeAgo.apply({}, args);\n }\n\n\n /************************************\n Week of Year\n ************************************/\n\n\n // firstDayOfWeek 0 = sun, 6 = sat\n // the day of the week that starts the week\n // (usually sunday or monday)\n // firstDayOfWeekOfYear 0 = sun, 6 = sat\n // the first week is the week that contains the first\n // of this day of the week\n // (eg. ISO weeks use thursday (4))\n function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {\n var end = firstDayOfWeekOfYear - firstDayOfWeek,\n daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),\n adjustedMoment;\n\n\n if (daysToDayOfWeek > end) {\n daysToDayOfWeek -= 7;\n }\n\n if (daysToDayOfWeek < end - 7) {\n daysToDayOfWeek += 7;\n }\n\n adjustedMoment = moment(mom).add(daysToDayOfWeek, 'd');\n return {\n week: Math.ceil(adjustedMoment.dayOfYear() / 7),\n year: adjustedMoment.year()\n };\n }\n\n //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday\n function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {\n var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear;\n\n d = d === 0 ? 7 : d;\n weekday = weekday != null ? weekday : firstDayOfWeek;\n daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);\n dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;\n\n return {\n year: dayOfYear > 0 ? year : year - 1,\n dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear\n };\n }\n\n /************************************\n Top Level Functions\n ************************************/\n\n function makeMoment(config) {\n var input = config._i,\n format = config._f,\n res;\n\n config._locale = config._locale || moment.localeData(config._l);\n\n if (input === null || (format === undefined && input === '')) {\n return moment.invalid({nullInput: true});\n }\n\n if (typeof input === 'string') {\n config._i = input = config._locale.preparse(input);\n }\n\n if (moment.isMoment(input)) {\n return new Moment(input, true);\n } else if (format) {\n if (isArray(format)) {\n makeDateFromStringAndArray(config);\n } else {\n makeDateFromStringAndFormat(config);\n }\n } else {\n makeDateFromInput(config);\n }\n\n res = new Moment(config);\n if (res._nextDay) {\n // Adding is smart enough around DST\n res.add(1, 'd');\n res._nextDay = undefined;\n }\n\n return res;\n }\n\n moment = function (input, format, locale, strict) {\n var c;\n\n if (typeof(locale) === 'boolean') {\n strict = locale;\n locale = undefined;\n }\n // object construction must be done this way.\n // https://github.com/moment/moment/issues/1423\n c = {};\n c._isAMomentObject = true;\n c._i = input;\n c._f = format;\n c._l = locale;\n c._strict = strict;\n c._isUTC = false;\n c._pf = defaultParsingFlags();\n\n return makeMoment(c);\n };\n\n moment.suppressDeprecationWarnings = false;\n\n moment.createFromInputFallback = deprecate(\n 'moment construction falls back to js Date. This is ' +\n 'discouraged and will be removed in upcoming major ' +\n 'release. Please refer to ' +\n 'https://github.com/moment/moment/issues/1407 for more info.',\n function (config) {\n config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));\n }\n );\n\n // Pick a moment m from moments so that m[fn](other) is true for all\n // other. This relies on the function fn to be transitive.\n //\n // moments should either be an array of moment objects or an array, whose\n // first element is an array of moment objects.\n function pickBy(fn, moments) {\n var res, i;\n if (moments.length === 1 && isArray(moments[0])) {\n moments = moments[0];\n }\n if (!moments.length) {\n return moment();\n }\n res = moments[0];\n for (i = 1; i < moments.length; ++i) {\n if (moments[i][fn](res)) {\n res = moments[i];\n }\n }\n return res;\n }\n\n moment.min = function () {\n var args = [].slice.call(arguments, 0);\n\n return pickBy('isBefore', args);\n };\n\n moment.max = function () {\n var args = [].slice.call(arguments, 0);\n\n return pickBy('isAfter', args);\n };\n\n // creating with utc\n moment.utc = function (input, format, locale, strict) {\n var c;\n\n if (typeof(locale) === 'boolean') {\n strict = locale;\n locale = undefined;\n }\n // object construction must be done this way.\n // https://github.com/moment/moment/issues/1423\n c = {};\n c._isAMomentObject = true;\n c._useUTC = true;\n c._isUTC = true;\n c._l = locale;\n c._i = input;\n c._f = format;\n c._strict = strict;\n c._pf = defaultParsingFlags();\n\n return makeMoment(c).utc();\n };\n\n // creating with unix timestamp (in seconds)\n moment.unix = function (input) {\n return moment(input * 1000);\n };\n\n // duration\n moment.duration = function (input, key) {\n var duration = input,\n // matching against regexp is expensive, do it on demand\n match = null,\n sign,\n ret,\n parseIso,\n diffRes;\n\n if (moment.isDuration(input)) {\n duration = {\n ms: input._milliseconds,\n d: input._days,\n M: input._months\n };\n } else if (typeof input === 'number') {\n duration = {};\n if (key) {\n duration[key] = input;\n } else {\n duration.milliseconds = input;\n }\n } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {\n sign = (match[1] === '-') ? -1 : 1;\n duration = {\n y: 0,\n d: toInt(match[DATE]) * sign,\n h: toInt(match[HOUR]) * sign,\n m: toInt(match[MINUTE]) * sign,\n s: toInt(match[SECOND]) * sign,\n ms: toInt(match[MILLISECOND]) * sign\n };\n } else if (!!(match = isoDurationRegex.exec(input))) {\n sign = (match[1] === '-') ? -1 : 1;\n parseIso = function (inp) {\n // We'd normally use ~~inp for this, but unfortunately it also\n // converts floats to ints.\n // inp may be undefined, so careful calling replace on it.\n var res = inp && parseFloat(inp.replace(',', '.'));\n // apply sign while we're at it\n return (isNaN(res) ? 0 : res) * sign;\n };\n duration = {\n y: parseIso(match[2]),\n M: parseIso(match[3]),\n d: parseIso(match[4]),\n h: parseIso(match[5]),\n m: parseIso(match[6]),\n s: parseIso(match[7]),\n w: parseIso(match[8])\n };\n } else if (duration == null) {// checks for null or undefined\n duration = {};\n } else if (typeof duration === 'object' &&\n ('from' in duration || 'to' in duration)) {\n diffRes = momentsDifference(moment(duration.from), moment(duration.to));\n\n duration = {};\n duration.ms = diffRes.milliseconds;\n duration.M = diffRes.months;\n }\n\n ret = new Duration(duration);\n\n if (moment.isDuration(input) && hasOwnProp(input, '_locale')) {\n ret._locale = input._locale;\n }\n\n return ret;\n };\n\n // version number\n moment.version = VERSION;\n\n // default format\n moment.defaultFormat = isoFormat;\n\n // constant that refers to the ISO standard\n moment.ISO_8601 = function () {};\n\n // Plugins that add properties should also add the key here (null value),\n // so we can properly clone ourselves.\n moment.momentProperties = momentProperties;\n\n // This function will be called whenever a moment is mutated.\n // It is intended to keep the offset in sync with the timezone.\n moment.updateOffset = function () {};\n\n // This function allows you to set a threshold for relative time strings\n moment.relativeTimeThreshold = function (threshold, limit) {\n if (relativeTimeThresholds[threshold] === undefined) {\n return false;\n }\n if (limit === undefined) {\n return relativeTimeThresholds[threshold];\n }\n relativeTimeThresholds[threshold] = limit;\n return true;\n };\n\n moment.lang = deprecate(\n 'moment.lang is deprecated. Use moment.locale instead.',\n function (key, value) {\n return moment.locale(key, value);\n }\n );\n\n // This function will load locale and then set the global locale. If\n // no arguments are passed in, it will simply return the current global\n // locale key.\n moment.locale = function (key, values) {\n var data;\n if (key) {\n if (typeof(values) !== 'undefined') {\n data = moment.defineLocale(key, values);\n }\n else {\n data = moment.localeData(key);\n }\n\n if (data) {\n moment.duration._locale = moment._locale = data;\n }\n }\n\n return moment._locale._abbr;\n };\n\n moment.defineLocale = function (name, values) {\n if (values !== null) {\n values.abbr = name;\n if (!locales[name]) {\n locales[name] = new Locale();\n }\n locales[name].set(values);\n\n // backwards compat for now: also set the locale\n moment.locale(name);\n\n return locales[name];\n } else {\n // useful for testing\n delete locales[name];\n return null;\n }\n };\n\n moment.langData = deprecate(\n 'moment.langData is deprecated. Use moment.localeData instead.',\n function (key) {\n return moment.localeData(key);\n }\n );\n\n // returns locale data\n moment.localeData = function (key) {\n var locale;\n\n if (key && key._locale && key._locale._abbr) {\n key = key._locale._abbr;\n }\n\n if (!key) {\n return moment._locale;\n }\n\n if (!isArray(key)) {\n //short-circuit everything else\n locale = loadLocale(key);\n if (locale) {\n return locale;\n }\n key = [key];\n }\n\n return chooseLocale(key);\n };\n\n // compare moment object\n moment.isMoment = function (obj) {\n return obj instanceof Moment ||\n (obj != null && hasOwnProp(obj, '_isAMomentObject'));\n };\n\n // for typechecking Duration objects\n moment.isDuration = function (obj) {\n return obj instanceof Duration;\n };\n\n for (i = lists.length - 1; i >= 0; --i) {\n makeList(lists[i]);\n }\n\n moment.normalizeUnits = function (units) {\n return normalizeUnits(units);\n };\n\n moment.invalid = function (flags) {\n var m = moment.utc(NaN);\n if (flags != null) {\n extend(m._pf, flags);\n }\n else {\n m._pf.userInvalidated = true;\n }\n\n return m;\n };\n\n moment.parseZone = function () {\n return moment.apply(null, arguments).parseZone();\n };\n\n moment.parseTwoDigitYear = function (input) {\n return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);\n };\n\n moment.isDate = isDate;\n\n /************************************\n Moment Prototype\n ************************************/\n\n\n extend(moment.fn = Moment.prototype, {\n\n clone : function () {\n return moment(this);\n },\n\n valueOf : function () {\n return +this._d - ((this._offset || 0) * 60000);\n },\n\n unix : function () {\n return Math.floor(+this / 1000);\n },\n\n toString : function () {\n return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');\n },\n\n toDate : function () {\n return this._offset ? new Date(+this) : this._d;\n },\n\n toISOString : function () {\n var m = moment(this).utc();\n if (0 < m.year() && m.year() <= 9999) {\n if ('function' === typeof Date.prototype.toISOString) {\n // native implementation is ~50x faster, use it when we can\n return this.toDate().toISOString();\n } else {\n return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');\n }\n } else {\n return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');\n }\n },\n\n toArray : function () {\n var m = this;\n return [\n m.year(),\n m.month(),\n m.date(),\n m.hours(),\n m.minutes(),\n m.seconds(),\n m.milliseconds()\n ];\n },\n\n isValid : function () {\n return isValid(this);\n },\n\n isDSTShifted : function () {\n if (this._a) {\n return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;\n }\n\n return false;\n },\n\n parsingFlags : function () {\n return extend({}, this._pf);\n },\n\n invalidAt: function () {\n return this._pf.overflow;\n },\n\n utc : function (keepLocalTime) {\n return this.utcOffset(0, keepLocalTime);\n },\n\n local : function (keepLocalTime) {\n if (this._isUTC) {\n this.utcOffset(0, keepLocalTime);\n this._isUTC = false;\n\n if (keepLocalTime) {\n this.subtract(this._dateUtcOffset(), 'm');\n }\n }\n return this;\n },\n\n format : function (inputString) {\n var output = formatMoment(this, inputString || moment.defaultFormat);\n return this.localeData().postformat(output);\n },\n\n add : createAdder(1, 'add'),\n\n subtract : createAdder(-1, 'subtract'),\n\n diff : function (input, units, asFloat) {\n var that = makeAs(input, this),\n zoneDiff = (that.utcOffset() - this.utcOffset()) * 6e4,\n anchor, diff, output, daysAdjust;\n\n units = normalizeUnits(units);\n\n if (units === 'year' || units === 'month' || units === 'quarter') {\n output = monthDiff(this, that);\n if (units === 'quarter') {\n output = output / 3;\n } else if (units === 'year') {\n output = output / 12;\n }\n } else {\n diff = this - that;\n output = units === 'second' ? diff / 1e3 : // 1000\n units === 'minute' ? diff / 6e4 : // 1000 * 60\n units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60\n units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst\n units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst\n diff;\n }\n return asFloat ? output : absRound(output);\n },\n\n from : function (time, withoutSuffix) {\n return moment.duration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);\n },\n\n fromNow : function (withoutSuffix) {\n return this.from(moment(), withoutSuffix);\n },\n\n calendar : function (time) {\n // We want to compare the start of today, vs this.\n // Getting start-of-today depends on whether we're locat/utc/offset\n // or not.\n var now = time || moment(),\n sod = makeAs(now, this).startOf('day'),\n diff = this.diff(sod, 'days', true),\n format = diff < -6 ? 'sameElse' :\n diff < -1 ? 'lastWeek' :\n diff < 0 ? 'lastDay' :\n diff < 1 ? 'sameDay' :\n diff < 2 ? 'nextDay' :\n diff < 7 ? 'nextWeek' : 'sameElse';\n return this.format(this.localeData().calendar(format, this, moment(now)));\n },\n\n isLeapYear : function () {\n return isLeapYear(this.year());\n },\n\n isDST : function () {\n return (this.utcOffset() > this.clone().month(0).utcOffset() ||\n this.utcOffset() > this.clone().month(5).utcOffset());\n },\n\n day : function (input) {\n var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();\n if (input != null) {\n input = parseWeekday(input, this.localeData());\n return this.add(input - day, 'd');\n } else {\n return day;\n }\n },\n\n month : makeAccessor('Month', true),\n\n startOf : function (units) {\n units = normalizeUnits(units);\n // the following switch intentionally omits break keywords\n // to utilize falling through the cases.\n switch (units) {\n case 'year':\n this.month(0);\n /* falls through */\n case 'quarter':\n case 'month':\n this.date(1);\n /* falls through */\n case 'week':\n case 'isoWeek':\n case 'day':\n this.hours(0);\n /* falls through */\n case 'hour':\n this.minutes(0);\n /* falls through */\n case 'minute':\n this.seconds(0);\n /* falls through */\n case 'second':\n this.milliseconds(0);\n /* falls through */\n }\n\n // weeks are a special case\n if (units === 'week') {\n this.weekday(0);\n } else if (units === 'isoWeek') {\n this.isoWeekday(1);\n }\n\n // quarters are also special\n if (units === 'quarter') {\n this.month(Math.floor(this.month() / 3) * 3);\n }\n\n return this;\n },\n\n endOf: function (units) {\n units = normalizeUnits(units);\n if (units === undefined || units === 'millisecond') {\n return this;\n }\n return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');\n },\n\n isAfter: function (input, units) {\n var inputMs;\n units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');\n if (units === 'millisecond') {\n input = moment.isMoment(input) ? input : moment(input);\n return +this > +input;\n } else {\n inputMs = moment.isMoment(input) ? +input : +moment(input);\n return inputMs < +this.clone().startOf(units);\n }\n },\n\n isBefore: function (input, units) {\n var inputMs;\n units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');\n if (units === 'millisecond') {\n input = moment.isMoment(input) ? input : moment(input);\n return +this < +input;\n } else {\n inputMs = moment.isMoment(input) ? +input : +moment(input);\n return +this.clone().endOf(units) < inputMs;\n }\n },\n\n isBetween: function (from, to, units) {\n return this.isAfter(from, units) && this.isBefore(to, units);\n },\n\n isSame: function (input, units) {\n var inputMs;\n units = normalizeUnits(units || 'millisecond');\n if (units === 'millisecond') {\n input = moment.isMoment(input) ? input : moment(input);\n return +this === +input;\n } else {\n inputMs = +moment(input);\n return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units));\n }\n },\n\n min: deprecate(\n 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',\n function (other) {\n other = moment.apply(null, arguments);\n return other < this ? this : other;\n }\n ),\n\n max: deprecate(\n 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',\n function (other) {\n other = moment.apply(null, arguments);\n return other > this ? this : other;\n }\n ),\n\n zone : deprecate(\n 'moment().zone is deprecated, use moment().utcOffset instead. ' +\n 'https://github.com/moment/moment/issues/1779',\n function (input, keepLocalTime) {\n if (input != null) {\n if (typeof input !== 'string') {\n input = -input;\n }\n\n this.utcOffset(input, keepLocalTime);\n\n return this;\n } else {\n return -this.utcOffset();\n }\n }\n ),\n\n // keepLocalTime = true means only change the timezone, without\n // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->\n // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset\n // +0200, so we adjust the time as needed, to be valid.\n //\n // Keeping the time actually adds/subtracts (one hour)\n // from the actual represented time. That is why we call updateOffset\n // a second time. In case it wants us to change the offset again\n // _changeInProgress == true case, then we have to adjust, because\n // there is no such time in the given timezone.\n utcOffset : function (input, keepLocalTime) {\n var offset = this._offset || 0,\n localAdjust;\n if (input != null) {\n if (typeof input === 'string') {\n input = utcOffsetFromString(input);\n }\n if (Math.abs(input) < 16) {\n input = input * 60;\n }\n if (!this._isUTC && keepLocalTime) {\n localAdjust = this._dateUtcOffset();\n }\n this._offset = input;\n this._isUTC = true;\n if (localAdjust != null) {\n this.add(localAdjust, 'm');\n }\n if (offset !== input) {\n if (!keepLocalTime || this._changeInProgress) {\n addOrSubtractDurationFromMoment(this,\n moment.duration(input - offset, 'm'), 1, false);\n } else if (!this._changeInProgress) {\n this._changeInProgress = true;\n moment.updateOffset(this, true);\n this._changeInProgress = null;\n }\n }\n\n return this;\n } else {\n return this._isUTC ? offset : this._dateUtcOffset();\n }\n },\n\n isLocal : function () {\n return !this._isUTC;\n },\n\n isUtcOffset : function () {\n return this._isUTC;\n },\n\n isUtc : function () {\n return this._isUTC && this._offset === 0;\n },\n\n zoneAbbr : function () {\n return this._isUTC ? 'UTC' : '';\n },\n\n zoneName : function () {\n return this._isUTC ? 'Coordinated Universal Time' : '';\n },\n\n parseZone : function () {\n if (this._tzm) {\n this.utcOffset(this._tzm);\n } else if (typeof this._i === 'string') {\n this.utcOffset(utcOffsetFromString(this._i));\n }\n return this;\n },\n\n hasAlignedHourOffset : function (input) {\n if (!input) {\n input = 0;\n }\n else {\n input = moment(input).utcOffset();\n }\n\n return (this.utcOffset() - input) % 60 === 0;\n },\n\n daysInMonth : function () {\n return daysInMonth(this.year(), this.month());\n },\n\n dayOfYear : function (input) {\n var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;\n return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');\n },\n\n quarter : function (input) {\n return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);\n },\n\n weekYear : function (input) {\n var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year;\n return input == null ? year : this.add((input - year), 'y');\n },\n\n isoWeekYear : function (input) {\n var year = weekOfYear(this, 1, 4).year;\n return input == null ? year : this.add((input - year), 'y');\n },\n\n week : function (input) {\n var week = this.localeData().week(this);\n return input == null ? week : this.add((input - week) * 7, 'd');\n },\n\n isoWeek : function (input) {\n var week = weekOfYear(this, 1, 4).week;\n return input == null ? week : this.add((input - week) * 7, 'd');\n },\n\n weekday : function (input) {\n var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;\n return input == null ? weekday : this.add(input - weekday, 'd');\n },\n\n isoWeekday : function (input) {\n // behaves the same as moment#day except\n // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)\n // as a setter, sunday should belong to the previous week.\n return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);\n },\n\n isoWeeksInYear : function () {\n return weeksInYear(this.year(), 1, 4);\n },\n\n weeksInYear : function () {\n var weekInfo = this.localeData()._week;\n return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);\n },\n\n get : function (units) {\n units = normalizeUnits(units);\n return this[units]();\n },\n\n set : function (units, value) {\n var unit;\n if (typeof units === 'object') {\n for (unit in units) {\n this.set(unit, units[unit]);\n }\n }\n else {\n units = normalizeUnits(units);\n if (typeof this[units] === 'function') {\n this[units](value);\n }\n }\n return this;\n },\n\n // If passed a locale key, it will set the locale for this\n // instance. Otherwise, it will return the locale configuration\n // variables for this instance.\n locale : function (key) {\n var newLocaleData;\n\n if (key === undefined) {\n return this._locale._abbr;\n } else {\n newLocaleData = moment.localeData(key);\n if (newLocaleData != null) {\n this._locale = newLocaleData;\n }\n return this;\n }\n },\n\n lang : deprecate(\n 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',\n function (key) {\n if (key === undefined) {\n return this.localeData();\n } else {\n return this.locale(key);\n }\n }\n ),\n\n localeData : function () {\n return this._locale;\n },\n\n _dateUtcOffset : function () {\n // On Firefox.24 Date#getTimezoneOffset returns a floating point.\n // https://github.com/moment/moment/pull/1871\n return -Math.round(this._d.getTimezoneOffset() / 15) * 15;\n }\n\n });\n\n function rawMonthSetter(mom, value) {\n var dayOfMonth;\n\n // TODO: Move this out of here!\n if (typeof value === 'string') {\n value = mom.localeData().monthsParse(value);\n // TODO: Another silent failure?\n if (typeof value !== 'number') {\n return mom;\n }\n }\n\n dayOfMonth = Math.min(mom.date(),\n daysInMonth(mom.year(), value));\n mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);\n return mom;\n }\n\n function rawGetter(mom, unit) {\n return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]();\n }\n\n function rawSetter(mom, unit, value) {\n if (unit === 'Month') {\n return rawMonthSetter(mom, value);\n } else {\n return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);\n }\n }\n\n function makeAccessor(unit, keepTime) {\n return function (value) {\n if (value != null) {\n rawSetter(this, unit, value);\n moment.updateOffset(this, keepTime);\n return this;\n } else {\n return rawGetter(this, unit);\n }\n };\n }\n\n moment.fn.millisecond = moment.fn.milliseconds = makeAccessor('Milliseconds', false);\n moment.fn.second = moment.fn.seconds = makeAccessor('Seconds', false);\n moment.fn.minute = moment.fn.minutes = makeAccessor('Minutes', false);\n // Setting the hour should keep the time, because the user explicitly\n // specified which hour he wants. So trying to maintain the same hour (in\n // a new timezone) makes sense. Adding/subtracting hours does not follow\n // this rule.\n moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true);\n // moment.fn.month is defined separately\n moment.fn.date = makeAccessor('Date', true);\n moment.fn.dates = deprecate('dates accessor is deprecated. Use date instead.', makeAccessor('Date', true));\n moment.fn.year = makeAccessor('FullYear', true);\n moment.fn.years = deprecate('years accessor is deprecated. Use year instead.', makeAccessor('FullYear', true));\n\n // add plural methods\n moment.fn.days = moment.fn.day;\n moment.fn.months = moment.fn.month;\n moment.fn.weeks = moment.fn.week;\n moment.fn.isoWeeks = moment.fn.isoWeek;\n moment.fn.quarters = moment.fn.quarter;\n\n // add aliased format methods\n moment.fn.toJSON = moment.fn.toISOString;\n\n // alias isUtc for dev-friendliness\n moment.fn.isUTC = moment.fn.isUtc;\n\n /************************************\n Duration Prototype\n ************************************/\n\n\n function daysToYears (days) {\n // 400 years have 146097 days (taking into account leap year rules)\n return days * 400 / 146097;\n }\n\n function yearsToDays (years) {\n // years * 365 + absRound(years / 4) -\n // absRound(years / 100) + absRound(years / 400);\n return years * 146097 / 400;\n }\n\n extend(moment.duration.fn = Duration.prototype, {\n\n _bubble : function () {\n var milliseconds = this._milliseconds,\n days = this._days,\n months = this._months,\n data = this._data,\n seconds, minutes, hours, years = 0;\n\n // The following code bubbles up values, see the tests for\n // examples of what that means.\n data.milliseconds = milliseconds % 1000;\n\n seconds = absRound(milliseconds / 1000);\n data.seconds = seconds % 60;\n\n minutes = absRound(seconds / 60);\n data.minutes = minutes % 60;\n\n hours = absRound(minutes / 60);\n data.hours = hours % 24;\n\n days += absRound(hours / 24);\n\n // Accurately convert days to years, assume start from year 0.\n years = absRound(daysToYears(days));\n days -= absRound(yearsToDays(years));\n\n // 30 days to a month\n // TODO (iskren): Use anchor date (like 1st Jan) to compute this.\n months += absRound(days / 30);\n days %= 30;\n\n // 12 months -> 1 year\n years += absRound(months / 12);\n months %= 12;\n\n data.days = days;\n data.months = months;\n data.years = years;\n },\n\n abs : function () {\n this._milliseconds = Math.abs(this._milliseconds);\n this._days = Math.abs(this._days);\n this._months = Math.abs(this._months);\n\n this._data.milliseconds = Math.abs(this._data.milliseconds);\n this._data.seconds = Math.abs(this._data.seconds);\n this._data.minutes = Math.abs(this._data.minutes);\n this._data.hours = Math.abs(this._data.hours);\n this._data.months = Math.abs(this._data.months);\n this._data.years = Math.abs(this._data.years);\n\n return this;\n },\n\n weeks : function () {\n return absRound(this.days() / 7);\n },\n\n valueOf : function () {\n return this._milliseconds +\n this._days * 864e5 +\n (this._months % 12) * 2592e6 +\n toInt(this._months / 12) * 31536e6;\n },\n\n humanize : function (withSuffix) {\n var output = relativeTime(this, !withSuffix, this.localeData());\n\n if (withSuffix) {\n output = this.localeData().pastFuture(+this, output);\n }\n\n return this.localeData().postformat(output);\n },\n\n add : function (input, val) {\n // supports only 2.0-style add(1, 's') or add(moment)\n var dur = moment.duration(input, val);\n\n this._milliseconds += dur._milliseconds;\n this._days += dur._days;\n this._months += dur._months;\n\n this._bubble();\n\n return this;\n },\n\n subtract : function (input, val) {\n var dur = moment.duration(input, val);\n\n this._milliseconds -= dur._milliseconds;\n this._days -= dur._days;\n this._months -= dur._months;\n\n this._bubble();\n\n return this;\n },\n\n get : function (units) {\n units = normalizeUnits(units);\n return this[units.toLowerCase() + 's']();\n },\n\n as : function (units) {\n var days, months;\n units = normalizeUnits(units);\n\n if (units === 'month' || units === 'year') {\n days = this._days + this._milliseconds / 864e5;\n months = this._months + daysToYears(days) * 12;\n return units === 'month' ? months : months / 12;\n } else {\n // handle milliseconds separately because of floating point math errors (issue #1867)\n days = this._days + Math.round(yearsToDays(this._months / 12));\n switch (units) {\n case 'week': return days / 7 + this._milliseconds / 6048e5;\n case 'day': return days + this._milliseconds / 864e5;\n case 'hour': return days * 24 + this._milliseconds / 36e5;\n case 'minute': return days * 24 * 60 + this._milliseconds / 6e4;\n case 'second': return days * 24 * 60 * 60 + this._milliseconds / 1000;\n // Math.floor prevents floating point math errors here\n case 'millisecond': return Math.floor(days * 24 * 60 * 60 * 1000) + this._milliseconds;\n default: throw new Error('Unknown unit ' + units);\n }\n }\n },\n\n lang : moment.fn.lang,\n locale : moment.fn.locale,\n\n toIsoString : deprecate(\n 'toIsoString() is deprecated. Please use toISOString() instead ' +\n '(notice the capitals)',\n function () {\n return this.toISOString();\n }\n ),\n\n toISOString : function () {\n // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js\n var years = Math.abs(this.years()),\n months = Math.abs(this.months()),\n days = Math.abs(this.days()),\n hours = Math.abs(this.hours()),\n minutes = Math.abs(this.minutes()),\n seconds = Math.abs(this.seconds() + this.milliseconds() / 1000);\n\n if (!this.asSeconds()) {\n // this is the same as C#'s (Noda) and python (isodate)...\n // but not other JS (goog.date)\n return 'P0D';\n }\n\n return (this.asSeconds() < 0 ? '-' : '') +\n 'P' +\n (years ? years + 'Y' : '') +\n (months ? months + 'M' : '') +\n (days ? days + 'D' : '') +\n ((hours || minutes || seconds) ? 'T' : '') +\n (hours ? hours + 'H' : '') +\n (minutes ? minutes + 'M' : '') +\n (seconds ? seconds + 'S' : '');\n },\n\n localeData : function () {\n return this._locale;\n },\n\n toJSON : function () {\n return this.toISOString();\n }\n });\n\n moment.duration.fn.toString = moment.duration.fn.toISOString;\n\n function makeDurationGetter(name) {\n moment.duration.fn[name] = function () {\n return this._data[name];\n };\n }\n\n for (i in unitMillisecondFactors) {\n if (hasOwnProp(unitMillisecondFactors, i)) {\n makeDurationGetter(i.toLowerCase());\n }\n }\n\n moment.duration.fn.asMilliseconds = function () {\n return this.as('ms');\n };\n moment.duration.fn.asSeconds = function () {\n return this.as('s');\n };\n moment.duration.fn.asMinutes = function () {\n return this.as('m');\n };\n moment.duration.fn.asHours = function () {\n return this.as('h');\n };\n moment.duration.fn.asDays = function () {\n return this.as('d');\n };\n moment.duration.fn.asWeeks = function () {\n return this.as('weeks');\n };\n moment.duration.fn.asMonths = function () {\n return this.as('M');\n };\n moment.duration.fn.asYears = function () {\n return this.as('y');\n };\n\n /************************************\n Default Locale\n ************************************/\n\n\n // Set default locale, other locale will inherit from English.\n moment.locale('en', {\n ordinalParse: /\\d{1,2}(th|st|nd|rd)/,\n ordinal : function (number) {\n var b = number % 10,\n output = (toInt(number % 100 / 10) === 1) ? 'th' :\n (b === 1) ? 'st' :\n (b === 2) ? 'nd' :\n (b === 3) ? 'rd' : 'th';\n return number + output;\n }\n });\n\n /* EMBED_LOCALES */\n\n /************************************\n Exposing Moment\n ************************************/\n\n function makeGlobal(shouldDeprecate) {\n /*global ender:false */\n if (typeof ender !== 'undefined') {\n return;\n }\n oldGlobalMoment = globalScope.moment;\n if (shouldDeprecate) {\n globalScope.moment = deprecate(\n 'Accessing Moment through the global scope is ' +\n 'deprecated, and will be removed in an upcoming ' +\n 'release.',\n moment);\n } else {\n globalScope.moment = moment;\n }\n }\n\n // CommonJS module is defined\n if (hasModule) {\n module.exports = moment;\n } else if (typeof define === 'function' && define.amd) {\n define('moment',['require','exports','module'],function (require, exports, module) {\n if (module.config && module.config() && module.config().noGlobal === true) {\n // release the global variable\n globalScope.moment = oldGlobalMoment;\n }\n\n return moment;\n });\n makeGlobal(true);\n } else {\n makeGlobal();\n }\n}).call(this);\n\n","/*! Raven.js 3.15.0 (d49a1b8) | github.com/getsentry/raven-js */\n!function(a){if(\"object\"==typeof exports&&\"undefined\"!=typeof module)module.exports=a();else if(\"function\"==typeof define&&define.amd)define('Raven',[],a);else{var b;b=\"undefined\"!=typeof window?window:\"undefined\"!=typeof global?global:\"undefined\"!=typeof self?self:this,b.Raven=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i=\"function\"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error(\"Cannot find module '\"+g+\"'\");throw j.code=\"MODULE_NOT_FOUND\",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f=\"function\"==typeof require&&require,g=0;g \",i=h.length;a&&f++1&&g+e.length*i+b.length>=d));)e.push(b),g+=b.length,a=a.parentNode;return e.reverse().join(h)}function s(a){var b,c,d,e,f,g=[];if(!a||!a.tagName)return\"\";if(g.push(a.tagName.toLowerCase()),a.id&&g.push(\"#\"+a.id),b=a.className,b&&h(b))for(c=b.split(/\\s+/),f=0;fthis.k.maxBreadcrumbs&&this.t.shift(),this},addPlugin:function(a){var b=[].slice.call(arguments,1);return this.q.push([a,b]),this.m&&this.C(),this},setUserContext:function(a){return this.j.user=a,this},setExtraContext:function(a){return this.Q(\"extra\",a),this},setTagsContext:function(a){return this.Q(\"tags\",a),this},clearContext:function(){return this.j={},this},getContext:function(){return JSON.parse(y(this.j))},setEnvironment:function(a){return this.k.environment=a,this},setRelease:function(a){return this.k.release=a,this},setDataCallback:function(a){var b=this.k.dataCallback;return this.k.dataCallback=g(a)?function(c){return a(c,b)}:a,this},setBreadcrumbCallback:function(a){var b=this.k.breadcrumbCallback;return this.k.breadcrumbCallback=g(a)?function(c){return a(c,b)}:a,this},setShouldSendCallback:function(a){var b=this.k.shouldSendCallback;return this.k.shouldSendCallback=g(a)?function(c){return a(c,b)}:a,this},setTransport:function(a){return this.k.transport=a,this},lastException:function(){return this.d},lastEventId:function(){return this.f},isSetup:function(){return!!this.a&&(!!this.g||(this.ravenNotConfiguredError||(this.ravenNotConfiguredError=!0,this.y(\"error\",\"Error: Raven has not been configured.\")),!1))},afterLoad:function(){var a=G.RavenConfig;a&&this.config(a.dsn,a.config).install()},showReportDialog:function(a){if(H){a=a||{};var b=a.eventId||this.lastEventId();if(!b)throw new z(\"Missing eventId\");var c=a.dsn||this.E;if(!c)throw new z(\"Missing DSN\");var d=encodeURIComponent,e=\"\";e+=\"?eventId=\"+d(b),e+=\"&dsn=\"+d(c);var f=a.user||this.j.user;f&&(f.name&&(e+=\"&name=\"+d(f.name)),f.email&&(e+=\"&email=\"+d(f.email)));var g=this.G(this.D(c)),h=H.createElement(\"script\");h.async=!0,h.src=g+\"/api/embed/error-page/\"+e,(H.head||H.body).appendChild(h)}},I:function(){var a=this;this.l+=1,setTimeout(function(){a.l-=1})},R:function(a,b){var c,d;if(this.b){b=b||{},a=\"raven\"+a.substr(0,1).toUpperCase()+a.substr(1),H.createEvent?(c=H.createEvent(\"HTMLEvents\"),c.initEvent(a,!0,!0)):(c=H.createEventObject(),c.eventType=a);for(d in b)m(b,d)&&(c[d]=b[d]);if(H.createEvent)H.dispatchEvent(c);else try{H.fireEvent(\"on\"+c.eventType.toLowerCase(),c)}catch(e){}}},S:function(a){var b=this;return function(c){if(b.T=null,b.u!==c){b.u=c;var d;try{d=r(c.target)}catch(e){d=\"\"}b.captureBreadcrumb({category:\"ui.\"+a,message:d})}}},U:function(){var a=this,b=1e3;return function(c){var d;try{d=c.target}catch(e){return}var f=d&&d.tagName;if(f&&(\"INPUT\"===f||\"TEXTAREA\"===f||d.isContentEditable)){var g=a.T;g||a.S(\"input\")(c),clearTimeout(g),a.T=setTimeout(function(){a.T=null},b)}}},V:function(a,b){var c=p(this.v.href),d=p(b),e=p(a);this.w=b,c.protocol===d.protocol&&c.host===d.host&&(b=d.relative),c.protocol===e.protocol&&c.host===e.host&&(a=e.relative),this.captureBreadcrumb({category:\"navigation\",data:{to:b,from:a}})},A:function(){function a(a){return function(b,d){for(var e=new Array(arguments.length),f=0;f2?arguments[2]:void 0;return c&&b.V(b.w,c+\"\"),a.apply(this,arguments)}},d)}if(c.console&&\"console\"in G&&console.log){var m=function(a,c){b.captureBreadcrumb({message:a,level:c.level,category:\"console\"})};j([\"debug\",\"info\",\"warn\",\"error\",\"log\"],function(a,b){D(console,b,m)})}},M:function(){for(var a;this.s.length;){a=this.s.shift();var b=a[0],c=a[1],d=a[2];b[c]=d}},C:function(){var a=this;j(this.q,function(b,c){var d=c[0],e=c[1];d.apply(a,[a].concat(e))})},D:function(a){var b=F.exec(a),c={},d=7;try{for(;d--;)c[E[d]]=b[d]||\"\"}catch(e){throw new z(\"Invalid DSN: \"+a)}if(c.pass&&!this.k.allowSecretKey)throw new z(\"Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key\");return c},G:function(a){var b=\"//\"+a.host+(a.port?\":\"+a.port:\"\");return a.protocol&&(b=a.protocol+\":\"+b),b},z:function(){this.l||this.N.apply(this,arguments)},N:function(a,b){var c=this.O(a,b);this.R(\"handle\",{stackInfo:a,options:b}),this.X(a.name,a.message,a.url,a.lineno,c,b)},O:function(a,b){var c=this,d=[];if(a.stack&&a.stack.length&&(j(a.stack,function(a,b){var e=c.Y(b);e&&d.push(e)}),b&&b.trimHeadFrames))for(var e=0;e0&&(a.breadcrumbs={values:[].slice.call(this.t,0)}),i(a.tags)&&delete a.tags,this.j.user&&(a.user=this.j.user),b.environment&&(a.environment=b.environment),b.release&&(a.release=b.release),b.serverName&&(a.server_name=b.serverName),g(b.dataCallback)&&(a=b.dataCallback(a)||a),a&&!i(a)&&(!g(b.shouldSendCallback)||b.shouldSendCallback(a)))return this.ca()?void this.y(\"warn\",\"Raven dropped error due to backoff: \",a):void(\"number\"==typeof b.sampleRate?Math.random()=0;--b)s[b]===a&&s.splice(b,1)}function c(){n(),s=[]}function k(a,b){var c=null;if(!b||f.collectWindowErrors){for(var d in s)if(s.hasOwnProperty(d))try{s[d].apply(null,[a].concat(h.call(arguments,2)))}catch(e){c=e}if(c)throw c}}function l(a,b,c,g,h){var l=null;if(v)f.computeStackTrace.augmentStackTraceWithInitialElement(v,b,c,a),o();else if(h&&e.isError(h))l=f.computeStackTrace(h),k(l,!0);else{var m,n={url:b,line:c,column:g},p=void 0,r=a;if(\"[object String]\"==={}.toString.call(a)){var m=a.match(j);m&&(p=m[1],r=m[2])}n.func=i,l={name:p,message:r,url:d(),stack:[n]},k(l,!0)}return!!q&&q.apply(this,arguments)}function m(){r||(q=g.onerror,g.onerror=l,r=!0)}function n(){r&&(g.onerror=q,r=!1,q=void 0)}function o(){var a=v,b=t;t=null,v=null,u=null,k.apply(null,[a,!1].concat(b))}function p(a,b){var c=h.call(arguments,1);if(v){if(u===a)return;o()}var d=f.computeStackTrace(a);if(v=d,u=a,t=c,setTimeout(function(){u===a&&o()},d.incomplete?2e3:0),b!==!1)throw a}var q,r,s=[],t=null,u=null,v=null;return p.subscribe=a,p.unsubscribe=b,p.uninstall=c,p}(),f.computeStackTrace=function(){function a(a){if(\"undefined\"!=typeof a.stack&&a.stack){for(var b,c,e,f=/^\\s*at (.*?) ?\\(((?:file|https?|blob|chrome-extension|native|eval|webpack||\\/).*?)(?::(\\d+))?(?::(\\d+))?\\)?\\s*$/i,g=/^\\s*(.*?)(?:\\((.*?)\\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\\[native).*?)(?::(\\d+))?(?::(\\d+))?\\s*$/i,h=/^\\s*at (?:((?:\\[object object\\])?.+) )?\\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\\d+)(?::(\\d+))?\\)?\\s*$/i,j=/(\\S+) line (\\d+)(?: > eval line \\d+)* > eval/i,k=/\\((\\S*)(?::(\\d+))(?::(\\d+))\\)/,l=a.stack.split(\"\\n\"),m=[],n=(/^(.*) is undefined$/.exec(a.message),0),o=l.length;n eval\")>-1;q&&(b=j.exec(c[3]))?(c[3]=b[1],c[4]=b[2],c[5]=null):0!==n||c[5]||\"undefined\"==typeof a.columnNumber||(m[0].column=a.columnNumber+1),e={url:c[3],func:c[1]||i,args:c[2]?c[2].split(\",\"):[],line:c[4]?+c[4]:null,column:c[5]?+c[5]:null}}!e.func&&e.line&&(e.func=i),m.push(e)}return m.length?{name:a.name,message:a.message,url:d(),stack:m}:null}}function b(a,b,c,d){var e={url:b,line:c};if(e.url&&e.line){if(a.incomplete=!1,e.func||(e.func=i),a.stack.length>0&&a.stack[0].url===e.url){if(a.stack[0].line===e.line)return!1;if(!a.stack[0].line&&a.stack[0].func===e.func)return a.stack[0].line=e.line,!1}return a.stack.unshift(e),a.partial=!0,!0}return a.incomplete=!0,!1}function c(a,g){for(var h,j,k=/function\\s+([_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*)?\\s*\\(/i,l=[],m={},n=!1,o=c.caller;o&&!n;o=o.caller)if(o!==e&&o!==f.report){if(j={url:null,func:i,line:null,column:null},o.name?j.func=o.name:(h=k.exec(o.toString()))&&(j.func=h[1]),\"undefined\"==typeof j.func)try{j.func=h.input.substring(0,h.input.indexOf(\"{\"))}catch(p){}m[\"\"+o]?n=!0:m[\"\"+o]=!0,l.push(j)}g&&l.splice(0,g);var q={name:a.name,message:a.message,url:d(),stack:l};return b(q,a.sourceURL||a.fileName,a.line||a.lineNumber,a.message||a.description),q}function e(b,e){var g=null;e=null==e?0:+e;try{if(g=a(b))return g}catch(h){if(f.debug)throw h}try{if(g=c(b,e+1))return g}catch(h){if(f.debug)throw h}return{name:b.name,message:b.message,url:d()}}return e.augmentStackTraceWithInitialElement=b,e.computeStackTraceFromStackProp=a,e}(),b.exports=f}).call(this,\"undefined\"!=typeof global?global:\"undefined\"!=typeof self?self:\"undefined\"!=typeof window?window:{})},{5:5}],7:[function(a,b,c){\"use strict\";function d(a,b){for(var c=0;c0){var h=d(c,this);~h?c.splice(h+1):c.push(this),~h?e.splice(h,1/0,f):e.push(f),~d(c,g)&&(g=b.call(this,f,g))}else c.push(g);return null==a?g:a.call(this,f,g)}}c=b.exports=e,c.getSerialize=f},{}]},{},[4])(4)});\n//# sourceMappingURL=raven.min.js.map;\n","/**\n * @devseev:\n * It's the copy of source-maps library from https://github.com/mozilla/source-map.\n * Here method define renamed to define2 to prevent clashes with requirejs.\n * Is used to \"manually\" parse source of the errors in minified code.\n * See http://stackoverflow.com/questions/19420604/angularjs-stack-trace-ignoring-source-map\n */\n\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\n\n/**\n * Define a module along with a payload.\n * @param {string} moduleName Name for the payload\n * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec\n * @param {function} payload Function with (require, exports, module) params\n */\nfunction define2(moduleName, deps, payload) {\n if (typeof moduleName != \"string\") {\n throw new TypeError('Expected string, got: ' + moduleName);\n }\n\n if (arguments.length == 2) {\n payload = deps;\n }\n\n if (moduleName in define2.modules) {\n throw new Error(\"Module already defined: \" + moduleName);\n }\n define2.modules[moduleName] = payload;\n};\n\n/**\n * The global store of un-instantiated modules\n */\ndefine2.modules = {};\n\n\n/**\n * We invoke require() in the context of a Domain so we can have multiple\n * sets of modules running separate from each other.\n * This contrasts with JSMs which are singletons, Domains allows us to\n * optionally load a CommonJS module twice with separate data each time.\n * Perhaps you want 2 command lines with a different set of commands in each,\n * for example.\n */\nfunction Domain() {\n this.modules = {};\n this._currentModule = null;\n}\n\n(function () {\n\n /**\n * Lookup module names and resolve them by calling the definition function if\n * needed.\n * There are 2 ways to call this, either with an array of dependencies and a\n * callback to call when the dependencies are found (which can happen\n * asynchronously in an in-page context) or with a single string an no callback\n * where the dependency is resolved synchronously and returned.\n * The API is designed to be compatible with the CommonJS AMD spec and\n * RequireJS.\n * @param {string[]|string} deps A name, or names for the payload\n * @param {function|undefined} callback Function to call when the dependencies\n * are resolved\n * @return {undefined|object} The module required or undefined for\n * array/callback method\n */\n Domain.prototype.require = function(deps, callback) {\n if (Array.isArray(deps)) {\n var params = deps.map(function(dep) {\n return this.lookup(dep);\n }, this);\n if (callback) {\n callback.apply(null, params);\n }\n return undefined;\n }\n else {\n return this.lookup(deps);\n }\n };\n\n function normalize(path) {\n var bits = path.split('/');\n var i = 1;\n while (i < bits.length) {\n if (bits[i] === '..') {\n bits.splice(i-1, 1);\n } else if (bits[i] === '.') {\n bits.splice(i, 1);\n } else {\n i++;\n }\n }\n return bits.join('/');\n }\n\n function join(a, b) {\n a = a.trim();\n b = b.trim();\n if (/^\\//.test(b)) {\n return b;\n } else {\n return a.replace(/\\/*$/, '/') + b;\n }\n }\n\n function dirname(path) {\n var bits = path.split('/');\n bits.pop();\n return bits.join('/');\n }\n\n /**\n * Lookup module names and resolve them by calling the definition function if\n * needed.\n * @param {string} moduleName A name for the payload to lookup\n * @return {object} The module specified by aModuleName or null if not found.\n */\n Domain.prototype.lookup = function(moduleName) {\n if (/^\\./.test(moduleName)) {\n moduleName = normalize(join(dirname(this._currentModule), moduleName));\n }\n\n if (moduleName in this.modules) {\n var module = this.modules[moduleName];\n return module;\n }\n\n if (!(moduleName in define2.modules)) {\n throw new Error(\"Module not defined: \" + moduleName);\n }\n\n var module = define2.modules[moduleName];\n\n if (typeof module == \"function\") {\n var exports = {};\n var previousModule = this._currentModule;\n this._currentModule = moduleName;\n module(this.require.bind(this), exports, { id: moduleName, uri: \"\" });\n this._currentModule = previousModule;\n module = exports;\n }\n\n // cache the resulting module object for next time\n this.modules[moduleName] = module;\n\n return module;\n };\n\n}());\n\ndefine2.Domain = Domain;\ndefine2.globalDomain = new Domain();\nvar require = define2.globalDomain.require.bind(define2.globalDomain);\n/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\ndefine2('source-map/source-map-generator', ['require', 'exports', 'module' , 'source-map/base64-vlq', 'source-map/util', 'source-map/array-set', 'source-map/mapping-list'], function(require, exports, module) {\n\n var base64VLQ = require('./base64-vlq');\n var util = require('./util');\n var ArraySet = require('./array-set').ArraySet;\n var MappingList = require('./mapping-list').MappingList;\n\n /**\n * An instance of the SourceMapGenerator represents a source map which is\n * being built incrementally. You may pass an object with the following\n * properties:\n *\n * - file: The filename of the generated source.\n * - sourceRoot: A root for all relative URLs in this source map.\n */\n function SourceMapGenerator(aArgs) {\n if (!aArgs) {\n aArgs = {};\n }\n this._file = util.getArg(aArgs, 'file', null);\n this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);\n this._skipValidation = util.getArg(aArgs, 'skipValidation', false);\n this._sources = new ArraySet();\n this._names = new ArraySet();\n this._mappings = new MappingList();\n this._sourcesContents = null;\n }\n\n SourceMapGenerator.prototype._version = 3;\n\n /**\n * Creates a new SourceMapGenerator based on a SourceMapConsumer\n *\n * @param aSourceMapConsumer The SourceMap.\n */\n SourceMapGenerator.fromSourceMap =\n function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {\n var sourceRoot = aSourceMapConsumer.sourceRoot;\n var generator = new SourceMapGenerator({\n file: aSourceMapConsumer.file,\n sourceRoot: sourceRoot\n });\n aSourceMapConsumer.eachMapping(function (mapping) {\n var newMapping = {\n generated: {\n line: mapping.generatedLine,\n column: mapping.generatedColumn\n }\n };\n\n if (mapping.source != null) {\n newMapping.source = mapping.source;\n if (sourceRoot != null) {\n newMapping.source = util.relative(sourceRoot, newMapping.source);\n }\n\n newMapping.original = {\n line: mapping.originalLine,\n column: mapping.originalColumn\n };\n\n if (mapping.name != null) {\n newMapping.name = mapping.name;\n }\n }\n\n generator.addMapping(newMapping);\n });\n aSourceMapConsumer.sources.forEach(function (sourceFile) {\n var content = aSourceMapConsumer.sourceContentFor(sourceFile);\n if (content != null) {\n generator.setSourceContent(sourceFile, content);\n }\n });\n return generator;\n };\n\n /**\n * Add a single mapping from original source line and column to the generated\n * source's line and column for this source map being created. The mapping\n * object should have the following properties:\n *\n * - generated: An object with the generated line and column positions.\n * - original: An object with the original line and column positions.\n * - source: The original source file (relative to the sourceRoot).\n * - name: An optional original token name for this mapping.\n */\n SourceMapGenerator.prototype.addMapping =\n function SourceMapGenerator_addMapping(aArgs) {\n var generated = util.getArg(aArgs, 'generated');\n var original = util.getArg(aArgs, 'original', null);\n var source = util.getArg(aArgs, 'source', null);\n var name = util.getArg(aArgs, 'name', null);\n\n if (!this._skipValidation) {\n this._validateMapping(generated, original, source, name);\n }\n\n if (source != null && !this._sources.has(source)) {\n this._sources.add(source);\n }\n\n if (name != null && !this._names.has(name)) {\n this._names.add(name);\n }\n\n this._mappings.add({\n generatedLine: generated.line,\n generatedColumn: generated.column,\n originalLine: original != null && original.line,\n originalColumn: original != null && original.column,\n source: source,\n name: name\n });\n };\n\n /**\n * Set the source content for a source file.\n */\n SourceMapGenerator.prototype.setSourceContent =\n function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {\n var source = aSourceFile;\n if (this._sourceRoot != null) {\n source = util.relative(this._sourceRoot, source);\n }\n\n if (aSourceContent != null) {\n // Add the source content to the _sourcesContents map.\n // Create a new _sourcesContents map if the property is null.\n if (!this._sourcesContents) {\n this._sourcesContents = {};\n }\n this._sourcesContents[util.toSetString(source)] = aSourceContent;\n } else if (this._sourcesContents) {\n // Remove the source file from the _sourcesContents map.\n // If the _sourcesContents map is empty, set the property to null.\n delete this._sourcesContents[util.toSetString(source)];\n if (Object.keys(this._sourcesContents).length === 0) {\n this._sourcesContents = null;\n }\n }\n };\n\n /**\n * Applies the mappings of a sub-source-map for a specific source file to the\n * source map being generated. Each mapping to the supplied source file is\n * rewritten using the supplied source map. Note: The resolution for the\n * resulting mappings is the minimium of this map and the supplied map.\n *\n * @param aSourceMapConsumer The source map to be applied.\n * @param aSourceFile Optional. The filename of the source file.\n * If omitted, SourceMapConsumer's file property will be used.\n * @param aSourceMapPath Optional. The dirname of the path to the source map\n * to be applied. If relative, it is relative to the SourceMapConsumer.\n * This parameter is needed when the two source maps aren't in the same\n * directory, and the source map to be applied contains relative source\n * paths. If so, those relative source paths need to be rewritten\n * relative to the SourceMapGenerator.\n */\n SourceMapGenerator.prototype.applySourceMap =\n function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {\n var sourceFile = aSourceFile;\n // If aSourceFile is omitted, we will use the file property of the SourceMap\n if (aSourceFile == null) {\n if (aSourceMapConsumer.file == null) {\n throw new Error(\n 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' +\n 'or the source map\\'s \"file\" property. Both were omitted.'\n );\n }\n sourceFile = aSourceMapConsumer.file;\n }\n var sourceRoot = this._sourceRoot;\n // Make \"sourceFile\" relative if an absolute Url is passed.\n if (sourceRoot != null) {\n sourceFile = util.relative(sourceRoot, sourceFile);\n }\n // Applying the SourceMap can add and remove items from the sources and\n // the names array.\n var newSources = new ArraySet();\n var newNames = new ArraySet();\n\n // Find mappings for the \"sourceFile\"\n this._mappings.unsortedForEach(function (mapping) {\n if (mapping.source === sourceFile && mapping.originalLine != null) {\n // Check if it can be mapped by the source map, then update the mapping.\n var original = aSourceMapConsumer.originalPositionFor({\n line: mapping.originalLine,\n column: mapping.originalColumn\n });\n if (original.source != null) {\n // Copy mapping\n mapping.source = original.source;\n if (aSourceMapPath != null) {\n mapping.source = util.join(aSourceMapPath, mapping.source)\n }\n if (sourceRoot != null) {\n mapping.source = util.relative(sourceRoot, mapping.source);\n }\n mapping.originalLine = original.line;\n mapping.originalColumn = original.column;\n if (original.name != null) {\n mapping.name = original.name;\n }\n }\n }\n\n var source = mapping.source;\n if (source != null && !newSources.has(source)) {\n newSources.add(source);\n }\n\n var name = mapping.name;\n if (name != null && !newNames.has(name)) {\n newNames.add(name);\n }\n\n }, this);\n this._sources = newSources;\n this._names = newNames;\n\n // Copy sourcesContents of applied map.\n aSourceMapConsumer.sources.forEach(function (sourceFile) {\n var content = aSourceMapConsumer.sourceContentFor(sourceFile);\n if (content != null) {\n if (aSourceMapPath != null) {\n sourceFile = util.join(aSourceMapPath, sourceFile);\n }\n if (sourceRoot != null) {\n sourceFile = util.relative(sourceRoot, sourceFile);\n }\n this.setSourceContent(sourceFile, content);\n }\n }, this);\n };\n\n /**\n * A mapping can have one of the three levels of data:\n *\n * 1. Just the generated position.\n * 2. The Generated position, original position, and original source.\n * 3. Generated and original position, original source, as well as a name\n * token.\n *\n * To maintain consistency, we validate that any new mapping being added falls\n * in to one of these categories.\n */\n SourceMapGenerator.prototype._validateMapping =\n function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource,\n aName) {\n if (aGenerated && 'line' in aGenerated && 'column' in aGenerated\n && aGenerated.line > 0 && aGenerated.column >= 0\n && !aOriginal && !aSource && !aName) {\n // Case 1.\n return;\n }\n else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated\n && aOriginal && 'line' in aOriginal && 'column' in aOriginal\n && aGenerated.line > 0 && aGenerated.column >= 0\n && aOriginal.line > 0 && aOriginal.column >= 0\n && aSource) {\n // Cases 2 and 3.\n return;\n }\n else {\n throw new Error('Invalid mapping: ' + JSON.stringify({\n generated: aGenerated,\n source: aSource,\n original: aOriginal,\n name: aName\n }));\n }\n };\n\n /**\n * Serialize the accumulated mappings in to the stream of base 64 VLQs\n * specified by the source map format.\n */\n SourceMapGenerator.prototype._serializeMappings =\n function SourceMapGenerator_serializeMappings() {\n var previousGeneratedColumn = 0;\n var previousGeneratedLine = 1;\n var previousOriginalColumn = 0;\n var previousOriginalLine = 0;\n var previousName = 0;\n var previousSource = 0;\n var result = '';\n var mapping;\n\n var mappings = this._mappings.toArray();\n\n for (var i = 0, len = mappings.length; i < len; i++) {\n mapping = mappings[i];\n\n if (mapping.generatedLine !== previousGeneratedLine) {\n previousGeneratedColumn = 0;\n while (mapping.generatedLine !== previousGeneratedLine) {\n result += ';';\n previousGeneratedLine++;\n }\n }\n else {\n if (i > 0) {\n if (!util.compareByGeneratedPositions(mapping, mappings[i - 1])) {\n continue;\n }\n result += ',';\n }\n }\n\n result += base64VLQ.encode(mapping.generatedColumn\n - previousGeneratedColumn);\n previousGeneratedColumn = mapping.generatedColumn;\n\n if (mapping.source != null) {\n result += base64VLQ.encode(this._sources.indexOf(mapping.source)\n - previousSource);\n previousSource = this._sources.indexOf(mapping.source);\n\n // lines are stored 0-based in SourceMap spec version 3\n result += base64VLQ.encode(mapping.originalLine - 1\n - previousOriginalLine);\n previousOriginalLine = mapping.originalLine - 1;\n\n result += base64VLQ.encode(mapping.originalColumn\n - previousOriginalColumn);\n previousOriginalColumn = mapping.originalColumn;\n\n if (mapping.name != null) {\n result += base64VLQ.encode(this._names.indexOf(mapping.name)\n - previousName);\n previousName = this._names.indexOf(mapping.name);\n }\n }\n }\n\n return result;\n };\n\n SourceMapGenerator.prototype._generateSourcesContent =\n function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {\n return aSources.map(function (source) {\n if (!this._sourcesContents) {\n return null;\n }\n if (aSourceRoot != null) {\n source = util.relative(aSourceRoot, source);\n }\n var key = util.toSetString(source);\n return Object.prototype.hasOwnProperty.call(this._sourcesContents,\n key)\n ? this._sourcesContents[key]\n : null;\n }, this);\n };\n\n /**\n * Externalize the source map.\n */\n SourceMapGenerator.prototype.toJSON =\n function SourceMapGenerator_toJSON() {\n var map = {\n version: this._version,\n sources: this._sources.toArray(),\n names: this._names.toArray(),\n mappings: this._serializeMappings()\n };\n if (this._file != null) {\n map.file = this._file;\n }\n if (this._sourceRoot != null) {\n map.sourceRoot = this._sourceRoot;\n }\n if (this._sourcesContents) {\n map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);\n }\n\n return map;\n };\n\n /**\n * Render the source map being generated to a string.\n */\n SourceMapGenerator.prototype.toString =\n function SourceMapGenerator_toString() {\n return JSON.stringify(this.toJSON());\n };\n\n exports.SourceMapGenerator = SourceMapGenerator;\n\n});\n/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n *\n * Based on the Base 64 VLQ implementation in Closure Compiler:\n * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java\n *\n * Copyright 2011 The Closure Compiler Authors. All rights reserved.\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following\n * disclaimer in the documentation and/or other materials provided\n * with the distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived\n * from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\ndefine2('source-map/base64-vlq', ['require', 'exports', 'module' , 'source-map/base64'], function(require, exports, module) {\n\n var base64 = require('./base64');\n\n // A single base 64 digit can contain 6 bits of data. For the base 64 variable\n // length quantities we use in the source map spec, the first bit is the sign,\n // the next four bits are the actual value, and the 6th bit is the\n // continuation bit. The continuation bit tells us whether there are more\n // digits in this value following this digit.\n //\n // Continuation\n // | Sign\n // | |\n // V V\n // 101011\n\n var VLQ_BASE_SHIFT = 5;\n\n // binary: 100000\n var VLQ_BASE = 1 << VLQ_BASE_SHIFT;\n\n // binary: 011111\n var VLQ_BASE_MASK = VLQ_BASE - 1;\n\n // binary: 100000\n var VLQ_CONTINUATION_BIT = VLQ_BASE;\n\n /**\n * Converts from a two-complement value to a value where the sign bit is\n * placed in the least significant bit. For example, as decimals:\n * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)\n * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)\n */\n function toVLQSigned(aValue) {\n return aValue < 0\n ? ((-aValue) << 1) + 1\n : (aValue << 1) + 0;\n }\n\n /**\n * Converts to a two-complement value from a value where the sign bit is\n * placed in the least significant bit. For example, as decimals:\n * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1\n * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2\n */\n function fromVLQSigned(aValue) {\n var isNegative = (aValue & 1) === 1;\n var shifted = aValue >> 1;\n return isNegative\n ? -shifted\n : shifted;\n }\n\n /**\n * Returns the base 64 VLQ encoded value.\n */\n exports.encode = function base64VLQ_encode(aValue) {\n var encoded = \"\";\n var digit;\n\n var vlq = toVLQSigned(aValue);\n\n do {\n digit = vlq & VLQ_BASE_MASK;\n vlq >>>= VLQ_BASE_SHIFT;\n if (vlq > 0) {\n // There are still more digits in this value, so we must make sure the\n // continuation bit is marked.\n digit |= VLQ_CONTINUATION_BIT;\n }\n encoded += base64.encode(digit);\n } while (vlq > 0);\n\n return encoded;\n };\n\n /**\n * Decodes the next base 64 VLQ value from the given string and returns the\n * value and the rest of the string via the out parameter.\n */\n exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) {\n var strLen = aStr.length;\n var result = 0;\n var shift = 0;\n var continuation, digit;\n\n do {\n if (aIndex >= strLen) {\n throw new Error(\"Expected more digits in base 64 VLQ value.\");\n }\n digit = base64.decode(aStr.charAt(aIndex++));\n continuation = !!(digit & VLQ_CONTINUATION_BIT);\n digit &= VLQ_BASE_MASK;\n result = result + (digit << shift);\n shift += VLQ_BASE_SHIFT;\n } while (continuation);\n\n aOutParam.value = fromVLQSigned(result);\n aOutParam.rest = aIndex;\n };\n\n});\n/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\ndefine2('source-map/base64', ['require', 'exports', 'module' , ], function(require, exports, module) {\n\n var charToIntMap = {};\n var intToCharMap = {};\n\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n .split('')\n .forEach(function (ch, index) {\n charToIntMap[ch] = index;\n intToCharMap[index] = ch;\n });\n\n /**\n * Encode an integer in the range of 0 to 63 to a single base 64 digit.\n */\n exports.encode = function base64_encode(aNumber) {\n if (aNumber in intToCharMap) {\n return intToCharMap[aNumber];\n }\n throw new TypeError(\"Must be between 0 and 63: \" + aNumber);\n };\n\n /**\n * Decode a single base 64 digit to an integer.\n */\n exports.decode = function base64_decode(aChar) {\n if (aChar in charToIntMap) {\n return charToIntMap[aChar];\n }\n throw new TypeError(\"Not a valid base 64 digit: \" + aChar);\n };\n\n});\n/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\ndefine2('source-map/util', ['require', 'exports', 'module' , ], function(require, exports, module) {\n\n /**\n * This is a helper function for getting values from parameter/options\n * objects.\n *\n * @param args The object we are extracting values from\n * @param name The name of the property we are getting.\n * @param defaultValue An optional value to return if the property is missing\n * from the object. If this is not specified and the property is missing, an\n * error will be thrown.\n */\n function getArg(aArgs, aName, aDefaultValue) {\n if (aName in aArgs) {\n return aArgs[aName];\n } else if (arguments.length === 3) {\n return aDefaultValue;\n } else {\n throw new Error('\"' + aName + '\" is a required argument.');\n }\n }\n exports.getArg = getArg;\n\n var urlRegexp = /^(?:([\\w+\\-.]+):)?\\/\\/(?:(\\w+:\\w+)@)?([\\w.]*)(?::(\\d+))?(\\S*)$/;\n var dataUrlRegexp = /^data:.+\\,.+$/;\n\n function urlParse(aUrl) {\n var match = aUrl.match(urlRegexp);\n if (!match) {\n return null;\n }\n return {\n scheme: match[1],\n auth: match[2],\n host: match[3],\n port: match[4],\n path: match[5]\n };\n }\n exports.urlParse = urlParse;\n\n function urlGenerate(aParsedUrl) {\n var url = '';\n if (aParsedUrl.scheme) {\n url += aParsedUrl.scheme + ':';\n }\n url += '//';\n if (aParsedUrl.auth) {\n url += aParsedUrl.auth + '@';\n }\n if (aParsedUrl.host) {\n url += aParsedUrl.host;\n }\n if (aParsedUrl.port) {\n url += \":\" + aParsedUrl.port\n }\n if (aParsedUrl.path) {\n url += aParsedUrl.path;\n }\n return url;\n }\n exports.urlGenerate = urlGenerate;\n\n /**\n * Normalizes a path, or the path portion of a URL:\n *\n * - Replaces consequtive slashes with one slash.\n * - Removes unnecessary '.' parts.\n * - Removes unnecessary '/..' parts.\n *\n * Based on code in the Node.js 'path' core module.\n *\n * @param aPath The path or url to normalize.\n */\n function normalize(aPath) {\n var path = aPath;\n var url = urlParse(aPath);\n if (url) {\n if (!url.path) {\n return aPath;\n }\n path = url.path;\n }\n var isAbsolute = (path.charAt(0) === '/');\n\n var parts = path.split(/\\/+/);\n for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {\n part = parts[i];\n if (part === '.') {\n parts.splice(i, 1);\n } else if (part === '..') {\n up++;\n } else if (up > 0) {\n if (part === '') {\n // The first part is blank if the path is absolute. Trying to go\n // above the root is a no-op. Therefore we can remove all '..' parts\n // directly after the root.\n parts.splice(i + 1, up);\n up = 0;\n } else {\n parts.splice(i, 2);\n up--;\n }\n }\n }\n path = parts.join('/');\n\n if (path === '') {\n path = isAbsolute ? '/' : '.';\n }\n\n if (url) {\n url.path = path;\n return urlGenerate(url);\n }\n return path;\n }\n exports.normalize = normalize;\n\n /**\n * Joins two paths/URLs.\n *\n * @param aRoot The root path or URL.\n * @param aPath The path or URL to be joined with the root.\n *\n * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a\n * scheme-relative URL: Then the scheme of aRoot, if any, is prepended\n * first.\n * - Otherwise aPath is a path. If aRoot is a URL, then its path portion\n * is updated with the result and aRoot is returned. Otherwise the result\n * is returned.\n * - If aPath is absolute, the result is aPath.\n * - Otherwise the two paths are joined with a slash.\n * - Joining for example 'http://' and 'www.example.com' is also supported.\n */\n function join(aRoot, aPath) {\n if (aRoot === \"\") {\n aRoot = \".\";\n }\n if (aPath === \"\") {\n aPath = \".\";\n }\n var aPathUrl = urlParse(aPath);\n var aRootUrl = urlParse(aRoot);\n if (aRootUrl) {\n aRoot = aRootUrl.path || '/';\n }\n\n // `join(foo, '//www.example.org')`\n if (aPathUrl && !aPathUrl.scheme) {\n if (aRootUrl) {\n aPathUrl.scheme = aRootUrl.scheme;\n }\n return urlGenerate(aPathUrl);\n }\n\n if (aPathUrl || aPath.match(dataUrlRegexp)) {\n return aPath;\n }\n\n // `join('http://', 'www.example.com')`\n if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {\n aRootUrl.host = aPath;\n return urlGenerate(aRootUrl);\n }\n\n var joined = aPath.charAt(0) === '/'\n ? aPath\n : normalize(aRoot.replace(/\\/+$/, '') + '/' + aPath);\n\n if (aRootUrl) {\n aRootUrl.path = joined;\n return urlGenerate(aRootUrl);\n }\n return joined;\n }\n exports.join = join;\n\n /**\n * Make a path relative to a URL or another path.\n *\n * @param aRoot The root path or URL.\n * @param aPath The path or URL to be made relative to aRoot.\n */\n function relative(aRoot, aPath) {\n if (aRoot === \"\") {\n aRoot = \".\";\n }\n\n aRoot = aRoot.replace(/\\/$/, '');\n\n // XXX: It is possible to remove this block, and the tests still pass!\n var url = urlParse(aRoot);\n if (aPath.charAt(0) == \"/\" && url && url.path == \"/\") {\n return aPath.slice(1);\n }\n\n return aPath.indexOf(aRoot + '/') === 0\n ? aPath.substr(aRoot.length + 1)\n : aPath;\n }\n exports.relative = relative;\n\n /**\n * Because behavior goes wacky when you set `__proto__` on objects, we\n * have to prefix all the strings in our set with an arbitrary character.\n *\n * See https://github.com/mozilla/source-map/pull/31 and\n * https://github.com/mozilla/source-map/issues/30\n *\n * @param String aStr\n */\n function toSetString(aStr) {\n return '$' + aStr;\n }\n exports.toSetString = toSetString;\n\n function fromSetString(aStr) {\n return aStr.substr(1);\n }\n exports.fromSetString = fromSetString;\n\n function strcmp(aStr1, aStr2) {\n var s1 = aStr1 || \"\";\n var s2 = aStr2 || \"\";\n return (s1 > s2) - (s1 < s2);\n }\n\n /**\n * Comparator between two mappings where the original positions are compared.\n *\n * Optionally pass in `true` as `onlyCompareGenerated` to consider two\n * mappings with the same original source/line/column, but different generated\n * line and column the same. Useful when searching for a mapping with a\n * stubbed out mapping.\n */\n function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {\n var cmp;\n\n cmp = strcmp(mappingA.source, mappingB.source);\n if (cmp) {\n return cmp;\n }\n\n cmp = mappingA.originalLine - mappingB.originalLine;\n if (cmp) {\n return cmp;\n }\n\n cmp = mappingA.originalColumn - mappingB.originalColumn;\n if (cmp || onlyCompareOriginal) {\n return cmp;\n }\n\n cmp = mappingA.generatedColumn - mappingB.generatedColumn;\n if (cmp) {\n return cmp;\n }\n\n cmp = mappingA.generatedLine - mappingB.generatedLine;\n if (cmp) {\n return cmp;\n }\n\n return strcmp(mappingA.name, mappingB.name);\n };\n exports.compareByOriginalPositions = compareByOriginalPositions;\n\n /**\n * Comparator between two mappings where the generated positions are\n * compared.\n *\n * Optionally pass in `true` as `onlyCompareGenerated` to consider two\n * mappings with the same generated line and column, but different\n * source/name/original line and column the same. Useful when searching for a\n * mapping with a stubbed out mapping.\n */\n function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) {\n var cmp;\n\n cmp = mappingA.generatedLine - mappingB.generatedLine;\n if (cmp) {\n return cmp;\n }\n\n cmp = mappingA.generatedColumn - mappingB.generatedColumn;\n if (cmp || onlyCompareGenerated) {\n return cmp;\n }\n\n cmp = strcmp(mappingA.source, mappingB.source);\n if (cmp) {\n return cmp;\n }\n\n cmp = mappingA.originalLine - mappingB.originalLine;\n if (cmp) {\n return cmp;\n }\n\n cmp = mappingA.originalColumn - mappingB.originalColumn;\n if (cmp) {\n return cmp;\n }\n\n return strcmp(mappingA.name, mappingB.name);\n };\n exports.compareByGeneratedPositions = compareByGeneratedPositions;\n\n});\n/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\ndefine2('source-map/array-set', ['require', 'exports', 'module' , 'source-map/util'], function(require, exports, module) {\n\n var util = require('./util');\n\n /**\n * A data structure which is a combination of an array and a set. Adding a new\n * member is O(1), testing for membership is O(1), and finding the index of an\n * element is O(1). Removing elements from the set is not supported. Only\n * strings are supported for membership.\n */\n function ArraySet() {\n this._array = [];\n this._set = {};\n }\n\n /**\n * Static method for creating ArraySet instances from an existing array.\n */\n ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {\n var set = new ArraySet();\n for (var i = 0, len = aArray.length; i < len; i++) {\n set.add(aArray[i], aAllowDuplicates);\n }\n return set;\n };\n\n /**\n * Add the given string to this set.\n *\n * @param String aStr\n */\n ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {\n var isDuplicate = this.has(aStr);\n var idx = this._array.length;\n if (!isDuplicate || aAllowDuplicates) {\n this._array.push(aStr);\n }\n if (!isDuplicate) {\n this._set[util.toSetString(aStr)] = idx;\n }\n };\n\n /**\n * Is the given string a member of this set?\n *\n * @param String aStr\n */\n ArraySet.prototype.has = function ArraySet_has(aStr) {\n return Object.prototype.hasOwnProperty.call(this._set,\n util.toSetString(aStr));\n };\n\n /**\n * What is the index of the given string in the array?\n *\n * @param String aStr\n */\n ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {\n if (this.has(aStr)) {\n return this._set[util.toSetString(aStr)];\n }\n throw new Error('\"' + aStr + '\" is not in the set.');\n };\n\n /**\n * What is the element at the given index?\n *\n * @param Number aIdx\n */\n ArraySet.prototype.at = function ArraySet_at(aIdx) {\n if (aIdx >= 0 && aIdx < this._array.length) {\n return this._array[aIdx];\n }\n throw new Error('No element indexed by ' + aIdx);\n };\n\n /**\n * Returns the array representation of this set (which has the proper indices\n * indicated by indexOf). Note that this is a copy of the internal array used\n * for storing the members so that no one can mess with internal state.\n */\n ArraySet.prototype.toArray = function ArraySet_toArray() {\n return this._array.slice();\n };\n\n exports.ArraySet = ArraySet;\n\n});\n/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2014 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\ndefine2('source-map/mapping-list', ['require', 'exports', 'module' , 'source-map/util'], function(require, exports, module) {\n\n var util = require('./util');\n\n /**\n * Determine whether mappingB is after mappingA with respect to generated\n * position.\n */\n function generatedPositionAfter(mappingA, mappingB) {\n // Optimized for most common case\n var lineA = mappingA.generatedLine;\n var lineB = mappingB.generatedLine;\n var columnA = mappingA.generatedColumn;\n var columnB = mappingB.generatedColumn;\n return lineB > lineA || lineB == lineA && columnB >= columnA ||\n util.compareByGeneratedPositions(mappingA, mappingB) <= 0;\n }\n\n /**\n * A data structure to provide a sorted view of accumulated mappings in a\n * performance conscious manner. It trades a neglibable overhead in general\n * case for a large speedup in case of mappings being added in order.\n */\n function MappingList() {\n this._array = [];\n this._sorted = true;\n // Serves as infimum\n this._last = {generatedLine: -1, generatedColumn: 0};\n }\n\n /**\n * Iterate through internal items. This method takes the same arguments that\n * `Array.prototype.forEach` takes.\n *\n * NOTE: The order of the mappings is NOT guaranteed.\n */\n MappingList.prototype.unsortedForEach =\n function MappingList_forEach(aCallback, aThisArg) {\n this._array.forEach(aCallback, aThisArg);\n };\n\n /**\n * Add the given source mapping.\n *\n * @param Object aMapping\n */\n MappingList.prototype.add = function MappingList_add(aMapping) {\n var mapping;\n if (generatedPositionAfter(this._last, aMapping)) {\n this._last = aMapping;\n this._array.push(aMapping);\n } else {\n this._sorted = false;\n this._array.push(aMapping);\n }\n };\n\n /**\n * Returns the flat, sorted array of mappings. The mappings are sorted by\n * generated position.\n *\n * WARNING: This method returns internal data without copying, for\n * performance. The return value must NOT be mutated, and should be treated as\n * an immutable borrow. If you want to take ownership, you must make your own\n * copy.\n */\n MappingList.prototype.toArray = function MappingList_toArray() {\n if (!this._sorted) {\n this._array.sort(util.compareByGeneratedPositions);\n this._sorted = true;\n }\n return this._array;\n };\n\n exports.MappingList = MappingList;\n\n});\n/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\ndefine2('source-map/source-map-consumer', ['require', 'exports', 'module' , 'source-map/util', 'source-map/binary-search', 'source-map/array-set', 'source-map/base64-vlq'], function(require, exports, module) {\n\n var util = require('./util');\n var binarySearch = require('./binary-search');\n var ArraySet = require('./array-set').ArraySet;\n var base64VLQ = require('./base64-vlq');\n\n function SourceMapConsumer(aSourceMap) {\n var sourceMap = aSourceMap;\n if (typeof aSourceMap === 'string') {\n sourceMap = JSON.parse(aSourceMap.replace(/^\\)\\]\\}'/, ''));\n }\n\n return sourceMap.sections != null\n ? new IndexedSourceMapConsumer(sourceMap)\n : new BasicSourceMapConsumer(sourceMap);\n }\n\n SourceMapConsumer.fromSourceMap = function(aSourceMap) {\n return BasicSourceMapConsumer.fromSourceMap(aSourceMap);\n }\n\n /**\n * The version of the source mapping spec that we are consuming.\n */\n SourceMapConsumer.prototype._version = 3;\n\n // `__generatedMappings` and `__originalMappings` are arrays that hold the\n // parsed mapping coordinates from the source map's \"mappings\" attribute. They\n // are lazily instantiated, accessed via the `_generatedMappings` and\n // `_originalMappings` getters respectively, and we only parse the mappings\n // and create these arrays once queried for a source location. We jump through\n // these hoops because there can be many thousands of mappings, and parsing\n // them is expensive, so we only want to do it if we must.\n //\n // Each object in the arrays is of the form:\n //\n // {\n // generatedLine: The line number in the generated code,\n // generatedColumn: The column number in the generated code,\n // source: The path to the original source file that generated this\n // chunk of code,\n // originalLine: The line number in the original source that\n // corresponds to this chunk of generated code,\n // originalColumn: The column number in the original source that\n // corresponds to this chunk of generated code,\n // name: The name of the original symbol which generated this chunk of\n // code.\n // }\n //\n // All properties except for `generatedLine` and `generatedColumn` can be\n // `null`.\n //\n // `_generatedMappings` is ordered by the generated positions.\n //\n // `_originalMappings` is ordered by the original positions.\n\n SourceMapConsumer.prototype.__generatedMappings = null;\n Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', {\n get: function () {\n if (!this.__generatedMappings) {\n this.__generatedMappings = [];\n this.__originalMappings = [];\n this._parseMappings(this._mappings, this.sourceRoot);\n }\n\n return this.__generatedMappings;\n }\n });\n\n SourceMapConsumer.prototype.__originalMappings = null;\n Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', {\n get: function () {\n if (!this.__originalMappings) {\n this.__generatedMappings = [];\n this.__originalMappings = [];\n this._parseMappings(this._mappings, this.sourceRoot);\n }\n\n return this.__originalMappings;\n }\n });\n\n SourceMapConsumer.prototype._nextCharIsMappingSeparator =\n function SourceMapConsumer_nextCharIsMappingSeparator(aStr, index) {\n var c = aStr.charAt(index);\n return c === \";\" || c === \",\";\n };\n\n /**\n * Parse the mappings in a string in to a data structure which we can easily\n * query (the ordered arrays in the `this.__generatedMappings` and\n * `this.__originalMappings` properties).\n */\n SourceMapConsumer.prototype._parseMappings =\n function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {\n throw new Error(\"Subclasses must implement _parseMappings\");\n };\n\n SourceMapConsumer.GENERATED_ORDER = 1;\n SourceMapConsumer.ORIGINAL_ORDER = 2;\n\n SourceMapConsumer.GREATEST_LOWER_BOUND = 1;\n SourceMapConsumer.LEAST_UPPER_BOUND = 2;\n\n /**\n * Iterate over each mapping between an original source/line/column and a\n * generated line/column in this source map.\n *\n * @param Function aCallback\n * The function that is called with each mapping.\n * @param Object aContext\n * Optional. If specified, this object will be the value of `this` every\n * time that `aCallback` is called.\n * @param aOrder\n * Either `SourceMapConsumer.GENERATED_ORDER` or\n * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to\n * iterate over the mappings sorted by the generated file's line/column\n * order or the original's source/line/column order, respectively. Defaults to\n * `SourceMapConsumer.GENERATED_ORDER`.\n */\n SourceMapConsumer.prototype.eachMapping =\n function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {\n var context = aContext || null;\n var order = aOrder || SourceMapConsumer.GENERATED_ORDER;\n\n var mappings;\n switch (order) {\n case SourceMapConsumer.GENERATED_ORDER:\n mappings = this._generatedMappings;\n break;\n case SourceMapConsumer.ORIGINAL_ORDER:\n mappings = this._originalMappings;\n break;\n default:\n throw new Error(\"Unknown order of iteration.\");\n }\n\n var sourceRoot = this.sourceRoot;\n mappings.map(function (mapping) {\n var source = mapping.source;\n if (source != null && sourceRoot != null) {\n source = util.join(sourceRoot, source);\n }\n return {\n source: source,\n generatedLine: mapping.generatedLine,\n generatedColumn: mapping.generatedColumn,\n originalLine: mapping.originalLine,\n originalColumn: mapping.originalColumn,\n name: mapping.name\n };\n }).forEach(aCallback, context);\n };\n\n /**\n * Returns all generated line and column information for the original source,\n * line, and column provided. If no column is provided, returns all mappings\n * corresponding to a single line. Otherwise, returns all mappings\n * corresponding to a single line and column.\n *\n * The only argument is an object with the following properties:\n *\n * - source: The filename of the original source.\n * - line: The line number in the original source.\n * - column: Optional. the column number in the original source.\n *\n * and an array of objects is returned, each with the following properties:\n *\n * - line: The line number in the generated source, or null.\n * - column: The column number in the generated source, or null.\n */\n SourceMapConsumer.prototype.allGeneratedPositionsFor =\n function SourceMapConsumer_allGeneratedPositionsFor(aArgs) {\n // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping\n // returns the index of the closest mapping less than the needle. By\n // setting needle.originalColumn to 0, we thus find the last mapping for\n // the given line, provided such a mapping exists.\n var needle = {\n source: util.getArg(aArgs, 'source'),\n originalLine: util.getArg(aArgs, 'line'),\n originalColumn: util.getArg(aArgs, 'column', 0)\n };\n\n if (this.sourceRoot != null) {\n needle.source = util.relative(this.sourceRoot, needle.source);\n }\n\n var mappings = [];\n\n var index = this._findMapping(needle,\n this._originalMappings,\n \"originalLine\",\n \"originalColumn\",\n util.compareByOriginalPositions,\n binarySearch.LEAST_UPPER_BOUND);\n if (index >= 0) {\n var mapping = this._originalMappings[index];\n var originalLine = mapping.originalLine;\n var originalColumn = mapping.originalColumn;\n\n // Iterate until either we run out of mappings, or we run into\n // a mapping for a different line. Since mappings are sorted, this is\n // guaranteed to find all mappings for the line we are searching for.\n while (mapping && mapping.originalLine === originalLine &&\n (aArgs.column === undefined ||\n mapping.originalColumn === originalColumn)) {\n mappings.push({\n line: util.getArg(mapping, 'generatedLine', null),\n column: util.getArg(mapping, 'generatedColumn', null),\n lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)\n });\n\n mapping = this._originalMappings[++index];\n }\n }\n\n return mappings;\n };\n\n exports.SourceMapConsumer = SourceMapConsumer;\n\n /**\n * A BasicSourceMapConsumer instance represents a parsed source map which we can\n * query for information about the original file positions by giving it a file\n * position in the generated source.\n *\n * The only parameter is the raw source map (either as a JSON string, or\n * already parsed to an object). According to the spec, source maps have the\n * following attributes:\n *\n * - version: Which version of the source map spec this map is following.\n * - sources: An array of URLs to the original source files.\n * - names: An array of identifiers which can be referrenced by individual mappings.\n * - sourceRoot: Optional. The URL root from which all sources are relative.\n * - sourcesContent: Optional. An array of contents of the original source files.\n * - mappings: A string of base64 VLQs which contain the actual mappings.\n * - file: Optional. The generated file this source map is associated with.\n *\n * Here is an example source map, taken from the source map spec[0]:\n *\n * {\n * version : 3,\n * file: \"out.js\",\n * sourceRoot : \"\",\n * sources: [\"foo.js\", \"bar.js\"],\n * names: [\"src\", \"maps\", \"are\", \"fun\"],\n * mappings: \"AA,AB;;ABCDE;\"\n * }\n *\n * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1#\n */\n function BasicSourceMapConsumer(aSourceMap) {\n var sourceMap = aSourceMap;\n if (typeof aSourceMap === 'string') {\n sourceMap = JSON.parse(aSourceMap.replace(/^\\)\\]\\}'/, ''));\n }\n\n var version = util.getArg(sourceMap, 'version');\n var sources = util.getArg(sourceMap, 'sources');\n // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which\n // requires the array) to play nice here.\n var names = util.getArg(sourceMap, 'names', []);\n var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);\n var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);\n var mappings = util.getArg(sourceMap, 'mappings');\n var file = util.getArg(sourceMap, 'file', null);\n\n // Once again, Sass deviates from the spec and supplies the version as a\n // string rather than a number, so we use loose equality checking here.\n if (version != this._version) {\n throw new Error('Unsupported version: ' + version);\n }\n\n // Some source maps produce relative source paths like \"./foo.js\" instead of\n // \"foo.js\". Normalize these first so that future comparisons will succeed.\n // See bugzil.la/1090768.\n sources = sources.map(util.normalize);\n\n // Pass `true` below to allow duplicate names and sources. While source maps\n // are intended to be compressed and deduplicated, the TypeScript compiler\n // sometimes generates source maps with duplicates in them. See Github issue\n // #72 and bugzil.la/889492.\n this._names = ArraySet.fromArray(names, true);\n this._sources = ArraySet.fromArray(sources, true);\n\n this.sourceRoot = sourceRoot;\n this.sourcesContent = sourcesContent;\n this._mappings = mappings;\n this.file = file;\n }\n\n BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);\n BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer;\n\n /**\n * Create a BasicSourceMapConsumer from a SourceMapGenerator.\n *\n * @param SourceMapGenerator aSourceMap\n * The source map that will be consumed.\n * @returns BasicSourceMapConsumer\n */\n BasicSourceMapConsumer.fromSourceMap =\n function SourceMapConsumer_fromSourceMap(aSourceMap) {\n var smc = Object.create(BasicSourceMapConsumer.prototype);\n\n smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);\n smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);\n smc.sourceRoot = aSourceMap._sourceRoot;\n smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(),\n smc.sourceRoot);\n smc.file = aSourceMap._file;\n\n smc.__generatedMappings = aSourceMap._mappings.toArray().slice();\n smc.__originalMappings = aSourceMap._mappings.toArray().slice()\n .sort(util.compareByOriginalPositions);\n\n return smc;\n };\n\n /**\n * The version of the source mapping spec that we are consuming.\n */\n BasicSourceMapConsumer.prototype._version = 3;\n\n /**\n * The list of original sources.\n */\n Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', {\n get: function () {\n return this._sources.toArray().map(function (s) {\n return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s;\n }, this);\n }\n });\n\n /**\n * Parse the mappings in a string in to a data structure which we can easily\n * query (the ordered arrays in the `this.__generatedMappings` and\n * `this.__originalMappings` properties).\n */\n BasicSourceMapConsumer.prototype._parseMappings =\n function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {\n var generatedLine = 1;\n var previousGeneratedColumn = 0;\n var previousOriginalLine = 0;\n var previousOriginalColumn = 0;\n var previousSource = 0;\n var previousName = 0;\n var length = aStr.length;\n var index = 0;\n var cachedValues = {};\n var temp = {};\n var mapping, str, values, end, value;\n\n while (index < length) {\n if (aStr.charAt(index) === ';') {\n generatedLine++;\n ++index;\n previousGeneratedColumn = 0;\n }\n else if (aStr.charAt(index) === ',') {\n ++index;\n }\n else {\n mapping = {};\n mapping.generatedLine = generatedLine;\n\n // Because each offset is encoded relative to the previous one,\n // many segments often have the same encoding. We can exploit this\n // fact by caching the parsed variable length fields of each segment,\n // allowing us to avoid a second parse if we encounter the same\n // segment again.\n for (end = index; end < length; ++end) {\n if (this._nextCharIsMappingSeparator(aStr, end)) {\n break;\n }\n }\n str = aStr.slice(index, end);\n\n values = cachedValues[str];\n if (values) {\n index += str.length;\n } else {\n values = [];\n while (index < end) {\n base64VLQ.decode(aStr, index, temp);\n value = temp.value;\n index = temp.rest;\n values.push(value);\n }\n cachedValues[str] = values;\n }\n\n // Generated column.\n mapping.generatedColumn = previousGeneratedColumn + values[0];\n previousGeneratedColumn = mapping.generatedColumn;\n\n if (values.length > 1) {\n // Original source.\n mapping.source = this._sources.at(previousSource + values[1]);\n previousSource += values[1];\n if (values.length === 2) {\n throw new Error('Found a source, but no line and column');\n }\n\n // Original line.\n mapping.originalLine = previousOriginalLine + values[2];\n previousOriginalLine = mapping.originalLine;\n // Lines are stored 0-based\n mapping.originalLine += 1;\n if (values.length === 3) {\n throw new Error('Found a source and line, but no column');\n }\n\n // Original column.\n mapping.originalColumn = previousOriginalColumn + values[3];\n previousOriginalColumn = mapping.originalColumn;\n\n if (values.length > 4) {\n // Original name.\n mapping.name = this._names.at(previousName + values[4]);\n previousName += values[4];\n }\n }\n\n this.__generatedMappings.push(mapping);\n if (typeof mapping.originalLine === 'number') {\n this.__originalMappings.push(mapping);\n }\n }\n }\n\n this.__generatedMappings.sort(util.compareByGeneratedPositions);\n this.__originalMappings.sort(util.compareByOriginalPositions);\n };\n\n /**\n * Find the mapping that best matches the hypothetical \"needle\" mapping that\n * we are searching for in the given \"haystack\" of mappings.\n */\n BasicSourceMapConsumer.prototype._findMapping =\n function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName,\n aColumnName, aComparator, aBias) {\n // To return the position we are searching for, we must first find the\n // mapping for the given position and then return the opposite position it\n // points to. Because the mappings are sorted, we can use binary search to\n // find the best mapping.\n\n if (aNeedle[aLineName] <= 0) {\n throw new TypeError('Line must be greater than or equal to 1, got '\n + aNeedle[aLineName]);\n }\n if (aNeedle[aColumnName] < 0) {\n throw new TypeError('Column must be greater than or equal to 0, got '\n + aNeedle[aColumnName]);\n }\n\n return binarySearch.search(aNeedle, aMappings, aComparator, aBias);\n };\n\n /**\n * Compute the last column for each generated mapping. The last column is\n * inclusive.\n */\n BasicSourceMapConsumer.prototype.computeColumnSpans =\n function SourceMapConsumer_computeColumnSpans() {\n for (var index = 0; index < this._generatedMappings.length; ++index) {\n var mapping = this._generatedMappings[index];\n\n // Mappings do not contain a field for the last generated columnt. We\n // can come up with an optimistic estimate, however, by assuming that\n // mappings are contiguous (i.e. given two consecutive mappings, the\n // first mapping ends where the second one starts).\n if (index + 1 < this._generatedMappings.length) {\n var nextMapping = this._generatedMappings[index + 1];\n\n if (mapping.generatedLine === nextMapping.generatedLine) {\n mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1;\n continue;\n }\n }\n\n // The last mapping for each line spans the entire line.\n mapping.lastGeneratedColumn = Infinity;\n }\n };\n\n /**\n * Returns the original source, line, and column information for the generated\n * source's line and column positions provided. The only argument is an object\n * with the following properties:\n *\n * - line: The line number in the generated source.\n * - column: The column number in the generated source.\n * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or\n * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the\n * closest element that is smaller than or greater than the one we are\n * searching for, respectively, if the exact element cannot be found.\n * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.\n *\n * and an object is returned with the following properties:\n *\n * - source: The original source file, or null.\n * - line: The line number in the original source, or null.\n * - column: The column number in the original source, or null.\n * - name: The original identifier, or null.\n */\n BasicSourceMapConsumer.prototype.originalPositionFor =\n function SourceMapConsumer_originalPositionFor(aArgs) {\n var needle = {\n generatedLine: util.getArg(aArgs, 'line'),\n generatedColumn: util.getArg(aArgs, 'column')\n };\n\n var index = this._findMapping(\n needle,\n this._generatedMappings,\n \"generatedLine\",\n \"generatedColumn\",\n util.compareByGeneratedPositions,\n util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND)\n );\n\n if (index >= 0) {\n var mapping = this._generatedMappings[index];\n\n if (mapping.generatedLine === needle.generatedLine) {\n var source = util.getArg(mapping, 'source', null);\n if (source != null && this.sourceRoot != null) {\n source = util.join(this.sourceRoot, source);\n }\n return {\n source: source,\n line: util.getArg(mapping, 'originalLine', null),\n column: util.getArg(mapping, 'originalColumn', null),\n name: util.getArg(mapping, 'name', null)\n };\n }\n }\n\n return {\n source: null,\n line: null,\n column: null,\n name: null\n };\n };\n\n /**\n * Returns the original source content. The only argument is the url of the\n * original source file. Returns null if no original source content is\n * availible.\n */\n BasicSourceMapConsumer.prototype.sourceContentFor =\n function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {\n if (!this.sourcesContent) {\n return null;\n }\n\n if (this.sourceRoot != null) {\n aSource = util.relative(this.sourceRoot, aSource);\n }\n\n if (this._sources.has(aSource)) {\n return this.sourcesContent[this._sources.indexOf(aSource)];\n }\n\n var url;\n if (this.sourceRoot != null\n && (url = util.urlParse(this.sourceRoot))) {\n // XXX: file:// URIs and absolute paths lead to unexpected behavior for\n // many users. We can help them out when they expect file:// URIs to\n // behave like it would if they were running a local HTTP server. See\n // https://bugzilla.mozilla.org/show_bug.cgi?id=885597.\n var fileUriAbsPath = aSource.replace(/^file:\\/\\//, \"\");\n if (url.scheme == \"file\"\n && this._sources.has(fileUriAbsPath)) {\n return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)]\n }\n\n if ((!url.path || url.path == \"/\")\n && this._sources.has(\"/\" + aSource)) {\n return this.sourcesContent[this._sources.indexOf(\"/\" + aSource)];\n }\n }\n\n // This function is used recursively from\n // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we\n // don't want to throw if we can't find the source - we just want to\n // return null, so we provide a flag to exit gracefully.\n if (nullOnMissing) {\n return null;\n }\n else {\n throw new Error('\"' + aSource + '\" is not in the SourceMap.');\n }\n };\n\n /**\n * Returns the generated line and column information for the original source,\n * line, and column positions provided. The only argument is an object with\n * the following properties:\n *\n * - source: The filename of the original source.\n * - line: The line number in the original source.\n * - column: The column number in the original source.\n * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or\n * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the\n * closest element that is smaller than or greater than the one we are\n * searching for, respectively, if the exact element cannot be found.\n * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'.\n *\n * and an object is returned with the following properties:\n *\n * - line: The line number in the generated source, or null.\n * - column: The column number in the generated source, or null.\n */\n BasicSourceMapConsumer.prototype.generatedPositionFor =\n function SourceMapConsumer_generatedPositionFor(aArgs) {\n var needle = {\n source: util.getArg(aArgs, 'source'),\n originalLine: util.getArg(aArgs, 'line'),\n originalColumn: util.getArg(aArgs, 'column')\n };\n\n if (this.sourceRoot != null) {\n needle.source = util.relative(this.sourceRoot, needle.source);\n }\n\n var index = this._findMapping(\n needle,\n this._originalMappings,\n \"originalLine\",\n \"originalColumn\",\n util.compareByOriginalPositions,\n util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND)\n );\n\n if (index >= 0) {\n var mapping = this._originalMappings[index];\n\n if (mapping.source === needle.source) {\n return {\n line: util.getArg(mapping, 'generatedLine', null),\n column: util.getArg(mapping, 'generatedColumn', null),\n lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)\n };\n }\n }\n\n return {\n line: null,\n column: null,\n lastColumn: null\n };\n };\n\n exports.BasicSourceMapConsumer = BasicSourceMapConsumer;\n\n /**\n * An IndexedSourceMapConsumer instance represents a parsed source map which\n * we can query for information. It differs from BasicSourceMapConsumer in\n * that it takes \"indexed\" source maps (i.e. ones with a \"sections\" field) as\n * input.\n *\n * The only parameter is a raw source map (either as a JSON string, or already\n * parsed to an object). According to the spec for indexed source maps, they\n * have the following attributes:\n *\n * - version: Which version of the source map spec this map is following.\n * - file: Optional. The generated file this source map is associated with.\n * - sections: A list of section definitions.\n *\n * Each value under the \"sections\" field has two fields:\n * - offset: The offset into the original specified at which this section\n * begins to apply, defined as an object with a \"line\" and \"column\"\n * field.\n * - map: A source map definition. This source map could also be indexed,\n * but doesn't have to be.\n *\n * Instead of the \"map\" field, it's also possible to have a \"url\" field\n * specifying a URL to retrieve a source map from, but that's currently\n * unsupported.\n *\n * Here's an example source map, taken from the source map spec[0], but\n * modified to omit a section which uses the \"url\" field.\n *\n * {\n * version : 3,\n * file: \"app.js\",\n * sections: [{\n * offset: {line:100, column:10},\n * map: {\n * version : 3,\n * file: \"section.js\",\n * sources: [\"foo.js\", \"bar.js\"],\n * names: [\"src\", \"maps\", \"are\", \"fun\"],\n * mappings: \"AAAA,E;;ABCDE;\"\n * }\n * }],\n * }\n *\n * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt\n */\n function IndexedSourceMapConsumer(aSourceMap) {\n var sourceMap = aSourceMap;\n if (typeof aSourceMap === 'string') {\n sourceMap = JSON.parse(aSourceMap.replace(/^\\)\\]\\}'/, ''));\n }\n\n var version = util.getArg(sourceMap, 'version');\n var sections = util.getArg(sourceMap, 'sections');\n\n if (version != this._version) {\n throw new Error('Unsupported version: ' + version);\n }\n\n var lastOffset = {\n line: -1,\n column: 0\n };\n this._sections = sections.map(function (s) {\n if (s.url) {\n // The url field will require support for asynchronicity.\n // See https://github.com/mozilla/source-map/issues/16\n throw new Error('Support for url field in sections not implemented.');\n }\n var offset = util.getArg(s, 'offset');\n var offsetLine = util.getArg(offset, 'line');\n var offsetColumn = util.getArg(offset, 'column');\n\n if (offsetLine < lastOffset.line ||\n (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) {\n throw new Error('Section offsets must be ordered and non-overlapping.');\n }\n lastOffset = offset;\n\n return {\n generatedOffset: {\n // The offset fields are 0-based, but we use 1-based indices when\n // encoding/decoding from VLQ.\n generatedLine: offsetLine + 1,\n generatedColumn: offsetColumn + 1\n },\n consumer: new SourceMapConsumer(util.getArg(s, 'map'))\n }\n });\n }\n\n IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);\n IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer;\n\n /**\n * The version of the source mapping spec that we are consuming.\n */\n IndexedSourceMapConsumer.prototype._version = 3;\n\n /**\n * The list of original sources.\n */\n Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', {\n get: function () {\n var sources = [];\n for (var i = 0; i < this._sections.length; i++) {\n for (var j = 0; j < this._sections[i].consumer.sources.length; j++) {\n sources.push(this._sections[i].consumer.sources[j]);\n }\n };\n return sources;\n }\n });\n\n /**\n * Returns the original source, line, and column information for the generated\n * source's line and column positions provided. The only argument is an object\n * with the following properties:\n *\n * - line: The line number in the generated source.\n * - column: The column number in the generated source.\n *\n * and an object is returned with the following properties:\n *\n * - source: The original source file, or null.\n * - line: The line number in the original source, or null.\n * - column: The column number in the original source, or null.\n * - name: The original identifier, or null.\n */\n IndexedSourceMapConsumer.prototype.originalPositionFor =\n function IndexedSourceMapConsumer_originalPositionFor(aArgs) {\n var needle = {\n generatedLine: util.getArg(aArgs, 'line'),\n generatedColumn: util.getArg(aArgs, 'column')\n };\n\n // Find the section containing the generated position we're trying to map\n // to an original position.\n var sectionIndex = binarySearch.search(needle, this._sections,\n function(needle, section) {\n var cmp = needle.generatedLine - section.generatedOffset.generatedLine;\n if (cmp) {\n return cmp;\n }\n\n return (needle.generatedColumn -\n section.generatedOffset.generatedColumn);\n });\n var section = this._sections[sectionIndex];\n\n if (!section) {\n return {\n source: null,\n line: null,\n column: null,\n name: null\n };\n }\n\n return section.consumer.originalPositionFor({\n line: needle.generatedLine -\n (section.generatedOffset.generatedLine - 1),\n column: needle.generatedColumn -\n (section.generatedOffset.generatedLine === needle.generatedLine\n ? section.generatedOffset.generatedColumn - 1\n : 0),\n bias: aArgs.bias\n });\n };\n\n /**\n * Returns the original source content. The only argument is the url of the\n * original source file. Returns null if no original source content is\n * available.\n */\n IndexedSourceMapConsumer.prototype.sourceContentFor =\n function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {\n for (var i = 0; i < this._sections.length; i++) {\n var section = this._sections[i];\n\n var content = section.consumer.sourceContentFor(aSource, true);\n if (content) {\n return content;\n }\n }\n if (nullOnMissing) {\n return null;\n }\n else {\n throw new Error('\"' + aSource + '\" is not in the SourceMap.');\n }\n };\n\n /**\n * Returns the generated line and column information for the original source,\n * line, and column positions provided. The only argument is an object with\n * the following properties:\n *\n * - source: The filename of the original source.\n * - line: The line number in the original source.\n * - column: The column number in the original source.\n *\n * and an object is returned with the following properties:\n *\n * - line: The line number in the generated source, or null.\n * - column: The column number in the generated source, or null.\n */\n IndexedSourceMapConsumer.prototype.generatedPositionFor =\n function IndexedSourceMapConsumer_generatedPositionFor(aArgs) {\n for (var i = 0; i < this._sections.length; i++) {\n var section = this._sections[i];\n\n // Only consider this section if the requested source is in the list of\n // sources of the consumer.\n if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) {\n continue;\n }\n var generatedPosition = section.consumer.generatedPositionFor(aArgs);\n if (generatedPosition) {\n var ret = {\n line: generatedPosition.line +\n (section.generatedOffset.generatedLine - 1),\n column: generatedPosition.column +\n (section.generatedOffset.generatedLine === generatedPosition.line\n ? section.generatedOffset.generatedColumn - 1\n : 0)\n };\n return ret;\n }\n }\n\n return {\n line: null,\n column: null\n };\n };\n\n /**\n * Parse the mappings in a string in to a data structure which we can easily\n * query (the ordered arrays in the `this.__generatedMappings` and\n * `this.__originalMappings` properties).\n */\n IndexedSourceMapConsumer.prototype._parseMappings =\n function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) {\n this.__generatedMappings = [];\n this.__originalMappings = [];\n for (var i = 0; i < this._sections.length; i++) {\n var section = this._sections[i];\n var sectionMappings = section.consumer._generatedMappings;\n for (var j = 0; j < sectionMappings.length; j++) {\n var mapping = sectionMappings[i];\n\n var source = mapping.source;\n var sourceRoot = section.consumer.sourceRoot;\n\n if (source != null && sourceRoot != null) {\n source = util.join(sourceRoot, source);\n }\n\n // The mappings coming from the consumer for the section have\n // generated positions relative to the start of the section, so we\n // need to offset them to be relative to the start of the concatenated\n // generated file.\n var adjustedMapping = {\n source: source,\n generatedLine: mapping.generatedLine +\n (section.generatedOffset.generatedLine - 1),\n generatedColumn: mapping.column +\n (section.generatedOffset.generatedLine === mapping.generatedLine)\n ? section.generatedOffset.generatedColumn - 1\n : 0,\n originalLine: mapping.originalLine,\n originalColumn: mapping.originalColumn,\n name: mapping.name\n };\n\n this.__generatedMappings.push(adjustedMapping);\n if (typeof adjustedMapping.originalLine === 'number') {\n this.__originalMappings.push(adjustedMapping);\n }\n };\n };\n\n this.__generatedMappings.sort(util.compareByGeneratedPositions);\n this.__originalMappings.sort(util.compareByOriginalPositions);\n };\n\n exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer;\n\n});\n/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\ndefine2('source-map/binary-search', ['require', 'exports', 'module' , ], function(require, exports, module) {\n\n exports.GREATEST_LOWER_BOUND = 1;\n exports.LEAST_UPPER_BOUND = 2;\n\n /**\n * Recursive implementation of binary search.\n *\n * @param aLow Indices here and lower do not contain the needle.\n * @param aHigh Indices here and higher do not contain the needle.\n * @param aNeedle The element being searched for.\n * @param aHaystack The non-empty array being searched.\n * @param aCompare Function which takes two elements and returns -1, 0, or 1.\n * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or\n * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the\n * closest element that is smaller than or greater than the one we are\n * searching for, respectively, if the exact element cannot be found.\n */\n function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) {\n // This function terminates when one of the following is true:\n //\n // 1. We find the exact element we are looking for.\n //\n // 2. We did not find the exact element, but we can return the index of\n // the next-closest element.\n //\n // 3. We did not find the exact element, and there is no next-closest\n // element than the one we are searching for, so we return -1.\n var mid = Math.floor((aHigh - aLow) / 2) + aLow;\n var cmp = aCompare(aNeedle, aHaystack[mid], true);\n if (cmp === 0) {\n // Found the element we are looking for.\n return mid;\n }\n else if (cmp > 0) {\n // Our needle is greater than aHaystack[mid].\n if (aHigh - mid > 1) {\n // The element is in the upper half.\n return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias);\n }\n\n // The exact needle element was not found in this haystack. Determine if\n // we are in termination case (3) or (2) and return the appropriate thing.\n if (aBias == exports.LEAST_UPPER_BOUND) {\n return aHigh < aHaystack.length ? aHigh : -1;\n } else {\n return mid;\n }\n }\n else {\n // Our needle is less than aHaystack[mid].\n if (mid - aLow > 1) {\n // The element is in the lower half.\n return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias);\n }\n\n // we are in termination case (3) or (2) and return the appropriate thing.\n if (aBias == exports.LEAST_UPPER_BOUND) {\n return mid;\n } else {\n return aLow < 0 ? -1 : aLow;\n }\n }\n }\n\n /**\n * This is an implementation of binary search which will always try and return\n * the index of the closest element if there is no exact hit. This is because\n * mappings between original and generated line/col pairs are single points,\n * and there is an implicit region between each of them, so a miss just means\n * that you aren't on the very start of a region.\n *\n * @param aNeedle The element you are looking for.\n * @param aHaystack The array that is being searched.\n * @param aCompare A function which takes the needle and an element in the\n * array and returns -1, 0, or 1 depending on whether the needle is less\n * than, equal to, or greater than the element, respectively.\n * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or\n * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the\n * closest element that is smaller than or greater than the one we are\n * searching for, respectively, if the exact element cannot be found.\n * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'.\n */\n exports.search = function search(aNeedle, aHaystack, aCompare, aBias) {\n if (aHaystack.length === 0) {\n return -1;\n }\n\n var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack,\n aCompare, aBias || exports.GREATEST_LOWER_BOUND);\n if (index < 0) {\n return -1;\n }\n\n // We have found either the exact element, or the next-closest element than\n // the one we are searching for. However, there may be more than one such\n // element. Make sure we always return the smallest of these.\n while (index - 1 >= 0) {\n if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) {\n break;\n }\n --index;\n }\n\n return index;\n };\n\n});\n/* -*- Mode: js; js-indent-level: 2; -*- */\n/*\n * Copyright 2011 Mozilla Foundation and contributors\n * Licensed under the New BSD license. See LICENSE or:\n * http://opensource.org/licenses/BSD-3-Clause\n */\ndefine2('source-map/source-node', ['require', 'exports', 'module' , 'source-map/source-map-generator', 'source-map/util'], function(require, exports, module) {\n\n var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator;\n var util = require('./util');\n\n // Matches a Windows-style `\\r\\n` newline or a `\\n` newline used by all other\n // operating systems these days (capturing the result).\n var REGEX_NEWLINE = /(\\r?\\n)/;\n\n // Newline character code for charCodeAt() comparisons\n var NEWLINE_CODE = 10;\n\n // Private symbol for identifying `SourceNode`s when multiple versions of\n // the source-map library are loaded. This MUST NOT CHANGE across\n // versions!\n var isSourceNode = \"$$$isSourceNode$$$\";\n\n /**\n * SourceNodes provide a way to abstract over interpolating/concatenating\n * snippets of generated JavaScript source code while maintaining the line and\n * column information associated with the original source code.\n *\n * @param aLine The original line number.\n * @param aColumn The original column number.\n * @param aSource The original source's filename.\n * @param aChunks Optional. An array of strings which are snippets of\n * generated JS, or other SourceNodes.\n * @param aName The original identifier.\n */\n function SourceNode(aLine, aColumn, aSource, aChunks, aName) {\n this.children = [];\n this.sourceContents = {};\n this.line = aLine == null ? null : aLine;\n this.column = aColumn == null ? null : aColumn;\n this.source = aSource == null ? null : aSource;\n this.name = aName == null ? null : aName;\n this[isSourceNode] = true;\n if (aChunks != null) this.add(aChunks);\n }\n\n /**\n * Creates a SourceNode from generated code and a SourceMapConsumer.\n *\n * @param aGeneratedCode The generated code\n * @param aSourceMapConsumer The SourceMap for the generated code\n * @param aRelativePath Optional. The path that relative sources in the\n * SourceMapConsumer should be relative to.\n */\n SourceNode.fromStringWithSourceMap =\n function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) {\n // The SourceNode we want to fill with the generated code\n // and the SourceMap\n var node = new SourceNode();\n\n // All even indices of this array are one line of the generated code,\n // while all odd indices are the newlines between two adjacent lines\n // (since `REGEX_NEWLINE` captures its match).\n // Processed fragments are removed from this array, by calling `shiftNextLine`.\n var remainingLines = aGeneratedCode.split(REGEX_NEWLINE);\n var shiftNextLine = function() {\n var lineContents = remainingLines.shift();\n // The last line of a file might not have a newline.\n var newLine = remainingLines.shift() || \"\";\n return lineContents + newLine;\n };\n\n // We need to remember the position of \"remainingLines\"\n var lastGeneratedLine = 1, lastGeneratedColumn = 0;\n\n // The generate SourceNodes we need a code range.\n // To extract it current and last mapping is used.\n // Here we store the last mapping.\n var lastMapping = null;\n\n aSourceMapConsumer.eachMapping(function (mapping) {\n if (lastMapping !== null) {\n // We add the code from \"lastMapping\" to \"mapping\":\n // First check if there is a new line in between.\n if (lastGeneratedLine < mapping.generatedLine) {\n var code = \"\";\n // Associate first line with \"lastMapping\"\n addMappingWithCode(lastMapping, shiftNextLine());\n lastGeneratedLine++;\n lastGeneratedColumn = 0;\n // The remaining code is added without mapping\n } else {\n // There is no new line in between.\n // Associate the code between \"lastGeneratedColumn\" and\n // \"mapping.generatedColumn\" with \"lastMapping\"\n var nextLine = remainingLines[0];\n var code = nextLine.substr(0, mapping.generatedColumn -\n lastGeneratedColumn);\n remainingLines[0] = nextLine.substr(mapping.generatedColumn -\n lastGeneratedColumn);\n lastGeneratedColumn = mapping.generatedColumn;\n addMappingWithCode(lastMapping, code);\n // No more remaining code, continue\n lastMapping = mapping;\n return;\n }\n }\n // We add the generated code until the first mapping\n // to the SourceNode without any mapping.\n // Each line is added as separate string.\n while (lastGeneratedLine < mapping.generatedLine) {\n node.add(shiftNextLine());\n lastGeneratedLine++;\n }\n if (lastGeneratedColumn < mapping.generatedColumn) {\n var nextLine = remainingLines[0];\n node.add(nextLine.substr(0, mapping.generatedColumn));\n remainingLines[0] = nextLine.substr(mapping.generatedColumn);\n lastGeneratedColumn = mapping.generatedColumn;\n }\n lastMapping = mapping;\n }, this);\n // We have processed all mappings.\n if (remainingLines.length > 0) {\n if (lastMapping) {\n // Associate the remaining code in the current line with \"lastMapping\"\n addMappingWithCode(lastMapping, shiftNextLine());\n }\n // and add the remaining lines without any mapping\n node.add(remainingLines.join(\"\"));\n }\n\n // Copy sourcesContent into SourceNode\n aSourceMapConsumer.sources.forEach(function (sourceFile) {\n var content = aSourceMapConsumer.sourceContentFor(sourceFile);\n if (content != null) {\n if (aRelativePath != null) {\n sourceFile = util.join(aRelativePath, sourceFile);\n }\n node.setSourceContent(sourceFile, content);\n }\n });\n\n return node;\n\n function addMappingWithCode(mapping, code) {\n if (mapping === null || mapping.source === undefined) {\n node.add(code);\n } else {\n var source = aRelativePath\n ? util.join(aRelativePath, mapping.source)\n : mapping.source;\n node.add(new SourceNode(mapping.originalLine,\n mapping.originalColumn,\n source,\n code,\n mapping.name));\n }\n }\n };\n\n /**\n * Add a chunk of generated JS to this source node.\n *\n * @param aChunk A string snippet of generated JS code, another instance of\n * SourceNode, or an array where each member is one of those things.\n */\n SourceNode.prototype.add = function SourceNode_add(aChunk) {\n if (Array.isArray(aChunk)) {\n aChunk.forEach(function (chunk) {\n this.add(chunk);\n }, this);\n }\n else if (aChunk[isSourceNode] || typeof aChunk === \"string\") {\n if (aChunk) {\n this.children.push(aChunk);\n }\n }\n else {\n throw new TypeError(\n \"Expected a SourceNode, string, or an array of SourceNodes and strings. Got \" + aChunk\n );\n }\n return this;\n };\n\n /**\n * Add a chunk of generated JS to the beginning of this source node.\n *\n * @param aChunk A string snippet of generated JS code, another instance of\n * SourceNode, or an array where each member is one of those things.\n */\n SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) {\n if (Array.isArray(aChunk)) {\n for (var i = aChunk.length-1; i >= 0; i--) {\n this.prepend(aChunk[i]);\n }\n }\n else if (aChunk[isSourceNode] || typeof aChunk === \"string\") {\n this.children.unshift(aChunk);\n }\n else {\n throw new TypeError(\n \"Expected a SourceNode, string, or an array of SourceNodes and strings. Got \" + aChunk\n );\n }\n return this;\n };\n\n /**\n * Walk over the tree of JS snippets in this node and its children. The\n * walking function is called once for each snippet of JS and is passed that\n * snippet and the its original associated source's line/column location.\n *\n * @param aFn The traversal function.\n */\n SourceNode.prototype.walk = function SourceNode_walk(aFn) {\n var chunk;\n for (var i = 0, len = this.children.length; i < len; i++) {\n chunk = this.children[i];\n if (chunk[isSourceNode]) {\n chunk.walk(aFn);\n }\n else {\n if (chunk !== '') {\n aFn(chunk, { source: this.source,\n line: this.line,\n column: this.column,\n name: this.name });\n }\n }\n }\n };\n\n /**\n * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between\n * each of `this.children`.\n *\n * @param aSep The separator.\n */\n SourceNode.prototype.join = function SourceNode_join(aSep) {\n var newChildren;\n var i;\n var len = this.children.length;\n if (len > 0) {\n newChildren = [];\n for (i = 0; i < len-1; i++) {\n newChildren.push(this.children[i]);\n newChildren.push(aSep);\n }\n newChildren.push(this.children[i]);\n this.children = newChildren;\n }\n return this;\n };\n\n /**\n * Call String.prototype.replace on the very right-most source snippet. Useful\n * for trimming whitespace from the end of a source node, etc.\n *\n * @param aPattern The pattern to replace.\n * @param aReplacement The thing to replace the pattern with.\n */\n SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {\n var lastChild = this.children[this.children.length - 1];\n if (lastChild[isSourceNode]) {\n lastChild.replaceRight(aPattern, aReplacement);\n }\n else if (typeof lastChild === 'string') {\n this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);\n }\n else {\n this.children.push(''.replace(aPattern, aReplacement));\n }\n return this;\n };\n\n /**\n * Set the source content for a source file. This will be added to the SourceMapGenerator\n * in the sourcesContent field.\n *\n * @param aSourceFile The filename of the source file\n * @param aSourceContent The content of the source file\n */\n SourceNode.prototype.setSourceContent =\n function SourceNode_setSourceContent(aSourceFile, aSourceContent) {\n this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;\n };\n\n /**\n * Walk over the tree of SourceNodes. The walking function is called for each\n * source file content and is passed the filename and source content.\n *\n * @param aFn The traversal function.\n */\n SourceNode.prototype.walkSourceContents =\n function SourceNode_walkSourceContents(aFn) {\n for (var i = 0, len = this.children.length; i < len; i++) {\n if (this.children[i][isSourceNode]) {\n this.children[i].walkSourceContents(aFn);\n }\n }\n\n var sources = Object.keys(this.sourceContents);\n for (var i = 0, len = sources.length; i < len; i++) {\n aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]);\n }\n };\n\n /**\n * Return the string representation of this source node. Walks over the tree\n * and concatenates all the various snippets together to one string.\n */\n SourceNode.prototype.toString = function SourceNode_toString() {\n var str = \"\";\n this.walk(function (chunk) {\n str += chunk;\n });\n return str;\n };\n\n /**\n * Returns the string representation of this source node along with a source\n * map.\n */\n SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {\n var generated = {\n code: \"\",\n line: 1,\n column: 0\n };\n var map = new SourceMapGenerator(aArgs);\n var sourceMappingActive = false;\n var lastOriginalSource = null;\n var lastOriginalLine = null;\n var lastOriginalColumn = null;\n var lastOriginalName = null;\n this.walk(function (chunk, original) {\n generated.code += chunk;\n if (original.source !== null\n && original.line !== null\n && original.column !== null) {\n if(lastOriginalSource !== original.source\n || lastOriginalLine !== original.line\n || lastOriginalColumn !== original.column\n || lastOriginalName !== original.name) {\n map.addMapping({\n source: original.source,\n original: {\n line: original.line,\n column: original.column\n },\n generated: {\n line: generated.line,\n column: generated.column\n },\n name: original.name\n });\n }\n lastOriginalSource = original.source;\n lastOriginalLine = original.line;\n lastOriginalColumn = original.column;\n lastOriginalName = original.name;\n sourceMappingActive = true;\n } else if (sourceMappingActive) {\n map.addMapping({\n generated: {\n line: generated.line,\n column: generated.column\n }\n });\n lastOriginalSource = null;\n sourceMappingActive = false;\n }\n for (var idx = 0, length = chunk.length; idx < length; idx++) {\n if (chunk.charCodeAt(idx) === NEWLINE_CODE) {\n generated.line++;\n generated.column = 0;\n // Mappings end at eol\n if (idx + 1 === length) {\n lastOriginalSource = null;\n sourceMappingActive = false;\n } else if (sourceMappingActive) {\n map.addMapping({\n source: original.source,\n original: {\n line: original.line,\n column: original.column\n },\n generated: {\n line: generated.line,\n column: generated.column\n },\n name: original.name\n });\n }\n } else {\n generated.column++;\n }\n }\n });\n this.walkSourceContents(function (sourceFile, sourceContent) {\n map.setSourceContent(sourceFile, sourceContent);\n });\n\n return { code: generated.code, map: map };\n };\n\n exports.SourceNode = SourceNode;\n\n});\n/* -*- Mode: js; js-indent-level: 2; -*- */\n///////////////////////////////////////////////////////////////////////////////\n\nthis.sourceMap = {\n SourceMapConsumer: require('source-map/source-map-consumer').SourceMapConsumer,\n SourceMapGenerator: require('source-map/source-map-generator').SourceMapGenerator,\n SourceNode: require('source-map/source-node').SourceNode\n};\n\ndefine(\"source-map\", function(){});\n\n","define('modules/common/local-storage-service',['angular'], function (angular) {\n 'use strict';\n\n angular.module('bl.local-storage-service', [])\n\n .service('localStorageService', function($window) {\n\n var KEYS = {\n REGISTER: 'registerId',\n REGISTERS: 'bl_registers',\n TERMINAL: 'fullsteamTerminalId',\n TERMINAL_TYPE: 'fullsteamTerminalType',\n TERMINALS: 'bl_terminals',\n DEVICE: 'deviceToken',\n DEVICES: 'bl_devices',\n DEFAULT_REGISTER_AMOUNT: 'defaultCashAmount'\n };\n\n var service = {\n keys: KEYS,\n init: function(loginResult) {\n //console.log('Login Result', loginResult);\n },\n set: function(key, value, isObject) {\n try {\n //console.log('Set Item', key, value, isObject);\n if(isObject) {\n localStorage.setItem(key, JSON.stringify(value));\n } else {\n localStorage.setItem(key, value);\n }\n } catch (e) {\n console.log('Failed to set local storage for ' + key, e);\n }\n },\n get: function(key) {\n try {\n return localStorage.getItem(key);\n } catch (e) {\n console.log('Failed to get local storage for ' + key, e);\n }\n },\n update: function(key, property, value) {\n try {\n var data = localStorage.getItem(key);\n var obj = {};\n if(data && typeof data === \"string\") {\n obj = JSON.parse(data);\n obj[property] = value;\n } else {\n obj[property] = value;\n }\n\n localStorage.setItem(key, JSON.stringify(obj));\n } catch (e) {\n console.log('Failed to update local storage value for ' + key, e);\n }\n },\n delete: function(key, property) {\n try {\n var data = localStorage.getItem(key);\n var obj = {};\n if(data && typeof data === \"string\") {\n obj = JSON.parse(data);\n\n if(obj && obj[property]) {\n delete obj[property];\n console.log('Deleting property from key', key, property);\n }\n }\n\n localStorage.setItem(key, JSON.stringify(obj));\n } catch (e) {\n console.log('Failed to update local storage value for ' + key, e);\n }\n },\n initRegister: function(id, currentUser) {\n var result = {\n id: id,\n isSet: false\n };\n\n try {\n var data = localStorage.getItem(KEYS.REGISTERS);\n\n if(data && typeof data === \"string\" && currentUser && currentUser.retailerId) {\n var registers = JSON.parse(data);\n var register = registers[currentUser.retailerId];\n\n if(register && register.id && register.id != id) {\n id = register.id;\n result.id = id;\n service.set(KEYS.REGISTER, id, false);\n }\n\n result.isSet = !!(register && register.id);\n }\n } catch (e) {\n console.log('Failed to set bl_registers localStorage', e);\n }\n\n return result;\n },\n initTerminal: function(id, currentUser) {\n var result = {\n id: id,\n isSet: false\n };\n\n try {\n var data = localStorage.getItem(KEYS.TERMINALS);\n\n if(data && typeof data === \"string\" && currentUser && currentUser.retailerId) {\n data = JSON.parse(data);\n var terminal = data[currentUser.retailerId];\n\n if(terminal && terminal.id && terminal.id != id) {\n service.set(KEYS.TERMINAL, terminal.id, false);\n service.set(KEYS.TERMINAL_TYPE, terminal.type, false);\n result.id = terminal.id;\n }\n\n result.isSet = !!(terminal && terminal.id);\n }\n } catch (e) {\n console.log('Failed to set bl_terminals localStorage', e);\n }\n\n return result;\n }\n };\n\n return service;\n });\n});\n\n","define('modules/common/permissions-service',['angular'], function (angular) {\n 'use strict';\n\n var roles = {};\n\n angular.module('bl.permissions', []).constant('Permissions', roles);\n\n /* Permission Groups Setup */\n roles.GROUP_DASHBOARD = \"DASHBOARD\";\n roles.GROUP_CONTACT_CENTER = \"CC\";\n roles.GROUP_MARKETING_TOOLS = \"MT\";\n roles.GROUP_ACTIVITY_CENTER = \"AC\";\n roles.GROUP_APPOINTMENTS = \"APPT\";\n roles.GROUP_POS = \"POS\";\n roles.GROUP_PAYMENT_PLANS = \"PP\";\n roles.GROUP_INVENTORY = \"INV\";\n roles.GROUP_PURCHASING = \"PRCH\";\n roles.GROUP_REPORTS = \"RPT\";\n roles.GROUP_REGISTRY = \"RGST\";\n roles.GROUP_ADMINISTRATION = \"ADMN\";\n roles.GROUP_MARKETPLACE = \"MKT\";\n roles.GROUP_CLIENT_PORTAL = \"CP\";\n roles.GROUP_INTEGRATIONS = \"INT\";\n roles.GROUP_QUOTES = \"QT\";\n\n roles.groups = {};\n roles.groups[roles.GROUP_DASHBOARD] = {id:roles.GROUP_DASHBOARD, label:'common.modal.home'};\n roles.groups[roles.GROUP_CONTACT_CENTER] = {id:roles.GROUP_CONTACT_CENTER, label:'settings.header.contacts'};\n roles.groups[roles.GROUP_MARKETING_TOOLS] = {id:roles.GROUP_MARKETING_TOOLS, label:'settings.role.label.online-tools'};\n roles.groups[roles.GROUP_ACTIVITY_CENTER] = {id:roles.GROUP_ACTIVITY_CENTER, label:'settings.header.activities'};\n roles.groups[roles.GROUP_APPOINTMENTS] = {id:roles.GROUP_APPOINTMENTS, label:'contact.appointments'};\n roles.groups[roles.GROUP_POS] = {id:roles.GROUP_POS, label:'settings.header.point-of-sale'};\n roles.groups[roles.GROUP_PAYMENT_PLANS] = {id:roles.GROUP_PAYMENT_PLANS, label:'settings.payment-plans.title'};\n roles.groups[roles.GROUP_INVENTORY] = {id:roles.GROUP_INVENTORY, label:'item.inventory'};\n roles.groups[roles.GROUP_PURCHASING] = {id:roles.GROUP_PURCHASING, label:'settings.header.purchasing'};\n roles.groups[roles.GROUP_REGISTRY] = {id:roles.GROUP_REGISTRY, label:'settings.role.label.registry'};\n roles.groups[roles.GROUP_MARKETPLACE] = {id:roles.GROUP_MARKETPLACE, label:'settings.role.label.marketplace'};\n roles.groups[roles.GROUP_REPORTS] = {id:roles.GROUP_REPORTS, label:'reports'};\n roles.groups[roles.GROUP_ADMINISTRATION] = {id:roles.GROUP_ADMINISTRATION, label:'settings'};\n roles.groups[roles.GROUP_CLIENT_PORTAL] = {id:roles.GROUP_CLIENT_PORTAL, label:'settings.account.client-portal'};\n roles.groups[roles.GROUP_INTEGRATIONS] = {id:roles.GROUP_INTEGRATIONS, label:'settings.header.integrations'};\n roles.groups[roles.GROUP_QUOTES] = { id:roles.GROUP_QUOTES, label:'quote.quotes', validate:[{ type: '$rootScope', field: 'isQuoteEnabled' }] };\n\n /* Individual permissions setup */\n roles.permissions = {};\n \n roles.ADMIN_CLOCK = \"ADMIN_CLOCK\";\n roles.SALES_PERFORMANCE = \"SALES_PERFORMANCE\";\n roles.TIME_CLOCK = \"TIME_CLOCK\";\n roles.PUNCH_HISTORY = \"PUNCH_HISTORY\";\n roles.TIME_OFF = \"TIME_OFF\";\n roles.ATTENTION_ITEMS = \"ATTENTION_ITEMS\";\n roles.TODAYS_NOTES = \"TODAYS_NOTES\";\n roles.PRINT_SCHEDULE = \"PRINT_SCHEDULE\";\n roles.END_OF_DAY = \"END_OF_DAY\";\n roles.VIEW_PAYMENT_PLAN_PERFORMANCE = \"VIEW_PAYMENT_PLAN_PERFORMANCE\";\n\n roles.permissions[roles.ADMIN_CLOCK] = {id:roles.ADMIN_CLOCK, groupName: roles.groups[roles.GROUP_DASHBOARD].label, groupId:roles.GROUP_DASHBOARD, label:\"settings.role.admin-clock\", description:\"settings.ability.home.to-clock-in/out-for-users\"};\n roles.permissions[roles.SALES_PERFORMANCE] = {id:roles.SALES_PERFORMANCE, groupName: roles.groups[roles.GROUP_DASHBOARD].label, groupId:roles.GROUP_DASHBOARD, label:\"settings.role.my-sales-performance\", description:\"settings.ability.home.to-view-my-sales-performance\"};\n roles.permissions[roles.TIME_CLOCK] = {id:roles.TIME_CLOCK, groupName: roles.groups[roles.GROUP_DASHBOARD].label, groupId:roles.GROUP_DASHBOARD, label:\"settings.role.time-clock\", description:\"settings.ability.home.to-clock-in/out\"};\n roles.permissions[roles.PUNCH_HISTORY] = {id:roles.PUNCH_HISTORY, groupName: roles.groups[roles.GROUP_DASHBOARD].label, groupId:roles.GROUP_DASHBOARD, label:\"settings.role.punch-history\", description:\"settings.ability.home.to-view-punch-history\"};\n roles.permissions[roles.ATTENTION_ITEMS] = {id:roles.ATTENTION_ITEMS, groupName: roles.groups[roles.GROUP_DASHBOARD].label, groupId:roles.GROUP_DASHBOARD, label:\"settings.role.attention-items\", description:\"settings.ability.home.to-view-attention-items\"};\n roles.permissions[roles.TODAYS_NOTES] = {id:roles.TODAYS_NOTES, groupName: roles.groups[roles.GROUP_DASHBOARD].label, groupId:roles.GROUP_DASHBOARD, label:\"settings.role.todays-notes\", description:\"settings.ability.home.to-view/edit-todays-notes\"};\n roles.permissions[roles.PRINT_SCHEDULE] = {id:roles.PRINT_SCHEDULE, groupName: roles.groups[roles.GROUP_DASHBOARD].label, groupId:roles.GROUP_DASHBOARD, label:\"settings.role.print-schedule\", description:\"settings.ability.home.to-print-work-schedule\"};\n roles.permissions[roles.END_OF_DAY] = {id:roles.END_OF_DAY, groupName: roles.groups[roles.GROUP_DASHBOARD].label, groupId:roles.GROUP_DASHBOARD, label:\"end-of-day.end-of-day\", description:\"settings.ability.home.to-view/interact-end-of-day\"};\n roles.permissions[roles.VIEW_PAYMENT_PLAN_PERFORMANCE] = {id:roles.VIEW_PAYMENT_PLAN_PERFORMANCE, groupName: roles.groups[roles.GROUP_DASHBOARD].label, groupId:roles.GROUP_DASHBOARD, label:\"settings.role.payment-plans.view-payment-plan-performance\", description:\"settings.ability.payment-plans.view-payment-plan-performance\"};\n\n roles.CONTACTS = \"CONTACTS\";\n roles.FAVORITES = \"FAVORITES\";\n roles.PURCHASE_HISTORY = \"PURCHASE_HISTORY\";\n roles.QUOTES_HISTORY = \"QUOTES_HISTORY\";\n roles.ACTIVITIES = \"ACTIVITIES\";\n roles.MESSAGES = \"MESSAGES\";\n roles.CHANGE_ASSOCIATE = \"CHANGE_ASSOCIATE\";\n roles.VIEW_FILES = \"VIEW_FILES\";\n roles.DELETE_FILES = \"DELETE_FILES\";\n roles.DELETE_CONTACTS = \"DELETE_CONTACTS\";\n roles.IMPORT_CONTACTS = \"IMPORT_CONTACTS\";\n roles.MULTI_COPY_CONTACTS = \"MULTI_COPY_CONTACTS\";\n roles.DELETE_CARD_ON_FILE = \"DELETE_CARD_ON_FILE\";\n roles.MERGE_CONTACTS = \"MERGE_CONTACTS\";\n roles.EMAIL_ADDITIONAL_OPTIONS = \"EMAIL_ADDITIONAL_OPTIONS\";\n roles.ADDITIONAL_DETAILS = \"ADDITIONAL_DETAILS\";\n roles.ADDITIONAL_DETAILS_EDIT = \"ADDITIONAL_DETAILS_EDIT\";\n //roles.ADDITIONAL_DETAILS_REMOVE = \"ADDITIONAL_DETAILS_REMOVE\";\n\n roles.permissions[roles.CONTACTS] = {id:roles.CONTACTS, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.header.contacts\", description:\"settings.ability.contacts.to-view-create-edit\"};\n roles.permissions[roles.FAVORITES] = {id:roles.FAVORITES, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"contact.menu.favorites\", description:\"settings.ability.contacts.to-view-favorite-items\"};\n //roles.permissions[roles.MARKETING_STAGES] = {id:roles.MARKETING_STAGES, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.role.marketing-stages\", description:\"settings.ability.contacts.to-view-marketing-stages-tab\"};\n roles.permissions[roles.PURCHASE_HISTORY] = {id:roles.PURCHASE_HISTORY, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"contact.menu.purchase-history\", description:\"settings.ability.contacts.to-view-purchase-history-tab\"};\n roles.permissions[roles.QUOTES_HISTORY] = {id:roles.QUOTES_HISTORY, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.role.quotes.quotes-history\", description:\"settings.ability.quotes.quotes-history\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.ACTIVITIES] = {id:roles.ACTIVITIES, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.header.activities\", description:\"settings.ability.contacts.to-vce-appts-tasks\"};\n roles.permissions[roles.MESSAGES] = {id:roles.MESSAGES, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"contact.messages\", description:\"settings.ability.contacts.to-vce-email-sms\"};\n roles.permissions[roles.CHANGE_ASSOCIATE] = {id:roles.CHANGE_ASSOCIATE, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"appointment.bulk-actions.change-associate\", description:\"settings.ability.contacts.to-change-associate\"};\n roles.permissions[roles.IMPORT_CONTACTS] = {id:roles.IMPORT_CONTACTS, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.role.import-contacts\", description:\"settings.ability.contacts.to-import\"};\n roles.permissions[roles.MULTI_COPY_CONTACTS] = {id:roles.MULTI_COPY_CONTACTS, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.role.copy-contacts-elite-plan\", description:\"settings.ability.contacts.to-copy-to-other-locations\"};\n roles.permissions[roles.VIEW_FILES] = {id:roles.VIEW_FILES, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.role.view-files\", description:\"settings.ability.contacts.to-view-files-associated\"};\n roles.permissions[roles.DELETE_FILES] = {id:roles.DELETE_FILES, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.role.delete-files\", description:\"settings.ability.contacts.to-delete-files-associated\"};\n roles.permissions[roles.DELETE_CONTACTS] = {id:roles.DELETE_CONTACTS, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.role.delete-contacts\", description:\"settings.ability.contacts.to-delete-contacts\"};\n roles.permissions[roles.DELETE_CARD_ON_FILE] = {id:roles.DELETE_CARD_ON_FILE, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.role.delete-card-on-file\", description:\"settings.ability.contacts.to-delete-card-on-file\"};\n roles.permissions[roles.MERGE_CONTACTS] = {id:roles.MERGE_CONTACTS, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.role.merge-contacts\", description:\"settings.ability.contacts.to-merge-contacts\"};\n roles.permissions[roles.EMAIL_ADDITIONAL_OPTIONS] = {id:roles.EMAIL_ADDITIONAL_OPTIONS, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.role.email-additional-options\", description:\"settings.ability.contacts.to-edit-email-additional-options\"};\n roles.permissions[roles.ADDITIONAL_DETAILS] = {id:roles.ADDITIONAL_DETAILS, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.role.contact-additional-details\", description:\"settings.ability.contacts.to-view-contact-additional-details\"};\n roles.permissions[roles.ADDITIONAL_DETAILS_EDIT] = {id:roles.ADDITIONAL_DETAILS_EDIT, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.role.contact-additional-details-edit\", description:\"settings.ability.contacts.to-edit-contact-additional-details\"};\n //roles.permissions[roles.ADDITIONAL_DETAILS_REMOVE] = {id:roles.ADDITIONAL_DETAILS_REMOVE, groupName: roles.groups[roles.GROUP_CONTACT_CENTER].label, groupId:roles.GROUP_CONTACT_CENTER, label:\"settings.role.contact-additional-details-remove\", description:\"settings.ability.contacts.to-remove-contact-additional-details\"};\n\n roles.LEADS = \"LEADS\";\n roles.APPT_REQUESTS = \"APPT_REQUESTS\";\n roles.INTERVIEWS = \"INTERVIEWS\";\n roles.FEEDBACK = \"FEEDBACK\";\n roles.EVENT_REQUESTS = \"EVENT_REQUESTS\";\n roles.ONLINE_PAYMENTS = \"ONLINE_PAYMENTS\";\n roles.ONLINE_SIGNATURES = \"ONLINE_SIGNATURES\";\n roles.ONLINE_MEASUREMENTS = \"ONLINE_MEASUREMENTS\";\n roles.CONTACT_UPDATE_REQUESTS = \"CONTACT_UPDATE_REQUESTS\";\n roles.PAYMENT_UPDATE_REQUESTS = \"PAYMENT_UPDATE_REQUESTS\";\n roles.DELETE_ONLINE_SUBMISSIONS = \"DELETE_ONLINE_SUBMISSIONS\";\n roles.permissions[roles.LEADS] = {id:roles.LEADS, groupName: roles.groups[roles.GROUP_MARKETING_TOOLS].label, groupId:roles.GROUP_MARKETING_TOOLS, label:\"interface.leads\", description:\"settings.ability.marketing-tools.to-manage-leads\"};\n roles.permissions[roles.APPT_REQUESTS] = {id:roles.APPT_REQUESTS, groupName: roles.groups[roles.GROUP_MARKETING_TOOLS].label, groupId:roles.GROUP_MARKETING_TOOLS, label:\"appointment.request.requests\", description:\"settings.ability.marketing-tools.to-manage-appt-requests\"};\n roles.permissions[roles.INTERVIEWS] = {id:roles.INTERVIEWS, groupName: roles.groups[roles.GROUP_MARKETING_TOOLS].label, groupId:roles.GROUP_MARKETING_TOOLS, label:\"interface.interviews\", description:\"settings.ability.marketing-tools.to-manage-interviews\"};\n roles.permissions[roles.FEEDBACK] = {id:roles.FEEDBACK, groupName: roles.groups[roles.GROUP_MARKETING_TOOLS].label, groupId:roles.GROUP_MARKETING_TOOLS, label:\"contact.feedback\", description:\"settings.ability.marketing-tools.to-manage-feedback\"};\n roles.permissions[roles.EVENT_REQUESTS] = {id:roles.EVENT_REQUESTS, groupName: roles.groups[roles.GROUP_MARKETING_TOOLS].label, groupId:roles.GROUP_MARKETING_TOOLS, label:\"client-portal.event-registrations\", description:\"settings.ability.marketing-tools.to-manage-event-registrations\"};\n roles.permissions[roles.ONLINE_PAYMENTS] = {id:roles.ONLINE_PAYMENTS, groupName: roles.groups[roles.GROUP_MARKETING_TOOLS].label, groupId:roles.GROUP_MARKETING_TOOLS, label:\"interface.online-payments\", description:\"settings.ability.marketing-tools.to-manage-online-payments\"};\n roles.permissions[roles.ONLINE_SIGNATURES] = {id:roles.ONLINE_SIGNATURES, groupName: roles.groups[roles.GROUP_MARKETING_TOOLS].label, groupId:roles.GROUP_MARKETING_TOOLS, label:\"interface.online-signatures\", description:\"settings.ability.marketing-tools.to-manage-online-signatures\"};\n roles.permissions[roles.ONLINE_MEASUREMENTS] = {id:roles.ONLINE_MEASUREMENTS, groupName: roles.groups[roles.GROUP_MARKETING_TOOLS].label, groupId:roles.GROUP_MARKETING_TOOLS, label:\"interface.online-measurements\", description:\"settings.ability.marketing-tools.to-manage-online-measurements\"};\n roles.permissions[roles.CONTACT_UPDATE_REQUESTS] = {id:roles.CONTACT_UPDATE_REQUESTS, groupName: roles.groups[roles.GROUP_MARKETING_TOOLS].label, groupId:roles.GROUP_MARKETING_TOOLS, label:\"client-portal.contact-update-requests\", description:\"settings.ability.marketing-tools.to-manage-contact-update-requests\"};\n roles.permissions[roles.PAYMENT_UPDATE_REQUESTS] = {id:roles.PAYMENT_UPDATE_REQUESTS, groupName: roles.groups[roles.GROUP_MARKETING_TOOLS].label, groupId:roles.GROUP_MARKETING_TOOLS, label:\"client-portal.payment-update-requests\", description:\"settings.ability.marketing-tools.to-manage-payment-update-requests\"};\n roles.permissions[roles.DELETE_ONLINE_SUBMISSIONS] = {id:roles.DELETE_ONLINE_SUBMISSIONS, groupName: roles.groups[roles.GROUP_MARKETING_TOOLS].label, groupId:roles.GROUP_MARKETING_TOOLS, label:\"interface.delete-online-submissions\", description:\"settings.ability.marketing-tools.to-delete-online-submissions\"};\n\n roles.CALENDAR = \"CALENDAR\";\n roles.FITTING_ROOM_VIEW = \"FITTING_ROOM_VIEW\";\n roles.EMPLOYEE_VIEW = \"EMPLOYEE_VIEW\";\n roles.APPOINTMENTS = \"APPOINTMENTS\";\n roles.TASKS = \"TASKS\";\n roles.WAIT_LISTS = \"WAIT_LISTS\";\n roles.BOOK_WAIT_LISTS = \"BOOK_WAIT_LISTS\";\n roles.EDIT_WAIT_LISTS = \"EDIT_WAIT_LISTS\";\n roles.DELETE_WAIT_LISTS = \"DELETE_WAIT_LISTS\";\n roles.ADD_WORK_SCHEDULE = \"ADD_WORK_SCHEDULE\";\n roles.EDIT_WORK_SCHEDULE = \"EDIT_WORK_SCHEDULE\";\n roles.DELETE_WORK_SCHEDULE = \"DELETE_WORK_SCHEDULE\";\n roles.PRINT_WORK_SCHEDULE = \"PRINT_WORK_SCHEDULE\";\n\n roles.permissions[roles.CALENDAR] = {id:roles.CALENDAR, groupName: roles.groups[roles.GROUP_ACTIVITY_CENTER].label, groupId:roles.GROUP_ACTIVITY_CENTER, label:\"calendar\", description:\"settings.ability.activities.to-view-day/week/month-views\"};\n roles.permissions[roles.FITTING_ROOM_VIEW] = {id:roles.FITTING_ROOM_VIEW, groupName: roles.groups[roles.GROUP_ACTIVITY_CENTER].label, groupId:roles.GROUP_ACTIVITY_CENTER, label:\"interface.fitting-room-view\", description:\"settings.ability.activities.to-view-fitting-room-view\"};\n roles.permissions[roles.EMPLOYEE_VIEW] = {id:roles.EMPLOYEE_VIEW, groupName: roles.groups[roles.GROUP_ACTIVITY_CENTER].label, groupId:roles.GROUP_ACTIVITY_CENTER, label:\"settings.role.employee-view\", description:\"settings.ability.activities.to-view-employee-view\"};\n roles.permissions[roles.APPOINTMENTS] = {id:roles.APPOINTMENTS, groupName: roles.groups[roles.GROUP_ACTIVITY_CENTER].label, groupId:roles.GROUP_ACTIVITY_CENTER, label:\"contact.appointments\", description:\"settings.ability.appointments.to-view-appointments\"};\n roles.permissions[roles.TASKS] = {id:roles.TASKS, groupName: roles.groups[roles.GROUP_ACTIVITY_CENTER].label, groupId:roles.GROUP_ACTIVITY_CENTER, label:\"calendar.tasks\", description:\"settings.ability.activities.to-view/create/edit-tasks\"};\n roles.permissions[roles.WAIT_LISTS] = {id:roles.WAIT_LISTS, groupName: roles.groups[roles.GROUP_ACTIVITY_CENTER].label, groupId:roles.GROUP_ACTIVITY_CENTER, label:\"settings.role.wait-list\", description:\"settings.ability.activities.to-view/create\"};\n roles.permissions[roles.BOOK_WAIT_LISTS] = {id:roles.BOOK_WAIT_LISTS, groupName: roles.groups[roles.GROUP_ACTIVITY_CENTER].label, groupId:roles.GROUP_ACTIVITY_CENTER, label:\"settings.role.wait-list-book\", description:\"settings.ability.activities.to-book-wait-lists\"};\n roles.permissions[roles.EDIT_WAIT_LISTS] = {id:roles.EDIT_WAIT_LISTS, groupName: roles.groups[roles.GROUP_ACTIVITY_CENTER].label, groupId:roles.GROUP_ACTIVITY_CENTER, label:\"settings.role.wait-list-edit\", description:\"settings.ability.activities.to-edit-wait-lists\"};\n roles.permissions[roles.DELETE_WAIT_LISTS] = {id:roles.DELETE_WAIT_LISTS, groupName: roles.groups[roles.GROUP_ACTIVITY_CENTER].label, groupId:roles.GROUP_ACTIVITY_CENTER, label:\"settings.role.wait-list-delete\", description:\"settings.ability.activities.to-delete-wait-lists\"};\n roles.permissions[roles.ADD_WORK_SCHEDULE] = {id:roles.ADD_WORK_SCHEDULE, groupName: roles.groups[roles.GROUP_ACTIVITY_CENTER].label, groupId:roles.GROUP_ACTIVITY_CENTER, label:\"settings.role.add-work-schedule\", description:\"settings.ability.settings.add-work-schedule\"};\n roles.permissions[roles.EDIT_WORK_SCHEDULE] = {id:roles.EDIT_WORK_SCHEDULE, groupName: roles.groups[roles.GROUP_ACTIVITY_CENTER].label, groupId:roles.GROUP_ACTIVITY_CENTER, label:\"settings.role.edit-work-schedule\", description:\"settings.ability.settings.edit-work-schedule\"};\n roles.permissions[roles.DELETE_WORK_SCHEDULE] = {id:roles.DELETE_WORK_SCHEDULE, groupName: roles.groups[roles.GROUP_ACTIVITY_CENTER].label, groupId:roles.GROUP_ACTIVITY_CENTER, label:\"settings.role.delete-work-schedule\", description:\"settings.ability.settings.delete-work-schedule\"};\n roles.permissions[roles.PRINT_WORK_SCHEDULE] = {id:roles.PRINT_WORK_SCHEDULE, groupName: roles.groups[roles.GROUP_ACTIVITY_CENTER].label, groupId:roles.GROUP_ACTIVITY_CENTER, label:\"settings.role.print-work-schedule\", description:\"settings.ability.settings.print-work-schedule\"};\n\n roles.SMART_BOOK_APPOINTMENTS = \"SMART_BOOK_APPOINTMENTS\";\n roles.ADD_APPOINTMENT = \"ADD_APPOINTMENT\";\n roles.VIEW_APPOINTMENTS = \"VIEW_APPOINTMENTS\";\n roles.RESCHEDULE_APPOINTMENTS = \"RESCHEDULE_APPOINTMENTS\";\n roles.EDIT_APPOINTMENT_DATE = \"EDIT_APPOINTMENT_DATE\";\n roles.EDIT_APPOINTMENT_CONFIRM_OR_CHECKIN = \"EDIT_APPOINTMENT_CONFIRM_OR_CHECKIN\";\n roles.EDIT_APPOINTMENT_STATUS = \"EDIT_APPOINTMENT_STATUS\";\n roles.EDIT_APPOINTMENT_CONTACT = \"EDIT_APPOINTMENT_CONTACT\";\n roles.EDIT_APPOINTMENT_NOTES = \"EDIT_APPOINTMENT_NOTES\";\n roles.EDIT_APPOINTMENT_TYPE = \"EDIT_APPOINTMENT_TYPE\";\n roles.EDIT_APPOINTMENT_DURATION = \"EDIT_APPOINTMENT_DURATION\";\n roles.EDIT_APPOINTMENT_FITTING_ROOM = \"EDIT_APPOINTMENT_FITTING_ROOM\";\n roles.EDIT_APPOINTMENT_ASSOCIATE = \"EDIT_APPOINTMENT_ASSOCIATE\";\n roles.EDIT_APPOINTMENT_RESEND = \"EDIT_APPOINTMENT_RESEND\";\n roles.EDIT_APPOINTMENT_TASKS = \"EDIT_APPOINTMENT_TASKS\";\n roles.CHARGE_APPOINTMENTS = \"CHARGE_APPOINTMENTS\";\n roles.PRINT_APPOINTMENT_SHEET = \"PRINT_APPOINTMENT_SHEET\";\n roles.DELETE_APPOINTMENTS = \"DELETE_APPOINTMENTS\";\n\n roles.permissions[roles.SMART_BOOK_APPOINTMENTS] = {id:roles.SMART_BOOK_APPOINTMENTS, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"calendar.smart-book\", description: \"settings.ability.appointments.to-create-appointments-from-smart-book\"};\n roles.permissions[roles.ADD_APPOINTMENT] = {id:roles.ADD_APPOINTMENT, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.add-appointments\", description: \"settings.ability.appointments.to-add-appointments\"};\n roles.permissions[roles.VIEW_APPOINTMENTS] = {id:roles.VIEW_APPOINTMENTS, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.view-appointments\", description: \"settings.ability.appointments.to-view-appointment-details\"};\n roles.permissions[roles.RESCHEDULE_APPOINTMENTS] = {id:roles.RESCHEDULE_APPOINTMENTS, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.reschedule-appointments\", description: \"settings.ability.appointments.to-reschedule-appointments\"};\n roles.permissions[roles.EDIT_APPOINTMENT_DATE] = {id:roles.EDIT_APPOINTMENT_DATE, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.edit-appointment-date\", description: \"settings.ability.appointments.to-edit-appointment-date\"};\n roles.permissions[roles.EDIT_APPOINTMENT_CONFIRM_OR_CHECKIN] = {id:roles.EDIT_APPOINTMENT_CONFIRM_OR_CHECKIN, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.edit-appointment-confirm-or-checkin\", description: \"settings.ability.appointments.to-edit-appointment-confirm-or-checkin\"};\n roles.permissions[roles.EDIT_APPOINTMENT_STATUS] = {id:roles.EDIT_APPOINTMENT_STATUS, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.edit-appointment-status\", description: \"settings.ability.appointments.to-edit-appointment-status\"};\n roles.permissions[roles.EDIT_APPOINTMENT_CONTACT] = {id:roles.EDIT_APPOINTMENT_CONTACT, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.edit-appointment-contact\", description: \"settings.ability.appointments.to-edit-appointment-contact\"};\n roles.permissions[roles.EDIT_APPOINTMENT_NOTES] = {id:roles.EDIT_APPOINTMENT_NOTES, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.edit-appointment-notes\", description: \"settings.ability.appointments.to-edit-appointment-notes\"};\n roles.permissions[roles.EDIT_APPOINTMENT_TYPE] = {id:roles.EDIT_APPOINTMENT_TYPE, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.edit-appointment-type\", description: \"settings.ability.appointments.to-edit-appointment-type\"};\n roles.permissions[roles.EDIT_APPOINTMENT_DURATION] = {id:roles.EDIT_APPOINTMENT_DURATION, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.edit-appointment-duration\", description: \"settings.ability.appointments.to-edit-appointment-duration\"};\n roles.permissions[roles.EDIT_APPOINTMENT_FITTING_ROOM] = {id:roles.EDIT_APPOINTMENT_FITTING_ROOM, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.edit-appointment-fitting-room\", description: \"settings.ability.appointments.to-edit-appointment-fitting-room\"};\n roles.permissions[roles.EDIT_APPOINTMENT_ASSOCIATE] = {id:roles.EDIT_APPOINTMENT_ASSOCIATE, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.edit-appointment-associate\", description: \"settings.ability.appointments.to-edit-appointment-associate\"};\n roles.permissions[roles.EDIT_APPOINTMENT_RESEND] = {id:roles.EDIT_APPOINTMENT_RESEND, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.resend-notifications\", description: \"settings.ability.appointments.to-resend-notifications\"};\n roles.permissions[roles.EDIT_APPOINTMENT_TASKS] = {id:roles.EDIT_APPOINTMENT_TASKS, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.reassign-tasks\", description: \"settings.ability.appointments.to-reassign-tasks\"};\n roles.permissions[roles.CHARGE_APPOINTMENTS] = {id:roles.CHARGE_APPOINTMENTS, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.charge-appointments\", description: \"settings.ability.appointments.to-charge-appointments\"};\n roles.permissions[roles.PRINT_APPOINTMENT_SHEET] = {id:roles.PRINT_APPOINTMENT_SHEET, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId: roles.GROUP_APPOINTMENTS, label: \"settings.role.appointments.print-appointment-sheet\", description: \"settings.ability.appointments.to-print-appointment-sheet\"};\n roles.permissions[roles.DELETE_APPOINTMENTS] = {id:roles.DELETE_APPOINTMENTS, groupName: roles.groups[roles.GROUP_APPOINTMENTS].label, groupId:roles.GROUP_APPOINTMENTS, label:\"settings.role.delete-appointments\", description:\"settings.ability.appointments.to-delete-appointments\"};\n\n roles.DEPARTMENTS = \"DEPARTMENTS\";\n roles.ITEMS = \"ITEMS\";\n roles.QUICK_ADD_ITEM = \"QUICK_ADD_ITEM\";\n roles.DELETE_ITEM = \"DELETE_ITEM\";\n roles.EDIT_ITEM = \"EDIT_ITEM\";\n roles.PHYSICAL_INVENTORY = \"PHYSICAL_INVENTORY\";\n roles.MERCHANDISE_TAGS = \"MERCHANDISE_TAGS\";\n roles.VENDORS = \"VENDORS\";\n roles.ITEM_COST = \"ITEM_COST\";\n roles.IMPORT_ITEMS = \"IMPORT_ITEMS\";\n roles.IMPORT_DEPARTMENTS = \"IMPORT_DEPARTMENTS\";\n roles.IMPORT_VENDORS = \"IMPORT_VENDORS\";\n roles.MULTI_TRANSFER_ITEMS = \"MULTI_TRANSFER_ITEMS\";\n roles.ITEM_SALE_PRICE = \"ITEM_SALE_PRICE\";\n\n roles.ADD_ITEM_VARIANT = \"ADD_ITEM_VARIANT\";\n roles.EDIT_ITEM_VARIANT = \"EDIT_ITEM_VARIANT\";\n roles.EDIT_ITEM_NOTE_VARIANT = \"EDIT_ITEM_NOTE_VARIANT\";\n roles.EDIT_ITEM_DESC_VARIANT = \"EDIT_ITEM_DESC_VARIANT\";\n roles.EDIT_ITEM_PRICE_VARIANT = \"EDIT_ITEM_PRICE_VARIANT\";\n roles.EDIT_ITEM_COST_VARIANT = \"EDIT_ITEM_COST_VARIANT\";\n roles.REMOVE_ITEM_VARIANT = \"REMOVE_ITEM_VARIANT\";\n roles.VIEW_ITEM_VARIANTS = \"VIEW_ITEM_VARIANTS\";\n\n roles.permissions[roles.DEPARTMENTS] = {id:roles.DEPARTMENTS, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.departments\", description:\"settings.ability.inventory.view/create/edit-departments\"};\n roles.permissions[roles.ITEMS] = {id:roles.ITEMS, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"item.search\", description:\"settings.ability.inventory.search-items\"};\n roles.permissions[roles.QUICK_ADD_ITEM] = {id:roles.QUICK_ADD_ITEM, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.add-items\", description:\"settings.ability.inventory.add-items\"};\n roles.permissions[roles.DELETE_ITEM] = {id:roles.DELETE_ITEM, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.delete-items\", description:\"settings.ability.inventory.delete-items\"};\n roles.permissions[roles.EDIT_ITEM] = {id:roles.EDIT_ITEM, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.edit-items\", description:\"settings.ability.inventory.edit-items\"};\n roles.permissions[roles.PHYSICAL_INVENTORY] = {id:roles.PHYSICAL_INVENTORY, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"interface.physical-inventory\", description:\"settings.ability.inventory.conduct-physical\"};\n roles.permissions[roles.MERCHANDISE_TAGS] = {id:roles.MERCHANDISE_TAGS, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.merchandise-tags\", description:\"settings.ability.inventory.print-merchandise-tags\"};\n roles.permissions[roles.VENDORS] = {id:roles.VENDORS, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.vendors\", description:\"settings.ability.inventory.view/create/edit-vendors\"};\n roles.permissions[roles.ITEM_COST] = {id:roles.ITEM_COST, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.item-cost\", description:\"settings.ability.inventory.view/edit-costs\"};\n roles.permissions[roles.ITEM_SALE_PRICE] = {id:roles.ITEM_SALE_PRICE, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.item-sale-price\", description:\"settings.ability.inventory.edit-sale-price\"};\n roles.permissions[roles.IMPORT_DEPARTMENTS] = {id:roles.IMPORT_DEPARTMENTS, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.import-departments\", description:\"settings.ability.inventory.import-departments\"};\n roles.permissions[roles.IMPORT_VENDORS] = {id:roles.IMPORT_VENDORS, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.import-vendors\", description:\"settings.ability.inventory.import-vendors\"};\n roles.permissions[roles.IMPORT_ITEMS] = {id:roles.IMPORT_ITEMS, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.import-items\", description:\"settings.ability.inventory.import-items\"};\n roles.permissions[roles.MULTI_TRANSFER_ITEMS] = {id:roles.MULTI_TRANSFER_ITEMS, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.transfer-items\", description:\"settings.ability.inventory.transfer-items\"};\n\n roles.permissions[roles.ADD_ITEM_VARIANT] = {id:roles.ADD_ITEM_VARIANT, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.item-add-on.add-item-add-on\", description:\"settings.ability.point-of-sale.item-add-on.add-item-add-on\"};\n roles.permissions[roles.EDIT_ITEM_VARIANT] = {id:roles.EDIT_ITEM_VARIANT, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.item-add-on.edit-item-add-on\", description:\"settings.ability.point-of-sale.item-add-on.edit-item-add-on\"};\n roles.permissions[roles.EDIT_ITEM_NOTE_VARIANT] = {id:roles.EDIT_ITEM_NOTE_VARIANT, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.item-add-on.edit-item-add-on-note\", description:\"settings.ability.point-of-sale.item-add-on.edit-item-add-on-note\"};\n roles.permissions[roles.EDIT_ITEM_DESC_VARIANT] = {id:roles.EDIT_ITEM_DESC_VARIANT, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.item-add-on.edit-item-add-on-desc\", description:\"settings.ability.point-of-sale.item-add-on.edit-item-add-on-desc\"};\n roles.permissions[roles.EDIT_ITEM_PRICE_VARIANT] = {id:roles.EDIT_ITEM_PRICE_VARIANT, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.item-add-on.edit-item-add-on-price\", description:\"settings.ability.point-of-sale.item-add-on.edit-item-add-on-price\"};\n roles.permissions[roles.EDIT_ITEM_COST_VARIANT] = {id:roles.EDIT_ITEM_COST_VARIANT, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.item-add-on.edit-item-add-on-cost\", description:\"settings.ability.point-of-sale.item-add-on.edit-item-add-on-cost\"};\n roles.permissions[roles.REMOVE_ITEM_VARIANT] = {id:roles.REMOVE_ITEM_VARIANT, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.item-add-on.remove-item-add-on\", description:\"settings.ability.point-of-sale.item-add-on.remove-item-add-on\"};\n roles.permissions[roles.VIEW_ITEM_VARIANTS] = {id:roles.VIEW_ITEM_VARIANTS, groupName: roles.groups[roles.GROUP_INVENTORY].label, groupId:roles.GROUP_INVENTORY, label:\"settings.role.item-add-on.view-item-add-on\", description:\"settings.ability.point-of-sale.item-add-on.view-item-add-on\"};\n\n roles.PURCHASE_ORDERS = \"PURCHASE_ORDERS\";\n roles.EDIT_PURCHASE_ORDERS = \"EDIT_PURCHASE_ORDERS\";\n roles.DELETE_PURCHASE_ORDERS = \"DELETE_PURCHASE_ORDERS\";\n roles.VOID_PURCHASE_ORDERS = \"VOID_PURCHASE_ORDERS\";\n roles.RECEIVING_VOUCHERS = \"RECEIVING_VOUCHERS\";\n roles.DELETE_RECEIVING_VOUCHERS = \"DELETE_RECEIVING_VOUCHERS\";\n roles.ADD_PO_ITEM_ADD_ON = \"ADD_PO_ITEM_ADD_ON\";\n roles.EDIT_PO_ITEM_ADD_ON_NOTE = \"EDIT_PO_ITEM_ADD_ON_NOTE\";\n roles.EDIT_PO_ITEM_ADD_ON_DESC = \"EDIT_PO_ITEM_ADD_ON_DESC\";\n roles.EDIT_PO_ITEM_ADD_ON_COST = \"EDIT_PO_ITEM_ADD_ON_COST\";\n roles.REMOVE_PO_ITEM_ADD_ON = \"REMOVE_PO_ITEM_ADD_ON\";\n roles.PO_ITEM_ADD_ON_REQUIRED = \"PO_ITEM_ADD_ON_REQUIRED\";\n roles.SELECT_PO_ITEM_ADD_ON = \"SELECT_PO_ITEM_ADD_ON\";\n\n roles.permissions[roles.PURCHASE_ORDERS] = {id:roles.PURCHASE_ORDERS, groupName: roles.groups[roles.GROUP_PURCHASING].label, groupId:roles.GROUP_PURCHASING, label:\"settings.role.create-pos\", description:\"settings.ability.purchasing.create-pos\"};\n roles.permissions[roles.EDIT_PURCHASE_ORDERS] = {id:roles.EDIT_PURCHASE_ORDERS, groupName: roles.groups[roles.GROUP_PURCHASING].label, groupId:roles.GROUP_PURCHASING, label:\"settings.role.edit-pos\", description:\"settings.ability.purchasing.edit-pos\"};\n roles.permissions[roles.DELETE_PURCHASE_ORDERS] = {id:roles.DELETE_PURCHASE_ORDERS, groupName: roles.groups[roles.GROUP_PURCHASING].label, groupId:roles.GROUP_PURCHASING, label:\"settings.role.delete-pos\", description:\"settings.ability.purchasing.delete-pos\"};\n roles.permissions[roles.VOID_PURCHASE_ORDERS] = {id:roles.VOID_PURCHASE_ORDERS, groupName: roles.groups[roles.GROUP_PURCHASING].label, groupId:roles.GROUP_PURCHASING, label:\"settings.role.void-pos\", description:\"settings.ability.purchasing.void-pos\"};\n roles.permissions[roles.RECEIVING_VOUCHERS] = {id:roles.RECEIVING_VOUCHERS, groupName: roles.groups[roles.GROUP_PURCHASING].label, groupId:roles.GROUP_PURCHASING, label:\"settings.quickbooks.receiving-vouchers\", description:\"settings.ability.purchasing.view/create/edit-pos\"};\n roles.permissions[roles.DELETE_RECEIVING_VOUCHERS] = {id:roles.DELETE_RECEIVING_VOUCHERS, groupName: roles.groups[roles.GROUP_PURCHASING].label, groupId:roles.GROUP_PURCHASING, label:\"settings.role.delete-receiving-vouchers\", description:\"settings.ability.purchasing.delete-rv\"};\n roles.permissions[roles.ADD_PO_ITEM_ADD_ON] = {id:roles.ADD_PO_ITEM_ADD_ON, groupName: roles.groups[roles.GROUP_PURCHASING].label, groupId:roles.GROUP_PURCHASING, label:\"settings.role.add-on.add-item-add-on\", description:\"settings.ability.point-of-sale.add-on.add-item-add-on\"};\n roles.permissions[roles.EDIT_PO_ITEM_ADD_ON_NOTE] = {id:roles.EDIT_PO_ITEM_ADD_ON_NOTE, groupName: roles.groups[roles.GROUP_PURCHASING].label, groupId:roles.GROUP_PURCHASING, label:\"settings.role.add-on.edit-item-add-on-note\", description:\"settings.ability.point-of-sale.add-on.edit-item-add-on-note\"};\n roles.permissions[roles.EDIT_PO_ITEM_ADD_ON_DESC] = {id:roles.EDIT_PO_ITEM_ADD_ON_DESC, groupName: roles.groups[roles.GROUP_PURCHASING].label, groupId:roles.GROUP_PURCHASING, label:\"settings.role.add-on.edit-item-add-on-desc\", description:\"settings.ability.point-of-sale.add-on.edit-item-add-on-desc\"};\n roles.permissions[roles.EDIT_PO_ITEM_ADD_ON_COST] = {id:roles.EDIT_PO_ITEM_ADD_ON_COST, groupName: roles.groups[roles.GROUP_PURCHASING].label, groupId:roles.GROUP_PURCHASING, label:\"settings.role.add-on.edit-item-add-on-cost\", description:\"settings.ability.point-of-sale.add-on.edit-item-add-on-cost\"};\n roles.permissions[roles.REMOVE_PO_ITEM_ADD_ON] = {id:roles.REMOVE_PO_ITEM_ADD_ON, groupName: roles.groups[roles.GROUP_PURCHASING].label, groupId:roles.GROUP_PURCHASING, label:\"settings.role.add-on.remove-item-add-on\", description:\"settings.ability.point-of-sale.add-on.remove-item-add-on\"};\n roles.permissions[roles.PO_ITEM_ADD_ON_REQUIRED] = {id:roles.PO_ITEM_ADD_ON_REQUIRED, groupName: roles.groups[roles.GROUP_PURCHASING].label, groupId:roles.GROUP_PURCHASING, label:\"settings.role.add-on.po-required-item-add-on\", description:\"settings.ability.point-of-sale.add-on.po-required-item-add-on\"};\n roles.permissions[roles.SELECT_PO_ITEM_ADD_ON] = {id:roles.SELECT_PO_ITEM_ADD_ON, groupName: roles.groups[roles.GROUP_PURCHASING].label, groupId:roles.GROUP_POS, label:\"settings.role.add-on.select-item-add-on\", description:\"settings.ability.point-of-sale.add-on.select-item-add-on\"};\n\n roles.SALES = \"SALES\";\n roles.SPECIAL_ORDERS = \"SPECIAL_ORDERS\";\n roles.LAYAWAY = \"LAYAWAY\";\n roles.RETURNS = \"RETURNS\";\n roles.EDIT_TRANSACTIONS = \"EDIT_TRANSACTIONS\";\n roles.VOID_PAYMENTS = \"VOID_PAYMENTS\";\n roles.CHANGE_ASSOCIATE_ON_PAYMENT = \"CHANGE_ASSOCIATE_ON_PAYMENT\";\n roles.DELETE_TRANSACTIONS = \"DELETE_TRANSACTIONS\";\n roles.UNCOMPLETE_TRANSACTIONS = \"UNCOMPLETE_TRANSACTIONS\";\n roles.DELETE_PAYMENTS = \"DELETE_PAYMENTS\";\n roles.POS_HISTORY = \"POS_HISTORY\";\n roles.CAN_EDIT_DIGITAL_SIGNATURES = \"CAN_EDIT_DIGITAL_SIGNATURES\";\n roles.COMPLETE_TRANSACTIONS = \"COMPLETE_TRANSACTIONS\";\n roles.EDIT_COMMISSIONS = \"EDIT_COMMISSIONS\";\n roles.EDIT_COMMISSION_EMPLOYEE = \"EDIT_COMMISSION_EMPLOYEE\";\n roles.VIEW_COMMISSION_EMPLOYEE = \"VIEW_COMMISSION_EMPLOYEE\";\n roles.EDIT_COMMISSION_STATUS = \"EDIT_COMMISSION_STATUS\";\n roles.VIEW_COMMISSION_STATUS = \"VIEW_COMMISSION_STATUS\";\n roles.REGISTERS = \"REGISTERS\";\n roles.OPEN_AND_CLOSE_REGISTERS = \"OPEN_AND_CLOSE_REGISTERS\";\n roles.MANUALLY_OPEN_REGISTERS = \"MANUALLY_OPEN_REGISTERS\";\n roles.UPDATE_TRX_COMPLETED_DATE = \"UPDATE_TRX_COMPLETED_DATE\";\n roles.UPDATE_TRX_ZERO_OUT_DATE = \"UPDATE_TRX_ZERO_OUT_DATE\";\n roles.REQUEST_CARD_INFO = \"REQUEST_CARD_INFO\";\n roles.PERMISSION_TO_APPROVE_REQUESTED_PAYMENT_UPDATES = \"PERMISSION_TO_APPROVE_REQUESTED_PAYMENT_UPDATES\";\n roles.ADD_ITEM_ADD_ON = \"ADD_ITEM_ADD_ON\";\n roles.SELECT_ITEM_ADD_ON = \"SELECT_ITEM_ADD_ON\";\n roles.EDIT_ITEM_ADD_ON_NOTE = \"EDIT_ITEM_ADD_ON_NOTE\";\n roles.EDIT_ITEM_ADD_ON_DESC = \"EDIT_ITEM_ADD_ON_DESC\";\n roles.EDIT_ITEM_ADD_ON_PRICE = \"EDIT_ITEM_ADD_ON_PRICE\";\n roles.REMOVE_ITEM_ADD_ON = \"REMOVE_ITEM_ADD_ON\";\n roles.TRX_ITEM_ADD_ON_REQUIRED = \"TRX_ITEM_ADD_ON_REQUIRED\";\n\n //roles.PERMISSION_TO_REQUEST_PAYMENT_PLAN_CREATION = \"PERMISSION_TO_REQUEST_PAYMENT_PLAN_CREATION\";\n\n roles.permissions[roles.SALES] = {id:roles.SALES, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.create-sales\", description:\"settings.ability.point-of-sale.create-sales\"};\n roles.permissions[roles.SPECIAL_ORDERS] = {id:roles.SPECIAL_ORDERS, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.create-so\", description:\"settings.ability.point-of-sale.create-so\"};\n roles.permissions[roles.LAYAWAY] = {id:roles.LAYAWAY, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.create-layaways\", description:\"settings.ability.point-of-sale.create-layaways\"};\n roles.permissions[roles.RETURNS] = {id:roles.RETURNS, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.create-returns\", description:\"settings.ability.point-of-sale.create-returns\"};\n roles.permissions[roles.EDIT_TRANSACTIONS] = {id:roles.EDIT_TRANSACTIONS, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.edit-transaction\", description:\"settings.ability.point-of-sale.edit-transaction\"};\n roles.permissions[roles.VOID_PAYMENTS] = {id:roles.VOID_PAYMENTS, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.void-payments\", description:\"settings.ability.point-of-sale.void-payments\"};\n roles.permissions[roles.CHANGE_ASSOCIATE_ON_PAYMENT] = {id:roles.CHANGE_ASSOCIATE_ON_PAYMENT, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.change-associate-on-payment\", description:\"settings.ability.point-of-sale.change-associate-assigned-to-payment\"};\n roles.permissions[roles.DELETE_TRANSACTIONS] = {id:roles.DELETE_TRANSACTIONS, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.delete-transactions\", description:\"settings.ability.point-of-sale.delete-transactions\"};\n roles.permissions[roles.UNCOMPLETE_TRANSACTIONS] = {id:roles.UNCOMPLETE_TRANSACTIONS, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.uncomplete-transactions\", description:\"settings.ability.point-of-sale.uncomplete-transactions\"};\n roles.permissions[roles.DELETE_PAYMENTS] = {id:roles.DELETE_PAYMENTS, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.delete-payments\", description:\"settings.ability.point-of-sale.delete-payments\"};\n roles.permissions[roles.POS_HISTORY] = {id:roles.POS_HISTORY, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.view-transaction-list\", description:\"settings.ability.point-of-sale.view-transactions\"};\n\n roles.permissions[roles.CAN_EDIT_DIGITAL_SIGNATURES] = {id:roles.CAN_EDIT_DIGITAL_SIGNATURES, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.can-edit-digital-signatures\", description:\"settings.ability.point-of-sale.can-edit-digital-signatures\"};\n roles.permissions[roles.COMPLETE_TRANSACTIONS] = {id:roles.COMPLETE_TRANSACTIONS, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.complete-transaction\", description:\"settings.ability.point-of-sale.complete-transaction\"};\n roles.permissions[roles.EDIT_COMMISSIONS] = {id:roles.EDIT_COMMISSIONS, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.edit-commission\", description:\"settings.ability.point-of-sale.edit-commission\"};\n roles.permissions[roles.VIEW_COMMISSION_EMPLOYEE] = {id:roles.VIEW_COMMISSION_EMPLOYEE, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.commissions.line-item.view-commission-employee\", description:\"settings.ability.point-of-sale.commissions.line-item.view-commission-employee\"};\n roles.permissions[roles.EDIT_COMMISSION_EMPLOYEE] = {id:roles.EDIT_COMMISSION_EMPLOYEE, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.commissions.line-item.edit-commission-employee\", description:\"settings.ability.point-of-sale.commissions.line-item.edit-commission-employee\"};\n roles.permissions[roles.VIEW_COMMISSION_STATUS] = {id:roles.VIEW_COMMISSION_STATUS, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.commissions.line-item.view-commission-status\", description:\"settings.ability.point-of-sale.commissions.line-item.view-commission-status\"};\n roles.permissions[roles.EDIT_COMMISSION_STATUS] = {id:roles.EDIT_COMMISSION_STATUS, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.commissions.line-item.edit-commission-status\", description:\"settings.ability.point-of-sale.commissions.line-item.edit-commission-status\"};\n roles.permissions[roles.REGISTERS] = {id:roles.REGISTERS, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.registers\", description:\"settings.ability.point-of-sale.registers\"};\n roles.permissions[roles.OPEN_AND_CLOSE_REGISTERS] = {id:roles.OPEN_AND_CLOSE_REGISTERS, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.open-and-close-registers\", description:\"settings.ability.point-of-sale.open-and-close-registers\"};\n roles.permissions[roles.MANUALLY_OPEN_REGISTERS] = {id:roles.MANUALLY_OPEN_REGISTERS, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.manually-open-registers\", description:\"settings.ability.point-of-sale.manually-open-registers\"};\n roles.permissions[roles.UPDATE_TRX_COMPLETED_DATE] = {id:roles.UPDATE_TRX_COMPLETED_DATE, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.update-completed-date\", description:\"settings.ability.point-of-sale.update-completed-date\"};\n roles.permissions[roles.UPDATE_TRX_ZERO_OUT_DATE] = {id:roles.UPDATE_TRX_ZERO_OUT_DATE, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.update-zero-out-date\", description:\"settings.ability.point-of-sale.update-zero-out-date\"};\n roles.permissions[roles.REQUEST_CARD_INFO] = {id:roles.REQUEST_CARD_INFO, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.request-card-info\", description:\"settings.ability.request-card-info\"};\n roles.permissions[roles.PERMISSION_TO_APPROVE_REQUESTED_PAYMENT_UPDATES] = {id:roles.PERMISSION_TO_APPROVE_REQUESTED_PAYMENT_UPDATES, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.permission-to-approve-requested-payment-updates\", description:\"settings.ability.permission-to-approve-requested-payment-updates\"};\n\n roles.permissions[roles.ADD_ITEM_ADD_ON] = {id:roles.ADD_ITEM_ADD_ON, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.add-on.add-item-add-on\", description:\"settings.ability.point-of-sale.add-on.add-item-add-on\"};\n roles.permissions[roles.SELECT_ITEM_ADD_ON] = {id:roles.SELECT_ITEM_ADD_ON, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.add-on.select-item-add-on\", description:\"settings.ability.point-of-sale.add-on.select-item-add-on\"};\n roles.permissions[roles.EDIT_ITEM_ADD_ON_NOTE] = {id:roles.EDIT_ITEM_ADD_ON_NOTE, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.add-on.edit-item-add-on-note\", description:\"settings.ability.point-of-sale.add-on.edit-item-add-on-note\"};\n roles.permissions[roles.EDIT_ITEM_ADD_ON_DESC] = {id:roles.EDIT_ITEM_ADD_ON_DESC, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.add-on.edit-item-add-on-desc\", description:\"settings.ability.point-of-sale.add-on.edit-item-add-on-desc\"};\n roles.permissions[roles.EDIT_ITEM_ADD_ON_PRICE] = {id:roles.EDIT_ITEM_ADD_ON_PRICE, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.add-on.edit-item-add-on-price\", description:\"settings.ability.point-of-sale.add-on.edit-item-add-on-price\"};\n roles.permissions[roles.REMOVE_ITEM_ADD_ON] = {id:roles.REMOVE_ITEM_ADD_ON, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.add-on.remove-item-add-on\", description:\"settings.ability.point-of-sale.add-on.remove-item-add-on\"};\n roles.permissions[roles.TRX_ITEM_ADD_ON_REQUIRED] = {id:roles.TRX_ITEM_ADD_ON_REQUIRED, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"settings.role.add-on.trx-required-item-add-on\", description:\"settings.ability.point-of-sale.add-on.trx-required-item-add-on\"};\n\n roles.QUOTES = \"QUOTES\";\n roles.EDIT_QUOTES = \"EDIT_QUOTES\";\n roles.VIEW_QUOTES = \"VIEW_QUOTES\";\n roles.SEARCH_QUOTES = \"SEARCH_QUOTES\";\n roles.DELETE_QUOTES = \"DELETE_QUOTES\";\n roles.VOID_QUOTES = \"VOID_QUOTES\";\n roles.ADD_QUOTE_ITEM_ADD_ON = \"ADD_QUOTE_ITEM_ADD_ON\";\n roles.EDIT_QUOTE_ITEM_ADD_ON_NOTE = \"EDIT_QUOTE_ITEM_ADD_ON_NOTE\";\n roles.EDIT_QUOTE_ITEM_ADD_ON_DESC = \"EDIT_QUOTE_ITEM_ADD_ON_DESC\";\n roles.EDIT_QUOTE_ITEM_ADD_ON_PRICE = \"EDIT_QUOTE_ITEM_ADD_ON_PRICE\";\n roles.REMOVE_QUOTE_ITEM_ADD_ON = \"REMOVE_QUOTE_ITEM_ADD_ON\";\n roles.QUOTE_ITEM_ADD_ON_REQUIRED = \"QUOTE_ITEM_ADD_ON_REQUIRED\";\n roles.SELECT_QUOTE_ITEM_ADD_ON = \"SELECT_QUOTE_ITEM_ADD_ON\";\n roles.CONVERT_QUOTES = \"CONVERT_QUOTES\";\n roles.DUPLICATE_QUOTES = \"DUPLICATE_QUOTES\";\n\n roles.permissions[roles.QUOTES] = {id:roles.QUOTES, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.create-quotes\", description:\"settings.ability.quotes.create-quotes\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.EDIT_QUOTES] = {id:roles.EDIT_QUOTES, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.edit-quotes\", description:\"settings.ability.quotes.edit-quotes\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.VIEW_QUOTES] = {id:roles.VIEW_QUOTES, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.view-quotes\", description:\"settings.ability.quotes.view-quotes\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.SEARCH_QUOTES] = {id:roles.SEARCH_QUOTES, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.search-quotes\", description:\"settings.ability.quotes.search-quotes\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.DELETE_QUOTES] = {id:roles.DELETE_QUOTES, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.delete-quotes\", description:\"settings.ability.quotes.delete-quotes\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.VOID_QUOTES] = {id:roles.VOID_QUOTES, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.void-quotes\", description:\"settings.ability.quotes.void-quotes\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.ADD_QUOTE_ITEM_ADD_ON] = {id:roles.ADD_QUOTE_ITEM_ADD_ON, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.add-quote-item-add-on\", description:\"settings.ability.quotes.add-quote-item-add-on\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.EDIT_QUOTE_ITEM_ADD_ON_NOTE] = {id:roles.EDIT_QUOTE_ITEM_ADD_ON_NOTE, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.edit-quote-item-add-on-note\", description:\"settings.ability.quotes.edit-quote-item-add-on-note\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.EDIT_QUOTE_ITEM_ADD_ON_DESC] = {id:roles.EDIT_QUOTE_ITEM_ADD_ON_DESC, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.edit-quote-item-add-on-desc\", description:\"settings.ability.quotes.edit-quote-item-add-on-desc\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.REMOVE_QUOTE_ITEM_ADD_ON] = {id:roles.REMOVE_QUOTE_ITEM_ADD_ON, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.remove-quote-item-add-on\", description:\"settings.ability.quotes.remove-quote-item-add-on\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.EDIT_QUOTE_ITEM_ADD_ON_PRICE] = {id:roles.EDIT_QUOTE_ITEM_ADD_ON_PRICE, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.edit-quote-item-add-on-price\", description:\"settings.ability.quotes.edit-quote-item-add-on-price\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.QUOTE_ITEM_ADD_ON_REQUIRED] = {id:roles.QUOTE_ITEM_ADD_ON_REQUIRED, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.quote-item-add-on-required\", description:\"settings.ability.quotes.quote-item-add-on-required\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.SELECT_QUOTE_ITEM_ADD_ON] = {id:roles.SELECT_QUOTE_ITEM_ADD_ON, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.select-quote-item-add-on\", description:\"settings.ability.quotes.select-quote-item-add-on\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.CONVERT_QUOTES] = {id:roles.CONVERT_QUOTES, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.convert-quotes\", description:\"settings.ability.quotes.convert-quotes\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.DUPLICATE_QUOTES] = {id:roles.DUPLICATE_QUOTES, groupName: roles.groups[roles.GROUP_QUOTES].label, groupId:roles.GROUP_QUOTES, label:\"settings.role.quotes.duplicate-quotes\", description:\"settings.ability.quotes.duplicate-quotes\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n\n //roles.permissions[roles.PERMISSION_TO_REQUEST_PAYMENT_PLAN_CREATION] = {id:roles.PERMISSION_TO_REQUEST_PAYMENT_PLAN_CREATION, groupName: roles.groups[roles.GROUP_POS].label, groupId:roles.GROUP_POS, label:\"PERMISSION_TO_REQUEST_PAYMENT_PLAN_CREATION\", description:\"PERMISSION_TO_REQUEST_PAYMENT_PLAN_CREATION\"};\n\n roles.ADD_PAYMENT_PLAN_TEMPLATES = \"ADD_PAYMENT_PLAN_TEMPLATES\";\n roles.EDIT_PAYMENT_PLAN_TEMPLATES = \"EDIT_PAYMENT_PLAN_TEMPLATES\";\n roles.DELETE_PAYMENT_PLAN_TEMPLATES = \"DELETE_PAYMENT_PLAN_TEMPLATES\";\n roles.CREATE_PAYMENT_PLAN = \"CREATE_PAYMENT_PLAN\";\n roles.VIEW_PAYMENT_PLAN = \"VIEW_PAYMENT_PLAN\";\n roles.EDIT_PAYMENT_PLAN = \"EDIT_PAYMENT_PLAN\";\n roles.EDIT_PAYMENT_PLAN_INSTALLMENT = \"EDIT_PAYMENT_PLAN_INSTALLMENT\";\n roles.CHARGE_PAYMENT_PLAN = \"CHARGE_PAYMENT_PLAN\";\n roles.VIEW_PAYMENT_PLAN_SEARCH = \"VIEW_PAYMENT_PLAN_SEARCH\";\n roles.DELETE_PAYMENT_PLAN_SIGNATURE = \"DELETE_PAYMENT_PLAN_SIGNATURE\";\n roles.DELETE_PAYMENT_PLAN = \"DELETE_PAYMENT_PLAN\";\n\n roles.permissions[roles.ADD_PAYMENT_PLAN_TEMPLATES] = {id:roles.ADD_PAYMENT_PLAN_TEMPLATES, groupName: roles.groups[roles.GROUP_PAYMENT_PLANS].label, groupId:roles.GROUP_PAYMENT_PLANS, label:\"settings.role.payment-plans.add-payment-plan-templates\", description:\"settings.ability.payment-plans.add-payment-plan-templates\"};\n roles.permissions[roles.EDIT_PAYMENT_PLAN_TEMPLATES] = {id:roles.EDIT_PAYMENT_PLAN_TEMPLATES, groupName: roles.groups[roles.GROUP_PAYMENT_PLANS].label, groupId:roles.GROUP_PAYMENT_PLANS, label:\"settings.role.payment-plans.edit-payment-plan-templates\", description:\"settings.ability.payment-plans.edit-payment-plan-templates\"};\n roles.permissions[roles.DELETE_PAYMENT_PLAN_TEMPLATES] = {id:roles.DELETE_PAYMENT_PLAN_TEMPLATES, groupName: roles.groups[roles.GROUP_PAYMENT_PLANS].label, groupId:roles.GROUP_PAYMENT_PLANS, label:\"settings.role.payment-plans.delete-payment-plan-templates\", description:\"settings.ability.payment-plans.delete-payment-plan-templates\"};\n roles.permissions[roles.CREATE_PAYMENT_PLAN] = {id:roles.CREATE_PAYMENT_PLAN, groupName: roles.groups[roles.GROUP_PAYMENT_PLANS].label, groupId:roles.GROUP_PAYMENT_PLANS, label:\"settings.role.payment-plans.add-payment-plan\", description:\"settings.ability.payment-plans.add-payment-plan\"};\n roles.permissions[roles.VIEW_PAYMENT_PLAN] = {id:roles.VIEW_PAYMENT_PLAN, groupName: roles.groups[roles.GROUP_PAYMENT_PLANS].label, groupId:roles.GROUP_PAYMENT_PLANS, label:\"settings.role.payment-plans.view-payment-plan\", description:\"settings.ability.payment-plans.view-payment-plan\"};\n roles.permissions[roles.EDIT_PAYMENT_PLAN] = {id:roles.EDIT_PAYMENT_PLAN, groupName: roles.groups[roles.GROUP_PAYMENT_PLANS].label, groupId:roles.GROUP_PAYMENT_PLANS, label:\"settings.role.payment-plans.edit-payment-plan\", description:\"settings.ability.payment-plans.edit-payment-plan\"};\n roles.permissions[roles.EDIT_PAYMENT_PLAN_INSTALLMENT] = {id:roles.EDIT_PAYMENT_PLAN_INSTALLMENT, groupName: roles.groups[roles.GROUP_PAYMENT_PLANS].label, groupId:roles.GROUP_PAYMENT_PLANS, label:\"settings.role.payment-plans.edit-payment-plan-installment\", description:\"settings.ability.payment-plans.edit-payment-plan-installment\"};\n roles.permissions[roles.CHARGE_PAYMENT_PLAN] = {id:roles.CHARGE_PAYMENT_PLAN, groupName: roles.groups[roles.GROUP_PAYMENT_PLANS].label, groupId:roles.GROUP_PAYMENT_PLANS, label:\"settings.role.payment-plans.charge-payment-plan\", description:\"settings.ability.payment-plans.charge-payment-plan\"};\n roles.permissions[roles.VIEW_PAYMENT_PLAN_SEARCH] = {id:roles.VIEW_PAYMENT_PLAN_SEARCH, groupName: roles.groups[roles.GROUP_PAYMENT_PLANS].label, groupId:roles.GROUP_PAYMENT_PLANS, label:\"settings.role.payment-plans.view-payment-plan-search\", description:\"settings.ability.payment-plans.view-payment-plan-search\"};\n roles.permissions[roles.DELETE_PAYMENT_PLAN_SIGNATURE] = {id:roles.DELETE_PAYMENT_PLAN_SIGNATURE, groupName: roles.groups[roles.GROUP_PAYMENT_PLANS].label, groupId:roles.GROUP_PAYMENT_PLANS, label:\"settings.role.payment-plans.delete-payment-plan-signature\", description:\"settings.ability.payment-plans.delete-payment-plan-signature\"};\n roles.permissions[roles.DELETE_PAYMENT_PLAN] = {id:roles.DELETE_PAYMENT_PLAN, groupName: roles.groups[roles.GROUP_PAYMENT_PLANS].label, groupId:roles.GROUP_PAYMENT_PLANS, label:\"settings.role.payment-plans.delete-payment-plan\", description:\"settings.ability.payment-plans.delete-payment-plan\"};\n\n roles.SMART_VIEW = \"SMART_VIEW\";\n roles.SALES_REPORTS = \"SALES_REPORTS\";\n roles.MERCHANDISING_REPORTS = \"MERCHANDISING_REPORTS\";\n roles.PURCHASING_REPORTS = \"PURCHASING_REPORTS\";\n roles.ASSOCIATE_REPORTS = \"ASSOCIATE_REPORTS\";\n roles.CONTACT_REPORTS = \"CONTACT_REPORTS\";\n roles.ACTIVITY_REPORTS = \"ACTIVITY_REPORTS\";\n roles.MULTI_LOCATION_REPORTS = \"MULTI_LOCATION_REPORTS\";\n roles.AUDIT_LOGS = \"AUDIT_LOGS\";\n roles.BL_PAY_REPORTS = \"BL_PAY_REPORTS\";\n roles.NF525_REPORTS = \"NF525_REPORTS\";\n\n roles.permissions[roles.SMART_VIEW] = {id:roles.SMART_VIEW, groupName: roles.groups[roles.GROUP_REPORTS].label, groupId:roles.GROUP_REPORTS, label:\"interface.smart-view\", description:\"settings.ability.reports.smart-view\"};\n roles.permissions[roles.MERCHANDISING_REPORTS] = {id:roles.MERCHANDISING_REPORTS, groupName: roles.groups[roles.GROUP_REPORTS].label, groupId:roles.GROUP_REPORTS, label:\"settings.role.merchandising-reports\", description:\"settings.ability.reports.show-merchandising-information\"};\n roles.permissions[roles.SALES_REPORTS] = {id:roles.SALES_REPORTS, groupName: roles.groups[roles.GROUP_REPORTS].label, groupId:roles.GROUP_REPORTS, label:\"reports.sales\", description:\"settings.ability.reports.show-sales-performance\"};\n roles.permissions[roles.PURCHASING_REPORTS] = {id:roles.PURCHASING_REPORTS, groupName: roles.groups[roles.GROUP_REPORTS].label, groupId:roles.GROUP_REPORTS, label:\"reports.purchasing\", description:\"settings.ability.reports.show-purchasing-information\"};\n roles.permissions[roles.ASSOCIATE_REPORTS] = {id:roles.ASSOCIATE_REPORTS, groupName: roles.groups[roles.GROUP_REPORTS].label, groupId:roles.GROUP_REPORTS, label:\"reports.associate\", description:\"settings.ability.reports.show-associate-information\"};\n roles.permissions[roles.CONTACT_REPORTS] = {id:roles.CONTACT_REPORTS, groupName: roles.groups[roles.GROUP_REPORTS].label, groupId:roles.GROUP_REPORTS, label:\"reports.contact\", description:\"settings.ability.reports.show-contact-information\"};\n roles.permissions[roles.ACTIVITY_REPORTS] = {id:roles.ACTIVITY_REPORTS, groupName: roles.groups[roles.GROUP_REPORTS].label, groupId:roles.GROUP_REPORTS, label:\"reports.activity\", description:\"settings.ability.reports.show-activity-center-information\"};\n roles.permissions[roles.MULTI_LOCATION_REPORTS] = {id:roles.MULTI_LOCATION_REPORTS, groupName: roles.groups[roles.GROUP_REPORTS].label, groupId:roles.GROUP_REPORTS, label:\"reports.activity.multi-location-reports\", description:\"settings.ability.reports.multi-location-reports\"};\n roles.permissions[roles.AUDIT_LOGS] = {id:roles.AUDIT_LOGS, groupName: roles.groups[roles.GROUP_REPORTS].label, groupId:roles.GROUP_REPORTS, label:\"reports.audit-logs\", description:\"settings.ability.reports.audit-logs\"};\n roles.permissions[roles.BL_PAY_REPORTS] = {id:roles.BL_PAY_REPORTS, groupName: roles.groups[roles.GROUP_REPORTS].label, groupId:roles.GROUP_REPORTS, label:\"reports.bl-pay\", description:\"settings.ability.reports.bl-pay\"};\n roles.permissions[roles.NF525_REPORTS] = {id:roles.NF525_REPORTS, groupName: roles.groups[roles.GROUP_REPORTS].label, groupId:roles.GROUP_REPORTS, label:\"reports.nf525\", description:\"settings.ability.reports.nf525\", locale:[\"FR\"]};\n\n roles.COMPANY_PROFILE = \"COMPANY_PROFILE\";\n roles.CLIENT_PORTAL_SETTINGS = \"CLIENT_PORTAL_SETTINGS\";\n roles.ACCOUNT_SETTINGS = \"ACCOUNT_SETTINGS\";\n roles.USERS = \"USERS\";\n roles.VIEW_TIME_PUNCHES = \"VIEW_TIME_PUNCHES\";\n roles.ADD_AND_EDIT_TIME_PUNCHES = \"ADD_AND_EDIT_TIME_PUNCHES\";\n roles.DELETE_TIME_PUNCHES = \"DELETE_TIME_PUNCHES\";\n roles.CAN_AUTHORIZE_DEVICES = \"CAN_AUTHORIZE_DEVICES\";\n roles.CAN_BYPASS_AUTHORIZED_DEVICES = \"CAN_BYPASS_AUTHORIZED_DEVICES\";\n roles.SETTINGS_CC = \"SETTINGS_CC\";\n roles.SETTINGS_AC = \"SETTINGS_AC\";\n roles.SETTINGS_INVENTORY = \"SETTINGS_INVENTORY\";\n roles.SETTINGS_POS = \"SETTINGS_POS\";\n roles.SETTINGS_QUOTES = \"SETTINGS_QUOTES\";\n roles.SETTINGS_PAYMENT_PLANS = \"SETTINGS_PAYMENT_PLANS\";\n roles.SETTINGS_PURCHASING = \"SETTINGS_PURCHASING\";\n roles.SMART_FLOWS = \"SMART_FLOWS\";\n roles.SETTINGS_EMAIL = \"SETTINGS_EMAIL\";\n roles.MESSAGING = \"MESSAGING\";\n roles.WEBSITE_FORMS = \"WEBSITE_FORMS\";\n roles.CUSTOM_FORMS = \"CUSTOM_FORMS\";\n\n // roles.CUSTOM_FORMS_LOOK_FEEL = \"CUSTOM_FORMS_LOOK_FEEL\";\n // roles.CUSTOM_FORMS_GENERAL = \"CUSTOM_FORMS_DEFAULT_FIELDS\";\n // roles.CUSTOM_FORMS_BASIC = \"CUSTOM_FORMS_BASIC\";\n // roles.CUSTOM_FORMS_DEFAULT_FIELDS = \"CUSTOM_FORMS_DEFAULT_FIELDS\";\n // roles.CUSTOM_FORMS_CUSTOM_FIELDS = \"CUSTOM_FORMS_CUSTOM_FIELDS\";\n // roles.CUSTOM_FORMS_ADV_APPT_ADD = \"CUSTOM_FORMS_ADV_APPT_ADD\";\n // roles.CUSTOM_FORMS_ADV_APPT_EDIT = \"CUSTOM_FORMS_ADV_APPT_EDIT\";\n // roles.CUSTOM_FORMS_ADV_APPT_VIEW = \"CUSTOM_FORMS_ADV_APPT_VIEW\";\n // roles.CUSTOM_FORMS_ADV_APPT_REMOVE = \"CUSTOM_FORMS_ADV_APPT_REMOVE\";\n\n roles.SUPPORT = \"SUPPORT\";\n\n roles.permissions[roles.COMPANY_PROFILE] = {id:roles.COMPANY_PROFILE, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.company-profile\", description:\"settings.ability.settings.manage-company-profile\"};\n roles.permissions[roles.CLIENT_PORTAL_SETTINGS] = {id:roles.CLIENT_PORTAL_SETTINGS, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.role.client-portal-settings\", description:\"settings.ability.client-portal.client-portal-settings\"};\n roles.permissions[roles.ACCOUNT_SETTINGS] = {id:roles.ACCOUNT_SETTINGS, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.account-settings\", description:\"settings.ability.settings.manage-your-account\"};\n roles.permissions[roles.USERS] = {id:roles.USERS, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.users\", description:\"settings.ability.settings.view/create/edit-users-roles\"};\n roles.permissions[roles.VIEW_TIME_PUNCHES] = {id:roles.VIEW_TIME_PUNCHES, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.role.view-time-punches\", description:\"settings.ability.settings.view-time-punches\"};\n roles.permissions[roles.ADD_AND_EDIT_TIME_PUNCHES] = {id:roles.ADD_AND_EDIT_TIME_PUNCHES, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.role.add/edit-time-punches\", description:\"settings.ability.settings.add/edit-time-punches\"};\n roles.permissions[roles.DELETE_TIME_PUNCHES] = {id:roles.DELETE_TIME_PUNCHES, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.role.delete-time-punches\", description:\"settings.ability.settings.delete-time-punches\"};\n roles.permissions[roles.TIME_OFF] = {id:roles.TIME_OFF, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.role.time-off\", description:\"settings.ability.home.to-view-time-off\"};\n roles.permissions[roles.CAN_AUTHORIZE_DEVICES] = {id:roles.CAN_AUTHORIZE_DEVICES, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.role.can-authorize-devices\", description:\"settings.ability.settings.to-authorize-new-devices\"};\n roles.permissions[roles.CAN_BYPASS_AUTHORIZED_DEVICES] = {id:roles.CAN_BYPASS_AUTHORIZED_DEVICES, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.role.can-bypass-authorize-devices\", description:\"settings.ability.settings.can-bypass-authorize-devices\"};\n roles.permissions[roles.SETTINGS_CC] = {id:roles.SETTINGS_CC, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.contacts\", description:\"settings.ability.settings.manage-contacts-module\"};\n roles.permissions[roles.SETTINGS_AC] = {id:roles.SETTINGS_AC, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.activities\", description:\"settings.ability.settings.manage-tasks-appts-fitting-rooms\"};\n roles.permissions[roles.SETTINGS_INVENTORY] = {id:roles.SETTINGS_INVENTORY, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"item.inventory\", description:\"settings.ability.settings.manage-inventory\"};\n roles.permissions[roles.SETTINGS_POS] = {id:roles.SETTINGS_POS, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.point-of-sale\", description:\"settings.ability.settings.manage-point-of-sale\"};\n roles.permissions[roles.SETTINGS_QUOTES] = {id:roles.SETTINGS_QUOTES, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"quote.quotes\", description:\"settings.ability.quotes.view-quote-settings\", validate:[{ type: '$rootScope', field: 'isQuoteEnabled'}]};\n roles.permissions[roles.SETTINGS_PAYMENT_PLANS] = {id:roles.SETTINGS_PAYMENT_PLANS, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.role.payment-plans.view-payment-plan-settings\", description:\"settings.ability.payment-plans.view-payment-plan-settings\"};\n roles.permissions[roles.SETTINGS_PURCHASING] = {id:roles.SETTINGS_PURCHASING, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.purchasing\", description:\"settings.ability.settings.manage-purchasing-module\"};\n roles.permissions[roles.SMART_FLOWS] = {id:roles.SMART_FLOWS, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"transaction.smart-flows\", description:\"settings.ability.settings.view/create/edit-smart-flows\"};\n roles.permissions[roles.MESSAGING] = {id:roles.MESSAGING, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.messaging\", description:\"settings.ability.settings.view/edit-messaging\"};\n roles.permissions[roles.WEBSITE_FORMS] = {id:roles.WEBSITE_FORMS, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.website-forms\", description:\"settings.ability.settings.view/edit-website-forms\"};\n roles.permissions[roles.CUSTOM_FORMS] = {id:roles.CUSTOM_FORMS, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.custom-forms\", description:\"settings.ability.settings.view/edit-custom-forms\"};\n\n // roles.permissions[roles.CUSTOM_FORMS_LOOK_FEEL] = {id:roles.CUSTOM_FORMS_LOOK_FEEL, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.custom-forms-look-feel\", description:\"settings.ability.settings.view/edit-custom-forms-look-feel\"};\n // roles.permissions[roles.CUSTOM_FORMS_GENERAL] = {id:roles.CUSTOM_FORMS_GENERAL, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.custom-forms-general\", description:\"settings.ability.settings.view/edit-custom-forms-general\"};\n // roles.permissions[roles.CUSTOM_FORMS_BASIC] = {id:roles.CUSTOM_FORMS_BASIC, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.custom-forms-basic\", description:\"settings.ability.settings.view/edit-custom-forms-basic\"};\n // roles.permissions[roles.CUSTOM_FORMS_DEFAULT_FIELDS] = {id:roles.CUSTOM_FORMS_DEFAULT_FIELDS, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.custom-forms-default-field\", description:\"settings.ability.settings.view/edit-custom-forms-default-field\"};\n // roles.permissions[roles.CUSTOM_FORMS_CUSTOM_FIELDS] = {id:roles.CUSTOM_FORMS_CUSTOM_FIELDS, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.custom-forms-custom-field\", description:\"settings.ability.settings.view/edit-custom-forms-custom-field\"};\n // roles.permissions[roles.CUSTOM_FORMS_ADV_APPT_ADD] = {id:roles.CUSTOM_FORMS_ADV_APPT_ADD, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.custom-forms-adv-appt-type-add\", description:\"settings.ability.settings.view/edit-custom-forms-adv-appt-type-add\"};\n // roles.permissions[roles.CUSTOM_FORMS_ADV_APPT_EDIT] = {id:roles.CUSTOM_FORMS_ADV_APPT_EDIT, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.custom-forms-adv-appt-type-edit\", description:\"settings.ability.settings.view/edit-custom-forms-adv-appt-type-edit\"};\n // roles.permissions[roles.CUSTOM_FORMS_ADV_APPT_VIEW] = {id:roles.CUSTOM_FORMS_ADV_APPT_VIEW, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.custom-forms-adv-appt-type-view\", description:\"settings.ability.settings.view/edit-custom-forms-adv-appt-type-view\"};\n // roles.permissions[roles.CUSTOM_FORMS_ADV_APPT_REMOVE] = {id:roles.CUSTOM_FORMS_ADV_APPT_REMOVE, groupName: roles.groups[roles.GROUP_ADMINISTRATION].label, groupId:roles.GROUP_ADMINISTRATION, label:\"settings.header.custom-forms-adv-appt-type-remove\", description:\"settings.ability.settings.view/edit-custom-forms-adv-appt-type-remove\"};\n \n roles.REGISTRY = \"REGISTRY\";\n roles.DELETE_REG_ITEM = \"DELETE_REG_ITEM\";\n roles.QUICK_ADD_EVENT_LOCATION = \"QUICK_ADD_EVENT_LOCATION\";\n roles.permissions[roles.REGISTRY] = {id:roles.REGISTRY, groupName: roles.groups[roles.GROUP_REGISTRY].label, groupId:roles.GROUP_REGISTRY, label:\"settings.role.item-registry\", description:\"settings.ability.registry.view/create-items\"};\n roles.permissions[roles.DELETE_REG_ITEM] = {id:roles.DELETE_REG_ITEM, groupName: roles.groups[roles.GROUP_REGISTRY].label, groupId:roles.GROUP_REGISTRY, label:\"settings.role.delete-registered-items\", description:\"settings.ability.registry.delete-items\"};\n roles.permissions[roles.QUICK_ADD_EVENT_LOCATION] = {id:roles.QUICK_ADD_EVENT_LOCATION, groupName: roles.groups[roles.GROUP_REGISTRY].label, groupId:roles.GROUP_REGISTRY, label:\"settings.role.quick-add-event-location\", description:\"settings.ability.registry.add-locations-from-item-window\"};\n\n roles.MKT_VIEW_ACCESS = \"MKT_VIEW_ACCESS\";\n roles.MKT_FULL_ACCESS = \"MKT_FULL_ACCESS\";\n roles.permissions[roles.MKT_VIEW_ACCESS] = {id:roles.MKT_VIEW_ACCESS, groupName: roles.groups[roles.GROUP_MARKETPLACE].label, groupId:roles.GROUP_MARKETPLACE, label:\"settings.role.view-access\", description:\"settings.ability.marketplace.view-search\"};\n roles.permissions[roles.MKT_FULL_ACCESS] = {id:roles.MKT_FULL_ACCESS, groupName: roles.groups[roles.GROUP_MARKETPLACE].label, groupId:roles.GROUP_MARKETPLACE, label:\"settings.role.full-access\", description:\"settings.ability.marketplace.perform-advanced-functions\"};\n\n roles.REQUEST_MEASUREMENTS = \"REQUEST_MEASUREMENTS\";\n roles.REQUEST_PAYMENTS = \"REQUEST_PAYMENTS\";\n roles.REQUEST_SIGNATURES = \"REQUEST_SIGNATURES\";\n roles.EDIT_SHOW_ON_LOOKBOOK = \"EDIT_SHOW_ON_LOOKBOOK\";\n roles.permissions[roles.REQUEST_MEASUREMENTS] = {id:roles.REQUEST_MEASUREMENTS, groupName: roles.groups[roles.GROUP_CLIENT_PORTAL].label, groupId:roles.GROUP_CLIENT_PORTAL, label:\"settings.role.request-measurements\", description:\"settings.ability.client-portal.request-measurements\"};\n roles.permissions[roles.REQUEST_PAYMENTS] = {id:roles.REQUEST_PAYMENTS, groupName: roles.groups[roles.GROUP_CLIENT_PORTAL].label, groupId:roles.GROUP_CLIENT_PORTAL, label:\"settings.role.request-payments\", description:\"settings.ability.client-portal.request-payments\"};\n roles.permissions[roles.REQUEST_SIGNATURES] = {id:roles.REQUEST_SIGNATURES, groupName: roles.groups[roles.GROUP_CLIENT_PORTAL].label, groupId:roles.GROUP_CLIENT_PORTAL, label:\"settings.role.request-signatures\", description:\"settings.ability.client-portal.request-signatures\"};\n roles.permissions[roles.EDIT_SHOW_ON_LOOKBOOK] = {id:roles.EDIT_SHOW_ON_LOOKBOOK , groupName: roles.groups[roles.GROUP_CLIENT_PORTAL].label, groupId:roles.GROUP_CLIENT_PORTAL, label:\"settings.role.edit-show-on-lookbook\", description:\"settings.ability.client-portal.edit-show-on-lookbook\"};\n\n roles.CC_PROCESSING = \"CC_PROCESSING\";\n roles.ADD_MERCHANT_TRACK_EMP = \"ADD_MERCHANT_TRACK_EMP\";\n roles.EDIT_MERCHANT_TRACK_EMP = \"EDIT_MERCHANT_TRACK_EMP\";\n roles.DELETE_MERCHANT_TRACK_EMP = \"DELETE_MERCHANT_TRACK_EMP\";\n roles.QUICKBOOKS_EXPORT = \"QUICKBOOKS_EXPORT\";\n roles.TWILIO = \"TWILIO\";\n roles.MAIL_CHIMP = \"MAIL_CHIMP\";\n roles.TAX_JAR = \"TAX_JAR\";\n roles.FISKALY = \"FISKALY\";\n roles.CHAT_METER = \"CHAT_METER\";\n // roles.JFW = \"JFW\";\n roles.permissions[roles.CC_PROCESSING] = {id:roles.CC_PROCESSING, groupName: roles.groups[roles.GROUP_INTEGRATIONS].label, groupId:roles.GROUP_INTEGRATIONS, label:\"settings.role.cc-processing\", description:\"settings.ability.integrations.cc-processing\"};\n roles.permissions[roles.ADD_MERCHANT_TRACK_EMP] = {id:roles.ADD_MERCHANT_TRACK_EMP, groupName: roles.groups[roles.GROUP_INTEGRATIONS].label, groupId:roles.GROUP_INTEGRATIONS, label:\"settings.role.merchant-track-employee.add\", description:\"settings.ability.integrations.merchant-track-employee.add\", validate:[{ type: '$rootScope', field: 'isBLPayCustomer'}]};\n roles.permissions[roles.EDIT_MERCHANT_TRACK_EMP] = {id:roles.EDIT_MERCHANT_TRACK_EMP, groupName: roles.groups[roles.GROUP_INTEGRATIONS].label, groupId:roles.GROUP_INTEGRATIONS, label:\"settings.role.merchant-track-employee.edit\", description:\"settings.ability.integrations.merchant-track-employee.edit\", validate:[{ type: '$rootScope', field: 'isBLPayCustomer'}]};\n roles.permissions[roles.DELETE_MERCHANT_TRACK_EMP] = {id:roles.DELETE_MERCHANT_TRACK_EMP, groupName: roles.groups[roles.GROUP_INTEGRATIONS].label, groupId:roles.GROUP_INTEGRATIONS, label:\"settings.role.merchant-track-employee.delete\", description:\"settings.ability.integrations.merchant-track-employee.delete\", validate:[{ type: '$rootScope', field: 'isBLPayCustomer'}]};\n roles.permissions[roles.QUICKBOOKS_EXPORT] = {id:roles.QUICKBOOKS_EXPORT, groupName: roles.groups[roles.GROUP_INTEGRATIONS].label, groupId:roles.GROUP_INTEGRATIONS, label:\"settings.role.quickbooks\", description:\"settings.ability.quickbooks.quickbooks-export\"};\n roles.permissions[roles.TWILIO] = {id:roles.TWILIO, groupName: roles.groups[roles.GROUP_INTEGRATIONS].label, groupId:roles.GROUP_INTEGRATIONS, label:\"settings.role.twilio\", description:\"settings.ability.integrations.twilio\"};\n roles.permissions[roles.MAIL_CHIMP] = {id:roles.MAIL_CHIMP, groupName: roles.groups[roles.GROUP_INTEGRATIONS].label, groupId:roles.GROUP_INTEGRATIONS, label:\"settings.role.mail-chimp\", description:\"settings.ability.integrations.mail-chimp\"};\n roles.permissions[roles.TAX_JAR] = {id:roles.TAX_JAR, groupName: roles.groups[roles.GROUP_INTEGRATIONS].label, groupId:roles.GROUP_INTEGRATIONS, label:\"settings.role.tax-jar\", description:\"settings.ability.integrations.tax-jar\"};\n roles.permissions[roles.FISKALY] = {id:roles.FISKALY, groupName: roles.groups[roles.GROUP_INTEGRATIONS].label, groupId:roles.GROUP_INTEGRATIONS, label:\"settings.role.fiskaly\", description:\"settings.ability.integrations.fiskaly\", locale:[\"DE\", \"AUT\"]};\n roles.permissions[roles.CHAT_METER] = {id:roles.CHAT_METER, groupName: roles.groups[roles.GROUP_INTEGRATIONS].label, groupId:roles.GROUP_INTEGRATIONS, label:\"settings.role.chat-meter\", description:\"settings.ability.integrations.chat-meter\", locale:[\"US\"]};\n // roles.permissions[roles.JFW] = {id:roles.JFW, groupName: roles.groups[roles.GROUP_INTEGRATIONS].label, groupId:roles.GROUP_INTEGRATIONS, label:\"settings.role.jfw\", description:\"settings.ability.integrations.jfw\"};\n\n});\n\n","\ndefine('text!modules/appointment/appointment-search-typeahead-grid-directive/appointment-search-typeahead-grid.tpl.html',[],function () { return '
\\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
{{ appointment.typeDescription }}{{ appointment.contactName }}{{ appointment.contactEventDate | date:\\'mediumDate\\' }}{{ appointment.startDateTime | date:\\'short\\' }}{{ appointment.duration | durationToString }}
\\n \\n {{ pagination.page }}\\n \\n
\\n\\n
\\n
\\n';});\n\n","define('modules/common/enums-service',['angular'], function (angular) {\n 'use strict';\n\n angular.module('bl.enums', [])\n\n .constant('Enums', {\n statuses: {\n all: { description: 'enums.statuses.all', value: '' },\n active: { description: 'enums.statuses.active', value: 'A' },\n inactive: { description: 'enums.statuses.inactive', value: 'I' },\n pending: { description: 'enums.statuses.pending', value: 'P' },\n pendingAndComplete: { description: 'enums.statuses.pending-complete', value: 'P,C' },\n complete: { description: 'enums.statuses.complete', value: 'C' },\n voided: { description: 'enums.statuses.void', value: 'V' },\n returned: { description: 'enums.statuses.returned', value: 'R' },\n discontinued: { description: 'enums.statuses.discontinued', value: 'D' },\n error: { description: 'enums.statuses.error', value: 'E' },\n unpublished: { description: 'enums.statuses.unpublished', value: 'U' },\n published: { description: 'enums.statuses.published', value: 'B' },\n didNotShow: { description: 'enums.statuses.did-not-show', value: 'N' },\n canceled: { description: 'enums.statuses.canceled', value: 'L' },\n sent: { description: 'enums.statuses.sent', value: 'S' },\n received : { description: 'enums.statuses.received', value: 'R' },\n open: { description: 'enums.statuses.open', value: 'O' },\n closed: { description: 'enums.statuses.closed', value: 'C' },\n archived: { description: 'enums.statuses.archived', value: 'H' },\n unknown: { description: 'enums.statuses.unknown', value: '' },\n activeOrDiscontinued: { description: 'enums.statuses.active-or-discontinued', value: 'AD'},\n approved: { description: 'enums.statuses.approved', value: 'AP' },\n declined: { description: 'enums.statuses.declined', value: 'DE' },\n booked: { description: 'enums.statuses.booked', value: 'BO'},\n notBooked: { description: 'enums.statuses.not-booked', value: 'NB' },\n converted: { description: 'enums.statuses.converted', value: 'C' }\n },\n\n appointmentBlockDays: [\n { value: 0, description: \"common.none\" },\n { value: 1, description: \"settings.widgets.same-day\" },\n { value: 2, description: \"enums.days.2\" },\n { value: 3, description: \"enums.days.3\" },\n { value: 4, description: \"enums.days.4\" },\n { value: 5, description: \"enums.days.5\" },\n { value: 6, description: \"enums.days.6\" },\n { value: 7, description: \"enums.days.7\" },\n ],\n\n autoPayStatuses: {\n all: {value: '', description: \"common.all\"},\n yes: {value: 'Y', description: \"payment-plans.auto-pay\"}, //AutoPay\n no: {value: 'N', description: \"settings.payment-plans.manual\"} //Manual\n },\n\n bridalLivePayAdPhrases:[\n { id: 1, key: \"switch-and-save\", description: \"enums.bl-pay.ad-phrases.switch-and-save\" },\n { id: 2, key: \"auto-reconcile\", description: \"enums.bl-pay.ad-phrases.auto-reconcile\" },\n { id: 3, key: \"meet-and-beat\", description: \"enums.bl-pay.ad-phrases.meet-and-beat\" },\n { id: 4, key: \"client-portal\", description: \"enums.bl-pay.ad-phrases.client-portal\" },\n { id: 5, key: \"sign-contracts\", description: \"enums.bl-pay.ad-phrases.sign-contracts\" },\n { id: 6, key: \"one-company\", description: \"enums.bl-pay.ad-phrases.one-company\" },\n { id: 7, key: \"tips\", description: \"enums.bl-pay.ad-phrases.tips\" }\n ],\n\n bridalLivePayDevices:[\n // { value: '915', model: 'mx915', description: 'settings.merchant-account.modal.devices.verifone-mx915', purchaseType: 'L', warranty: 'tbd', qty: 0, dimensions: '225mm L × 182mm W × 56mm H', display:'4.3\" (480 × 272) color LCD', wifi: false, wired: true, signature: true, portable: false, signAgreements: true, touchscreen: true },\n { value: '925', model: 'mx925', description: 'settings.merchant-account.modal.devices.verifone-mx925', purchaseType: 'L', warranty: 'tbd', qty: 0, dimensions: '230mm L × 218mm W × 56mm H', display:'7\" WVGA (800 × 480) color LCD', wifi: false, wired: true, signature: true, portable: false, signAgreements: true, touchscreen: true },\n // { value: '320', model: 'ipp320', description: 'settings.merchant-account.modal.devices.ingenico-ipp320', purchaseType: 'L', warranty: 'tbd', qty: 0, dimensions: 'Medium!', display: '128x64 graphical LCD, white backlit', wifi: false, wired: true, signature: false, portable: false, signAgreements: false, touchscreen: false },\n //{ value: '4', model: 'ismp4', description: 'settings.merchant-account.modal.devices.ingenico-ismp4', purchaseType: 'L', warranty: 'tbd', qty: 0, dimensions: 'Small!', display: '2.8” backlit color display', wifi: true, wired: true, signature: false, portable: true, signAgreements: false, touchscreen: false },\n { value: '2500', model: 'link2500', description: 'settings.merchant-account.modal.devices.ingenico-link-2500', purchaseType: 'L', warranty: 'tbd', qty: 0, dimensions: 'Small!', display: '2.4” backlit color display', wifi: true, wired: true, signature: false, portable: true, signAgreements: false, touchscreen: false },\n { value: '7000', model: 'l7000', description: 'settings.merchant-account.modal.devices.ingenico-lane-7000', purchaseType: 'L', warranty: 'tbd', qty: 0, dimensions: '180 x 152 x 35,2 mm', display:'7.44\" x 5.89\" x 1.38\" color LCD', wifi: false, wired: true, signature: true, portable: false, signAgreements: true, touchscreen: true },\n { value: '5000', model: 'm5000', description: 'settings.merchant-account.modal.devices.ingenico-move-5000', purchaseType: 'L', warranty: 'tbd', qty: 0, dimensions: '6.6x3.1x2.2\" (169x78x57 mm)', display:'3.5\" backlit, HVGA', wifi: true, wired: true, signature: false, portable: true, signAgreements: false, touchscreen: true },\n { value: '77', model: 'a77', description: 'settings.merchant-account.modal.devices.pax-a-77', purchaseType: 'L', warranty: 'tbd', qty: 0, dimensions: '158.8 * 76.4 * 17.8 mm', display:'5.5\\'\\' IPS WXGA 720 x 1440 Pixels Multi-Point Capacitive HD Touch Screen', wifi: true, wired: true, signature: false, portable: true, signAgreements: false, touchscreen: true },\n { value: '920', model: 'a920_pro', description: 'settings.merchant-account.modal.devices.pax-a-920-pro', purchaseType: 'L', warranty: 'tbd', qty: 0, dimensions: 'L x W x H (inches): 7.02 x 3.07 x 2.13', display:'5.5” (720 x 1440) IPS', wifi: true, wired: true, signature: false, portable: true, signAgreements: false, touchscreen: true },\n { value: '8', model: 'aries8', description: 'settings.merchant-account.modal.devices.pax-aries-8', purchaseType: 'L', warranty: 'tbd', qty: 0, dimensions: '205.7 x 170.2 x 15.2mm,', display:'8\\'\\' IPS WXGA 1280 x 800 Pixels Multi-Point Capacitive Touch Screen', wifi: true, wired: true, signature: true, portable: false, signAgreements: true, touchscreen: true }\n ],\n\n bridalLivePayMerchantTrackClaims: [\n { value: 1, key: 'TRANSACTION_SEARCH', label: 'Transaction Search' },\n // { value: 2, key: 'REVERSE_OPEN_TRANSACTIONS', label: 'Void' },\n // { value: 3, key: 'REVERSE_SETTLED_TRANSACTIONS', label: 'Refund' },\n { value: 23, key:'VOID_AND_REFUND', label:'Void/Refund'},\n { value: 4, key: 'REPORTING', label: 'Reporting' },\n // { value: 5, key: 'USER_MANAGEMENT', label: 'User Management' },\n { value: 6, key: 'VIRTUAL_TERMINAL', label: 'Virtual Terminal' },\n { value: 7, key: 'TERMINAL_MANAGEMENT', label: 'Terminal Management' },\n { value: 10, key: 'MERCHANT_CAPITAL_ADVANCE', label: 'Merchant Capital Advance' }\n // { value: 8, key: 'PCI_MANAGEMENT', label: 'PCI Management' }\n ],\n\n bridalLivePayStatuses:[\n { description:'enums.bl-pay.bridallive-pay-statuses.unknown', value:'0' },\n { description:'enums.bl-pay.bridallive-pay-statuses.failed', value:'1' },\n { description:'enums.bl-pay.bridallive-pay-statuses.authorized', value:'2' },\n { description:'enums.bl-pay.bridallive-pay-statuses.partially-reversed', value:'3' },\n { description:'enums.bl-pay.bridallive-pay-statuses.voided', value:'4' },\n { description:'enums.bl-pay.bridallive-pay-statuses.batched', value:'5' },\n { description:'enums.bl-pay.bridallive-pay-statuses.partially-refunded', value:'6' },\n { description:'enums.bl-pay.bridallive-pay-statuses.refunded', value:'7' }\n ],\n\n bridalLivePayStatusesFilter: [\n // { description:'enums.bl-pay.bridallive-pay-statuses-filter.all', value:'0' },\n { description:'enums.bl-pay.bridallive-pay-statuses-filter.successful', value:'1' },\n { description:'enums.bl-pay.bridallive-pay-statuses-filter.failed', value:'2' }\n ],\n\n bridalLivePayDateFilter: [\n { description:'enums.bl-pay.bridallive-pay-date-filter.created-date', value:'0' },\n { description:'enums.bl-pay.bridallive-pay-date-filter.deposit-received-date', value: '1' },\n { description:'enums.bl-pay.bridallive-pay-date-filter.capture-date', value: '2' },\n { description:'enums.bl-pay.bridallive-pay-date-filter.issuer-settlement-date', value: '3' }\n ],\n\n bridalLivePayFundedFilter: [\n { description:'common.all', value:'' },\n { description:'common.funded', value:'0' },\n { description:'common.not-funded', value: '1' }\n ],\n\n bridalLivePayCardEntryContexts : [\n { description:'enums.bl-pay.bridallive-pay-card-entry-contexts.not-applicable', value:'0' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-contexts.point-of-sale-card-present', value:'1' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-contexts.point-of-sale-card-not-present-mail-order', value:'3' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-contexts.point-of-sale-card-not-present-phone-order', value:'4' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-contexts.web-consumer-initiated', value:'5' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-contexts.web-merchant-entered-mail-order', value:'6' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-contexts.web-merchant-entered-phone-order', value:'7' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-contexts.ivr', value:'8' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-contexts.card-on-file-recurring', value:'9' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-contexts.card-on-file-installment', value:'10' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-contexts.card-on-file-consumer-initiated', value:'11' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-contexts.card-on-file-merchant-initiated-mail-order', value:'12' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-contexts.card-on-file-merchant-initiated-phone-order', value:'13' }\n ],\n\n bridalLivePayCardEntryMethods : [\n { description:'enums.bl-pay.bridallive-pay-card-entry-methods.not-applicable', value: '0' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-methods.swipe', value: '1' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-methods.emv', value: '2' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-methods.contact-less', value: '3' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-methods.manual-entry-card-not-present', value: '4' },\n { description:'enums.bl-pay.bridallive-pay-card-entry-methods.manual-entry-card-present', value: '5' }\n ],\n\n bridalLivePayProcessingNetworks : [\n { description:'enums.bl-pay.bridallive-pay-processing-networks.none' , value: '0' },\n { description:'enums.bl-pay.bridallive-pay-processing-networks.credit' , value: '1' },\n { description:'enums.bl-pay.bridallive-pay-processing-networks.debit' , value: '2' },\n { description:'enums.bl-pay.bridallive-pay-processing-networks.ach' , value: '3' }\n ],\n\n bridalLivePayPaymentMethods : [\n { description:'enums.bl-pay.bridallive-pay-payment-methods.visa' , value: '1', id: 1 },\n { description:'enums.bl-pay.bridallive-pay-payment-methods.mastercard' , value: '2', id: 2 },\n { description:'enums.bl-pay.bridallive-pay-payment-methods.discover' , value: '3', id: 3 },\n { description:'enums.bl-pay.bridallive-pay-payment-methods.american-express' , value: '4', id: 4 }\n ],\n\n budgetRangeSeparators: [\n { value:\"0\", label:\"settings.budget-range.dash\" },\n { value:\"1\", label:\"settings.budget-range.min-through-max\" },\n { value:\"2\", label:\"settings.budget-range.between-min-and-max\" },\n ],\n\n bookingMethods: {\n block: { description: 'enums.booking-methods.blocks', value: 1 },\n first_available: { description: 'enums.booking-methods.first-available', value: 2 }\n },\n\n contactUpdateRequestTypes: [\n { value:\"CI\", label:\"enums.contact-update-request-types.contact-info\" },\n { value:\"PI\", label:\"enums.contact-update-request-types.payment-info\" },\n { value:\"PPI\", label:\"enums.contact-update-request-types.payment-plan-info\" },\n { value:\"SPR\", label:\"enums.contact-update-request-types.store-payment-request\" },\n { value:\"SPPR\", label:\"enums.contact-update-request-types.store-payment-plan-request\" }\n ],\n\n createdByUserTypes: [\n { value: \"\", description: 'common.all' },\n { value: \"ONLINE\", description: 'ONLINE' },\n { value: \"PORTAL\", description: 'PORTAL' }\n ],\n\n // CONTACT_INFO = \"CI\";\n // PAYMENT_INFO = \"PI\";\n // PAYMENT_PLAN_INFO = \"PPI\";\n // STORE_PAYMENT_REQUEST = \"SPR\";\n // STORE_PAYMENT_PLAN_REQUEST = \"SPPR\";\n\n daysOfWeek: {\n SUNDAY: {\n value: 1,\n description: 'settings.day-of-week.0'\n },\n MONDAY: {\n value: 2,\n description: 'settings.day-of-week.1'\n },\n TUESDAY: {\n value: 3,\n description: 'settings.day-of-week.2'\n },\n WEDNESDAY: {\n value: 4,\n description: 'settings.day-of-week.3'\n },\n THURSDAY: {\n value: 5,\n description: 'settings.day-of-week.4'\n },\n FRIDAY: {\n value: 6,\n description: 'settings.day-of-week.5'\n },\n SATURDAY: {\n value: 7,\n description: 'settings.day-of-week.6'\n }\n },\n\n defaultItemSortFieldHeaders: [\n { description: 'item.#', value: '0' },\n { description: 'common.name', value: '1' },\n { description: 'item.vendor-name', value: '2' },\n { description: 'common.color', value: '3' },\n { description: 'common.size', value: '4' },\n { description: 'item.qoh', value: '6' },\n { description: 'common.price', value: '7' },\n { description: 'item.order-cost', value: '8' },\n { description: 'common.vendor', value: '9' },\n { description: 'common.department', value: '10' }\n ],\n\n directions: [\n { description: 'enums.statuses.all', value: '' },\n { description: 'enums.directions.inbound-transfers', value: 'IB' },\n { description: 'enums.directions.outbound-transfers', value: 'OB' }\n ],\n\n evaluationTypes: [\n { value: 'PB', description: \"enums.evaluation-types.payment-based\" },\n { value: 'TB', description: \"enums.evaluation-types.transaction-based\" }\n ],\n\n commissionEvalTypes: [\n { value: 'TB', description: \"enums.evaluation-types.transaction-level\" },\n { value: 'LIB', description: \"enums.evaluation-types.line-item-level\" }\n ],\n\n commissionStatuses: [\n { value: '', description: 'common.all' },\n { value: 'U', description: \"enums.commission-statuses.not-paid\" },\n { value: 'P', description: \"enums.commission-statuses.paid\" },\n { value: 'NR', description: \"enums.commission-statuses.no-record\" }\n // { value: 'NRNP', description: \"enums.commission-statuses.no-record-and-not-paid\" }\n ],\n\n commissionStatusesObj: {\n unpaid: { value: 'U', description: \"enums.commission-statuses.not-paid\" },\n paid: { value: 'P', description: \"enums.commission-statuses.paid\" }\n },\n\n eventTypes: {\n wedding: { description: 'enums.event-types.wedding', value: 1, id:\"1\" },\n other: { description: 'enums.event-types.other', value: 2, id:\"2\" },\n prom: { description: 'enums.event-types.prom', value: 3, id:\"3\" },\n homecoming: { description: 'enums.event-types.homecoming', value: 4, id:\"4\" },\n pageant: { description: 'enums.event-types.pageant', value: 5, id:\"5\" },\n ball: { description: 'enums.event-types.ball', value: 6, id:\"6\" },\n formal_event: { description: 'enums.event-types.formal-event', value: 7, id:\"7\" },\n quince: { description: 'enums.event-types.quinceañera', value: 8, id:\"8\" },\n unknown: { description: 'enums.event-types.unknown', value: 9, id:\"9\" }\n },\n\n prefContactMethods: {\n mobile: { label: 'enums.pref-contact-methods.mobile', value: 1 },\n home: { label: 'enums.pref-contact-methods.home', value:2 },\n work: { label: 'enums.pref-contact-methods.work', value:3 },\n email: { label: 'enums.pref-contact-methods.email', value:4 },\n phone: { label: 'enums.pref-contact-methods.phone', value:5 }\n },\n\n prefContactMethodsAppointmentRequest: {\n email: { label: 'enums.pref-contact-methods.email', value:4 },\n phone: { label: 'enums.pref-contact-methods.phone', value:1 }\n },\n\n eventMemberTypes: {\n unknown: { description: 'enums.event-member-types.unknown', value: 0 , id: \"0\" },\n bride: { description: 'enums.event-member-types.bride', value: 1 , id: \"1\" },\n groom: { description: 'enums.event-member-types.groom', value: 2 , id: \"2\" },\n maid_of_honor: { description: 'enums.event-member-types.maid-of-honor', value: 3 , id: \"3\" },\n matron_of_honor: { description: 'enums.event-member-types.matron-of-honor', value: 17 , id: \"17\" },\n best_man: { description: 'enums.event-member-types.best-man', value: 4 , id: \"4\" },\n bridesmaid: { description: 'enums.event-member-types.bridesmaid', value: 5 , id: \"5\" },\n junior_bridesmaid: { description: 'enums.event-member-types.junior-bridesmaid', value: 16 , id: \"16\" },\n groomsman: { description: 'enums.event-member-types.groomsman', value: 6 , id: \"6\" },\n flowergirl: { description: 'enums.event-member-types.flowergirl', value: 7 , id: \"7\" },\n ring_bearer: { description: 'enums.event-member-types.ringbearer', value: 8 , id: \"8\" },\n mother_of_the_bride: { description: 'enums.event-member-types.mother-of-the-bride', value: 9 , id: \"9\" },\n mother_of_the_groom: { description: 'enums.event-member-types.mother-of-the-groom', value: 10 , id: \"10\" },\n father_of_the_bride: { description: 'enums.event-member-types.father-of-the-bride', value: 12 , id: \"12\" },\n father_of_the_groom: { description: 'enums.event-member-types.father-of-the-groom', value: 13 , id: \"13\" },\n grand_mother: { description: 'enums.event-member-types.grandmother', value: 11 , id: \"11\" },\n grand_father: { description: 'enums.event-member-types.grandfather', value: 14 , id: \"14\" },\n usher: { description: 'enums.event-member-types.usher', value: 15 , id: \"15\" },\n court_member: { description: 'enums.event-member-types.court-member', value: 18 , id: \"18\"},\n pageant_contestant: { description: 'enums.event-member-types.pageant-contestant', value: 19, id: \"19\" },\n officiant: { description: 'enums.event-member-types.officiant', value: 20, id: \"20\" },\n bride_party_member: { description: 'enums.event-member-types.bride-party-member', value: 21, id: \"21\" },\n groom_party_member: { description: 'enums.event-member-types.groom-party-member', value: 22, id: \"22\" }\n },\n\n roleTypes: [\n { description: 'enums.event-member-types.unknown', value: 0 },\n { description: 'enums.event-member-types.bride', value: 1 },\n { description: 'enums.event-member-types.groom', value: 2 },\n { description: 'enums.event-member-types.maid-of-honor', value: 3 },\n { description: 'enums.event-member-types.matron-of-honor', value: 17 },\n { description: 'enums.event-member-types.best-man', value: 4 },\n { description: 'enums.event-member-types.bridesmaid', value: 5 },\n { description: 'enums.event-member-types.junior-bridesmaid', value: 16 },\n { description: 'enums.event-member-types.groomsman', value: 6 },\n { description: 'enums.event-member-types.flowergirl', value: 7 },\n { description: 'enums.event-member-types.ringbearer', value: 8 },\n { description: 'enums.event-member-types.mother-of-the-bride', value: 9 },\n { description: 'enums.event-member-types.mother-of-the-groom', value: 10 },\n { description: 'enums.event-member-types.father-of-the-bride', value: 12 },\n { description: 'enums.event-member-types.father-of-the-groom', value: 13 },\n { description: 'enums.event-member-types.grandmother', value: 11 },\n { description: 'enums.event-member-types.grandfather', value: 14 },\n { description: 'enums.event-member-types.usher', value: 15 },\n { description: 'enums.event-member-types.court-member', value: 18 },\n { description: 'enums.event-member-types.pageant-contestant', value: 19 },\n { description: 'enums.event-member-types.officiant', value: 20 },\n { description: 'enums.event-member-types.bride-party-member', value: 21 },\n { description: 'enums.event-member-types.groom-party-member', value: 22 }\n ],\n\n eventTimesOfDay: {\n morning: { description: 'enums.event-times-of-day.morning', value: 1 },\n afternoon: { description: 'enums.event-times-of-day.afternoon', value: 2 },\n evening: { description: 'enums.event-times-of-day.evening', value: 3 }\n },\n\n eventFormalities: {\n informal: { description: 'enums.event-formalities.informal', value: 1 },\n semiformal: { description: 'enums.event-formalities.semi-formal', value: 2 },\n formal: { description: 'enums.event-formalities.formal', value: 3 }\n },\n\n formFieldTypes:[\n { description:'settings.webforms.form-builder.field-types.text', value: 'text' },\n { description:'settings.webforms.form-builder.field-types.textarea', value: 'textarea' },\n { description:'settings.webforms.form-builder.field-types.select', value: 'select' },\n { description:'settings.webforms.form-builder.field-types.checkbox', value: 'checkbox' },\n { description:'settings.webforms.form-builder.field-types.phone', value: 'phone' },\n { description:'settings.webforms.form-builder.field-types.radio', value: 'radio' },\n { description:'settings.webforms.form-builder.field-types.email', value: 'email' },\n { description:'settings.webforms.form-builder.field-types.number', value: 'number' },\n { description:'settings.webforms.form-builder.field-types.currency', value: 'currency' },\n { description:'settings.webforms.form-builder.field-types.date', value: 'date' }\n ],\n\n optInOptions: [\n { value: true, description: 'enums.opt-in-options.receives-mass-text-messages' },\n { value: false, description: 'enums.opt-in-options.does-not-receive-mass-text-messages' }\n ],\n\n itemTypes: [\n { value: 'I', description: \"item.types.inventory\" },\n { value: 'N', description: \"item.types.non-inventory\" },\n { value: 'R', description: \"item.rental\" },\n { value: 'S', description: \"item.service\" }\n ],\n\n salePriceFilterType: [\n { value: '', description: \"common.all\" },\n { value: 'Y', description: \"common.yes\" },\n { value: 'N', description: \"common.no\" }\n ],\n\n smartFlowTriggers: {\n contact_added: { id: 1, name: 'enums.smart-flow-triggers.contact-added' },\n appointment_added: { id: 2, name: 'enums.smart-flow-triggers.appointment-added' },\n appointment_completed: { id: 3, name: 'enums.smart-flow-triggers.appointment-completed' },\n appointment_no_show: { id: 9, name: 'enums.smart-flow-triggers.appointment-no-show' },\n appointment_canceled: { id: 10, name: 'enums.smart-flow-triggers.appointment-canceled' },\n transaction_created: { id: 4, name: 'enums.smart-flow-triggers.pos-transaction-created' },\n sale_created: { id: 5, name: 'enums.smart-flow-triggers.sale-created' },\n special_order_created: { id: 6, name: 'enums.smart-flow-triggers.special-order-created' },\n special_order_completed: { id: 7, name: 'enums.smart-flow-triggers.special-order-completed' },\n layaway_created: { id: 12, name: 'enums.smart-flow-triggers.layaway-created' },\n purchase_order_confirmed: { id: 13, name: 'enums.smart-flow-triggers.purchase-order-confirmed' },\n receiving_voucher_completed: { id: 14, name: 'enums.smart-flow-triggers.receiving-voucher-completed' },\n quote_created: { id: 16, name: 'enums.smart-flow-triggers.quote-created' },\n contact_registered: { id: 17, name: 'enums.smart-flow-triggers.contact-registered' }\n },\n\n smartFlowActions: {\n send_email: { id: 1, name: \"Send Email\" },\n send_sms: { id: 4, name: \"Send Text Message\" },\n create_task: { id: 2, name: \"Create Task\" },\n system_action: { id: 3, name: \"System Action\" }\n },\n\n smartFlowMilestones: {\n today: { id: 1, name: \"enums.smart-flow-milestones.today\" },\n appointment_date: { id: 2, name: \"enums.smart-flow-milestones.appointment-date\" },\n event_date: { id: 3, name: \"enums.smart-flow-milestones.event-date\" }\n },\n\n smartFlowWeddingPartyBehaviors: {\n event_contact_and_members: { id: 1, name: \"enums.smart-flow-wedding-party-behaviors.event_contact_and_members\" },\n event_contact_only: { id: 2, name: \"enums.smart-flow-wedding-party-behaviors.event_contact_only\" },\n event_members_only: { id: 3, name: \"enums.smart-flow-wedding-party-behaviors.event_members_only\" }\n },\n\n smartFlowSystemActions: [\n { id: 1, name: \"enums.smart-flow-system-actions.add-to-mailchimp-list\", isBackendProcess: true },\n { id: 2, name: \"enums.smart-flow-system-actions.remove-from-mailchimp-list\", isBackendProcess: true },\n { id: 3, name: \"enums.smart-flow-system-actions.assign-to-category\", isBackendProcess: true },\n { id: 4, name: \"enums.smart-flow-system-actions.schedule-another-appointment\", isBackendProcess: false },\n { id: 5, name: \"enums.smart-flow-system-actions.create-transaction\", isBackendProcess: false },\n { id: 6, name: \"enums.smart-flow-system-actions.webhook\", isBackendProcess: true }\n ],\n\n timeZones: [\n { label: \"(GMT-00:00) UTC - (Europe/London)\", value: \"Europe/London\" },\n { label: \"(GMT-04:00) Atlantic Time (Canada)\", value: \"America/Halifax\" },\n { label: \"(GMT-05:00) Eastern Time (US & Canada)\", value: \"America/New_York\" },\n { label: \"(GMT-05:00) America - Puerto_Rico\", value: \"America/Puerto_Rico\" },\n { label: \"(GMT-05:00) America - Guadeloupe\", value: \"America/Guadeloupe\" },\n { label: \"(GMT-05:00) America - Cancun\", value: \"America/Cancun\" },\n { label: \"(GMT-06:00) Central Time (US & Canada)\", value: \"America/Chicago\" },\n { label: \"(GMT-06:00) Central Time - No DST (Canada/Saskatchewan only)\", value: \"Canada/Saskatchewan\" },\n { label: \"(GMT-06:00) America - Monterrey\", value: \"America/Monterrey\" },\n { label: \"(GMT-06:00) America - Mexico City\", value: \"America/Mexico_City\" },\n { label: \"(GMT-06:00) America - Mexico City - No DST\", value: \"Canada/Saskatchewan\" },\n { label: \"(GMT-06:00) America - Merida\", value: \"America/Merida\" },\n { label: \"(GMT-07:00) Mountain Time (US & Canada)\", value: \"America/Denver\" },\n { label: \"(GMT-07:00) Mountain Time - No DST (US & Canada)\", value: \"America/Phoenix\" },\n { label: \"(GMT-07:00) America - Mazatlan\", value: \"America/Mazatlan\" },\n { label: \"(GMT-07:00) America - Hermosillo\", value: \"America/Hermosillo\" },\n { label: \"(GMT-07:00) America - Chihuahua\", value: \"America/Chihuahua\" },\n { label: \"(GMT-08:00) Pacific Time (US & Canada)\", value: \"America/Los_Angeles\" },\n { label: \"(GMT-08:00) America - Tijuana\", value: \"America/Tijuana\" },\n { label: \"(GMT-09:00) Alaska Time (US)\", value: \"America/Anchorage\" },\n { label: \"(GMT-10:00) Hawaii Time (US)\", value: \"Pacific/Honolulu\" },\n { label: \"(GMT+01:00) Central European Time\", value: \"Europe/Paris\" },\n { label: \"(GMT+01:00) Europe - Dublin\", value: \"Europe/Dublin\" },\n { label: \"(GMT+02:00) Europe - Kiev\", value: \"Europe/Kiev\" },\n { label: \"(GMT+04:00) Europe - Samara\", value: \"Europe/Samara\" },\n { label: \"(GMT+04:00) Indian/Reunion\", value: \"Indian/Reunion\" },\n { label: \"(GMT+08:00) Australia - Perth\", value: \"Australia/Perth\" },\n { label: \"(GMT+09:30) Australia - South\", value: \"Australia/South\" },\n { label: \"(GMT+09:30) Australia - North\", value: \"Australia/North\" },\n { label: \"(GMT+10:00) Australia - Queensland\", value: \"Australia/Queensland\" },\n { label: \"(GMT+10:00) Australia - New South Wales\", value: \"Australia/Sydney\" },\n { label: \"(GMT+11:00) Australia - Victoria\", value: \"Australia/Melbourne\" },\n { label: \"(GMT+12:00) New Zealand - Auckland\", value: \"Pacific/Auckland\"}\n ],\n\n transactionCancelReasons: [\n { id: 1, desc: \"Other reason\", key: \"settings.pos-cancel-type.cancel-reasons.other-reason\" },\n { id: 2, desc: \"Accidental order\", key: \"settings.pos-cancel-type.cancel-reasons.accidental-order\" },\n { id: 3, desc: \"Better price available\", key: \"settings.pos-cancel-type.cancel-reasons.better-price-available\" },\n { id: 4, desc: \"No reason given\", key: \"settings.pos-cancel-type.cancel-reasons.no-reason-given\" },\n { id: 5, desc: \"Damaged due to poor packaging\", key: \"settings.pos-cancel-type.cancel-reasons.damaged-due-to-poor-packaging\" },\n { id: 6, desc: \"Arrived too late\", key: \"settings.pos-cancel-type.cancel-reasons.arrived-too-late\" },\n { id: 7, desc: \"Missing parts or accessories\", key: \"settings.pos-cancel-type.cancel-reasons.missing-parts-or-accessories\" },\n { id: 8, desc: \"Damaged during shipping\", key: \"settings.pos-cancel-type.cancel-reasons.damaged-during-shipping\" },\n { id: 9, desc: \"Different from what was ordered\", key: \"settings.pos-cancel-type.cancel-reasons.different-from-what-was-ordered\" },\n { id: 10, desc:\t\"Defective/Does not work properly\", key: \"settings.pos-cancel-type.cancel-reasons.defective-does-not-work-properly\" },\n { id: 11, desc:\t\"Arrived in addition to what was ordered\", key: \"settings.pos-cancel-type.cancel-reasons.arrived-in-addition-to-what-was-ordered\" },\n { id: 12, desc:\t\"I don't want it anymore\", key: \"settings.pos-cancel-type.cancel-reasons.i-dont-want-it-anymore\" },\n { id: 13, desc:\t\"Defect emerged after use\", key: \"settings.pos-cancel-type.cancel-reasons.defect-emerged-after-use\" },\n { id: 14, desc:\t\"Unauthorized purchase\", key: \"settings.pos-cancel-type.cancel-reasons.unauthorized-purchase\" },\n { id: 15, desc:\t\"I haven't received this item yet\", key: \"settings.pos-cancel-type.cancel-reasons.i-havent-received-this-item-yet\" },\n { id: 16, desc:\t\"Item was defective\", key: \"settings.pos-cancel-type.cancel-reasons.item-was-defective\" },\n { id: 17, desc:\t\"Item description was inaccurate\", key: \"settings.pos-cancel-type.cancel-reasons.item-description-was-inaccurate\" },\n { id: 18, desc:\t\"Not satisfied with the quality\", key: \"settings.pos-cancel-type.cancel-reasons.not-satisfied-with-the-quality\" },\n { id: 19, desc:\t\"Fabric not as expected\", key: \"settings.pos-cancel-type.cancel-reasons.fabric-not-as-expected\" },\n { id: 20, desc:\t\"No longer needed/wanted\", key: \"settings.pos-cancel-type.cancel-reasons.no-longer-needed-wanted\" },\n { id: 21, desc:\t\"Item is too large\", key: \"settings.pos-cancel-type.cancel-reasons.item-is-too-large\" },\n { id: 22, desc:\t\"Item is too small\", key: \"settings.pos-cancel-type.cancel-reasons.item-is-too-small\" },\n { id: 23, desc:\t\"Item is too long\", key: \"settings.pos-cancel-type.cancel-reasons.item-is-too-long\" },\n { id: 24, desc:\t\"Item is too short\", key: \"settings.pos-cancel-type.cancel-reasons.item-is-too-short\" },\n { id: 25, desc:\t\"Wrong item sent\", key: \"settings.pos-cancel-type.cancel-reasons.wrong-item-sent\" },\n { id: 26, desc:\t\"Better price is available\", key: \"settings.pos-cancel-type.cancel-reasons.better-price-is-available\" },\n { id: 27, desc:\t\"Damaged upon arrival\", key: \"settings.pos-cancel-type.cancel-reasons.damaged-upon-arrival\" },\n { id: 28, desc:\t\"Ordered wrong style/size/color\", key: \"settings.pos-cancel-type.cancel-reasons.ordered-wrong-style-size-color\" },\n { id: 29, desc:\t\"Different from website description\", key: \"settings.pos-cancel-type.cancel-reasons.different-from-website-description\" },\n { id: 30, desc:\t\"Didn't like fabric\", key: \"settings.pos-cancel-type.cancel-reasons.didn't-like-fabric\" },\n { id: 31, desc:\t\"Did not like the color\", key: \"settings.pos-cancel-type.cancel-reasons.did-not-like-the-color\" },\n { id: 32, desc:\t\"Missing or loose stone\", key: \"settings.pos-cancel-type.cancel-reasons.missing-or-loose-stone\" },\n { id: 33, desc:\t\"Item is the wrong color\", key: \"settings.pos-cancel-type.cancel-reasons.item-is-the-wrong-color\" },\n { id: 34, desc:\t\"Item is of the wrong material\", key: \"settings.pos-cancel-type.cancel-reasons.item-is-of-the-wrong-material\" }\n ],\n\n browserTimeZones: [\n {\n id: \"Europe/London\",\n label: \"(GMT-00:00) UTC - (Europe/London)\",\n zones:[\n \"Europe/Isle_of_Man\",\n \"Europe/Guernsey\",\n \"Europe/Jersey\",\n \"Europe/London\",\n \"Europe/Dublin\"\n ]\n },\n {\n id: \"America/Halifax\",\n label: \"(GMT-04:00) Atlantic Time (Canada)\",\n zones:[\n \"America/Glace_Bay\",\n \"America/Goose_Bay\",\n \"America/Halifax\",\n \"America/Moncton\",\n \"America/Thule\",\n \"Atlantic/Bermuda\"\n ]\n },\n {\n id: \"America/New_York\",\n label: \"(GMT-05:00) Eastern Time (US & Canada)\",\n zones:[\n \"America/Detroit\",\n \"America/Havana\",\n \"America/Indiana/Petersburg\",\n \"America/Indiana/Vincennes\",\n \"America/Indiana/Winamac\",\n \"America/Indiana/Indianapolis\",\n \"America/Indianapolis\",\n \"America/Iqaluit\",\n \"America/Kentucky/Monticello\",\n \"America/Louisville\",\n \"America/Montreal\",\n \"America/Nassau\",\n \"America/New_York\",\n \"America/Nipigon\",\n \"America/Pangnirtung\",\n \"America/Port-au-Prince\",\n \"America/Thunder_Bay\",\n \"America/Toronto\"\n ]\n },\n {\n id: \"America/Puerto_Rico\",\n label: \"(GMT-05:00) America - Puerto_Rico\",\n zones:[\n \"America/Anguilla\",\n \"America/Antigua\",\n \"America/Aruba\",\n \"America/Barbados\",\n \"America/Blanc-Sablon\",\n \"America/Boa_Vista\",\n \"America/Curacao\",\n \"America/Dominica\",\n \"America/Grand_Turk\",\n \"America/Grenada\",\n \"America/Guadeloupe\",\n \"America/Guyana\",\n \"America/Kralendijk\",\n \"America/La_Paz\",\n \"America/Lower_Princes\",\n \"America/Manaus\",\n \"America/Marigot\",\n \"America/Martinique\",\n \"America/Montserrat\",\n \"America/Port_of_Spain\",\n \"America/Porto_Velho\",\n \"America/Puerto_Rico\",\n \"America/Santo_Domingo\",\n \"America/St_Barthelemy\",\n \"America/St_Kitts\",\n \"America/St_Lucia\",\n \"America/St_Thomas\",\n \"America/St_Vincent\",\n \"America/Tortola\",\n \"Etc/GMT+4\"\n ]\n },\n {\n id: \"America/Guadeloupe\",\n label: \"(GMT-05:00) America - Guadeloupe\",\n zones:[\n \"America/Anguilla\",\n \"America/Antigua\",\n \"America/Aruba\",\n \"America/Barbados\",\n \"America/Blanc-Sablon\",\n \"America/Boa_Vista\",\n \"America/Curacao\",\n \"America/Dominica\",\n \"America/Grand_Turk\",\n \"America/Grenada\",\n \"America/Guadeloupe\",\n \"America/Guyana\",\n \"America/Kralendijk\",\n \"America/La_Paz\",\n \"America/Lower_Princes\",\n \"America/Manaus\",\n \"America/Marigot\",\n \"America/Martinique\",\n \"America/Montserrat\",\n \"America/Port_of_Spain\",\n \"America/Porto_Velho\",\n \"America/Puerto_Rico\",\n \"America/Santo_Domingo\",\n \"America/St_Barthelemy\",\n \"America/St_Kitts\",\n \"America/St_Lucia\",\n \"America/St_Thomas\",\n \"America/St_Vincent\",\n \"America/Tortola\",\n \"Etc/GMT+4\"\n ]\n },\n {\n id: \"America/Cancun\",\n label: \"(GMT-05:00) America - Cancun\",\n zones:[\n \"America/Bahia_Banderas\",\n \"America/Cancun\",\n \"America/Merida\",\n \"America/Mexico_City\",\n \"America/Monterrey\"\n ]\n },\n {\n id: \"America/Chicago\",\n label: \"(GMT-06:00) Central Time (US & Canada)\",\n zones:[\n \"America/Chicago\",\n \"America/Indiana/Knox\",\n \"America/Indiana/Tell_City\",\n \"America/Matamoros\",\n \"America/Menominee\",\n \"America/North_Dakota/Beulah\",\n \"America/North_Dakota/Center\",\n \"America/North_Dakota/New_Salem\",\n \"America/Rainy_River\",\n \"America/Rankin_Inlet\",\n \"America/Resolute\",\n \"America/Winnipeg\",\n \"CST6CDT\"\n ]\n },\n {\n id: \"Canada/Saskatchewan\",\n label: \"(GMT-06:00) Central Time - No Daylight Savings (Canada/Saskatchewan only)\",\n zones:[\n \"America/Regina\",\n \"America/Swift_Current\",\n \"America/Mexico_City\"\n ]\n },\n {\n id: \"America/Monterrey\",\n label: \"(GMT-06:00) America - Monterrey\",\n zones:[\n \"America/Monterrey\"\n ]\n },\n {\n id: \"America/Mexico_City\",\n label: \"(GMT-06:00) America - Mexico_City\",\n zones:[\n \"America/Bahia_Banderas\",\n \"America/Cancun\",\n \"America/Merida\",\n \"America/Mexico_City\",\n \"America/Monterrey\",\n \"Canada/Saskatchewan\"\n ]\n },\n {\n id: \"America/Merida\",\n label: \"(GMT-06:00) America - Merida\",\n zones:[\n \"America/Bahia_Banderas\",\n \"America/Cancun\",\n \"America/Merida\",\n \"America/Mexico_City\",\n \"America/Monterrey\"\n ]\n },\n {\n id: \"America/Denver\",\n label: \"(GMT-07:00) Mountain Time (US & Canada)\",\n zones:[\n \"America/Boise\",\n \"America/Cambridge_Bay\",\n \"America/Denver\",\n \"America/Edmonton\",\n \"America/Inuvik\",\n \"America/Ojinaga\",\n \"America/Yellowknife\",\n \"MST7MDT\"\n ]\n },\n {\n id: \"America/Phoenix\",\n label: \"(GMT-07:00) Mountain Time - No Daylight Savings (US & Canada)\",\n zones:[\n \"America/Creston\",\n \"America/Dawson\",\n \"America/Dawson_Creek\",\n \"America/Hermosillo\",\n \"America/Phoenix\",\n \"America/Whitehorse\",\n \"Etc/GMT+7\"\n ]\n },\n {\n id: \"America/Mazatlan\",\n label: \"(GMT-07:00) America - Mazatlan\",\n zones:[\n \"America/Chihuahua\",\n \"America/Mazatlan\"\n ]\n },\n {\n id: \"America/Hermosillo\",\n label: \"(GMT-07:00) America - Hermosillo\",\n zones:[\n \"America/Creston\",\n \"America/Dawson\",\n \"America/Dawson_Creek\",\n \"America/Hermosillo\",\n \"America/Phoenix\",\n \"America/Whitehorse\",\n \"Etc/GMT+7\"\n ]\n },\n {\n id: \"America/Chihuahua\",\n label: \"(GMT-07:00) America - Chihuahua\",\n zones:[\n \"America/Chihuahua\",\n \"America/Mazatlan\"\n ]\n },\n {\n id: \"America/Los_Angeles\",\n label: \"(GMT-08:00) Pacific Time (US & Canada)\",\n zones:[\n \"America/Los_Angeles\",\n \"America/Tijuana\",\n \"America/Vancouver\"\n ]\n },\n {\n id: \"America/Tijuana\",\n label: \"(GMT-08:00) America - Tijuana\",\n zones:[\n \"America/Los_Angeles\",\n \"America/Tijuana\",\n \"America/Vancouver\"\n ]\n },\n {\n id: \"America/Anchorage\",\n label: \"(GMT-09:00) Alaska Time (US)\",\n zones:[\n \"America/Anchorage\",\n \"America/Juneau\",\n \"America/Nome\",\n \"America/Sitka\",\n \"America/Yakutat\"\n ]\n },\n {\n id: \"Pacific/Honolulu\",\n label: \"(GMT-10:00) Hawaii Time (US)\",\n zones:[\n \"Etc/GMT+10\",\n \"Pacific/Honolulu\",\n \"Pacific/Johnston\",\n \"Pacific/Rarotonga\",\n \"Pacific/Tahiti\"\n ]\n },\n {\n id: \"Europe/Paris\",\n label: \"(GMT+01:00) Central European Time\",\n zones:[\n \"Africa/Ceuta\",\n \"Europe/Brussels\",\n \"Europe/Copenhagen\",\n \"Europe/Madrid\",\n \"Europe/Paris\",\n \"Europe/Berlin\",\n \"Europe/Busingen\",\n \"Arctic/Longyearbyen\",\n \"Europe/Copenhagen\",\n \"Europe/Oslo\",\n \"Europe/Stockholm\",\n \"Atlantic/Jan_Mayen\",\n \"Europe/Belgrade\",\n \"Europe/Ljubljana\",\n \"Europe/Podgorica\",\n \"Europe/Sarajevo\",\n \"Europe/Skopje\",\n \"Europe/Zagreb\",\n \"Africa/Algiers\",\n \"Europe/Amsterdam\",\n \"Europe/Andorra\",\n \"Europe/Malta\",\n \"Europe/Bratislava\",\n \"Europe/Brussels\",\n \"Europe/Amsterdam\",\n \"Europe/Luxembourg\",\n \"Europe/Budapest\",\n \"Europe/Copenhagen\",\n \"Europe/Gibraltar\",\n \"Europe/Ljubljana\",\n \"Arctic/Longyearbyen\",\n \"Europe/Luxembourg\",\n \"Africa/Ceuta\",\n \"Europe/Madrid\",\n \"Europe/Monaco\",\n \"Europe/Oslo\",\n \"Atlantic/Jan_Mayen\",\n \"Europe/Paris\",\n \"Europe/Monaco\",\n \"Europe/Podgorica\",\n \"Europe/Prague\",\n \"Europe/Bratislava\",\n \"Europe/Rome\",\n \"Europe/San_Marino\",\n \"Europe/Vatican\",\n \"Europe/San_Marino\",\n \"Europe/Sarajevo\",\n \"Europe/Skopje\",\n \"Europe/Stockholm\",\n \"Europe/Tirane\",\n \"Africa/Tunis\",\n \"Europe/Vaduz\",\n \"Europe/Vatican\",\n \"Europe/Vienna\",\n \"Europe/Warsaw\",\n \"Europe/Zagreb\",\n \"Europe/Zurich\",\n \"Europe/Busingen\",\n \"Europe/Vaduz\",\n \"Poland\"\n ],\n },\n {\n id: \"Europe/Dublin\",\n label: \"(GMT+01:00) Europe - Dublin\",\n zones:[\n \"Atlantic/Canary\",\n \"Atlantic/Faeroe\",\n \"Atlantic/Madeira\",\n \"Europe/London\",\n \"Europe/Dublin\",\n \"Europe/Lisbon\",\n \"Europe/Berlin\",\n \"Europe/Busingen\",\n \"Arctic/Longyearbyen\",\n \"Europe/Copenhagen\",\n \"Europe/Oslo\",\n \"Europe/Stockholm\",\n \"Atlantic/Jan_Mayen\",\n \"Europe/Belgrade\",\n \"Europe/Ljubljana\",\n \"Europe/Podgorica\",\n \"Europe/Sarajevo\",\n \"Europe/Skopje\",\n \"Europe/Zagreb\",\n \"Africa/Algiers\",\n \"Europe/Amsterdam\",\n \"Europe/Andorra\",\n \"Europe/Malta\",\n \"Europe/Bratislava\",\n \"Europe/Brussels\",\n \"Europe/Amsterdam\",\n \"Europe/Luxembourg\",\n \"Europe/Budapest\",\n \"Europe/Copenhagen\",\n \"Europe/Gibraltar\",\n \"Europe/Ljubljana\",\n \"Arctic/Longyearbyen\",\n \"Europe/Luxembourg\",\n \"Africa/Ceuta\",\n \"Europe/Madrid\",\n \"Europe/Monaco\",\n \"Europe/Oslo\",\n \"Atlantic/Jan_Mayen\",\n \"Europe/Paris\",\n \"Europe/Monaco\",\n \"Europe/Podgorica\",\n \"Europe/Prague\",\n \"Europe/Bratislava\",\n \"Europe/Rome\",\n \"Europe/San_Marino\",\n \"Europe/Vatican\",\n \"Europe/San_Marino\",\n \"Europe/Sarajevo\",\n \"Europe/Skopje\",\n \"Europe/Stockholm\",\n \"Europe/Tirane\",\n \"Africa/Tunis\",\n \"Europe/Vaduz\",\n \"Europe/Vatican\",\n \"Europe/Vienna\",\n \"Europe/Warsaw\",\n \"Europe/Zagreb\",\n \"Europe/Zurich\",\n \"Europe/Busingen\",\n \"Europe/Vaduz\",\n \"Poland\"\n ]\n },\n {\n id: \"Europe/Kiev\",\n label: \"(GMT+02:00) Europe - Kiev\",\n zones:[\n \"Asia/Nicosia\",\n \"Europe/Athens\",\n \"Europe/Bucharest\",\n \"Europe/Chisinau\",\n \"Europe/Helsinki\",\n \"Europe/Kiev\",\n \"Europe/Mariehamn\",\n \"Europe/Nicosia\",\n \"Europe/Riga\",\n \"Europe/Sofia\",\n \"Europe/Tallinn\",\n \"Europe/Uzhgorod\",\n \"Europe/Vilnius\",\n \"Europe/Zaporozhye\"\n ]\n },\n {\n id: \"Europe/Samara\",\n label: \"(GMT+04:00) Europe - Samara\",\n zones:[\n \"Europe/Astrakhan\",\n \"Europe/Samara\",\n \"Europe/Ulyanovsk\"\n ]\n },\n {\n id: \"Indian/Reunion\",\n label: \"(GMT+04:00) Indian/Reunion\",\n zones:[\n \"Indian/Mahe\",\n \"Indian/Mauritius\",\n \"Indian/Reunion\"\n ]\n },\n {\n id: \"Australia/Perth\",\n label: \"(GMT+08:00) Australia - Perth\",\n zones:[\n \"Antarctica/Casey\",\n \"Australia/Perth\"\n ]\n },\n {\n id: \"Australia/South\",\n label: \"(GMT+09:30) Australia - South\",\n zones:[\n \"Australia/Adelaide\",\n \"Australia/Broken_Hill\",\n \"Australia/Darwin\"\n ]\n },\n {\n id: \"Australia/North\",\n label: \"(GMT+09:30) Australia - North\",\n zones:[\n \"Australia/Adelaide\",\n \"Australia/Broken_Hill\",\n \"Australia/Darwin\"\n ]\n },\n {\n id: \"Australia/Queensland\",\n label: \"(GMT+10:00) Australia - Queensland\",\n zones:[\n \"Australia/Brisbane\",\n \"Australia/Lindeman\"\n ]\n },\n {\n id: \"Australia/Sydney\",\n label: \"(GMT+10:00) Australia - New South Wales\",\n zones:[\n \"Australia/Melbourne\",\n \"Australia/Sydney\"\n ]\n },\n {\n id: \"Australia/Melbourne\",\n label: \"(GMT+11:00) Australia - Victoria\",\n zones:[\n \"Australia/Melbourne\",\n \"Australia/Sydney\"\n ]\n },\n {\n id: \"Pacific/Auckland\",\n label: \"(GMT+12:00) New Zealand - Auckland\",\n zones: [\n \"Antarctica/McMurdo\",\n \"Pacific/Auckland\"\n ]\n }\n ],\n\n hoursArr: [\n { label: \"7:00AM\", value: \"7:00AM\" },\n { label: \"7:30AM\", value: \"7:30AM\" },\n { label: \"8:00AM\", value: \"8:00AM\" },\n { label: \"8:30AM\", value: \"8:30AM\" },\n { label: \"9:00AM\", value: \"9:00AM\" },\n { label: \"9:30AM\", value: \"9:30AM\" },\n { label: \"10:00AM\", value: \"10:00AM\" },\n { label: \"10:30AM\", value: \"10:30AM\" },\n { label: \"11:00AM\", value: \"11:00AM\" },\n { label: \"11:30AM\", value: \"11:30AM\" },\n { label: \"12:00PM\", value: \"12:00PM\" },\n { label: \"12:30PM\", value: \"12:30PM\" },\n { label: \"1:00PM\", value: \"1:00PM\" },\n { label: \"1:30PM\", value: \"1:30PM\" },\n { label: \"2:00PM\", value: \"2:00PM\" },\n { label: \"2:30PM\", value: \"2:30PM\" },\n { label: \"3:00PM\", value: \"3:00PM\" },\n { label: \"3:30PM\", value: \"3:30PM\" },\n { label: \"4:00PM\", value: \"4:00PM\" },\n { label: \"4:30PM\", value: \"4:30PM\" },\n { label: \"5:00PM\", value: \"5:00PM\" },\n { label: \"5:30PM\", value: \"5:30PM\" },\n { label: \"6:00PM\", value: \"6:00PM\" },\n { label: \"6:30PM\", value: \"6:30PM\" },\n { label: \"7:00PM\", value: \"7:00PM\" },\n { label: \"7:30PM\", value: \"7:30PM\" },\n { label: \"8:00PM\", value: \"8:00PM\" },\n { label: \"8:30PM\", value: \"8:30PM\" },\n { label: \"9:00PM\", value: \"9:00PM\" },\n { label: \"9:30PM\", value: \"9:30PM\" },\n { label: \"10:00PM\", value: \"10:00PM\" }\n ],\n\n durations: [\n { label: \"enums.appointment-durations.15\", value: 900000 },\n { label: \"enums.appointment-durations.30\", value: 1800000 },\n { label: \"enums.appointment-durations.45\", value: 2700000 },\n { label: \"enums.appointment-durations.60\", value: 3600000 },\n { label: \"enums.appointment-durations.75\", value: 4500000 },\n { label: \"enums.appointment-durations.90\", value: 5400000 },\n { label: \"enums.appointment-durations.105\", value: 6300000 },\n { label: \"enums.appointment-durations.120\", value: 7200000 },\n { label: \"enums.appointment-durations.135\", value: 8100000 },\n { label: \"enums.appointment-durations.150\", value: 9000000 },\n { label: \"enums.appointment-durations.165\", value: 9900000 },\n { label: \"enums.appointment-durations.180\", value: 10800000 },\n { label: \"enums.appointment-durations.195\", value: 11700000 },\n { label: \"enums.appointment-durations.210\", value: 12600000 },\n { label: \"enums.appointment-durations.225\", value: 13500000 },\n { label: \"enums.appointment-durations.240\", value: 14400000 },\n { label: \"enums.appointment-durations.255\", value: 15300000 },\n { label: \"enums.appointment-durations.270\", value: 16200000 },\n { label: \"enums.appointment-durations.285\", value: 17100000 },\n { label: \"enums.appointment-durations.300\", value: 18000000 }\n ],\n\n printFormatTypes: [\n { value: \"CF\", label: \"contact.print.condensed\" },\n { value: \"SF\", label: \"contact.print.with-images\" },\n { value: \"WIF\", label: \"contact.print.without-images\" }\n ],\n\n priorities: [\n { description: \"enums.priorities.high\", value: 0 },\n { description: \"enums.priorities.medium\", value: 1 },\n { description: \"enums.priorities.low\", value: 2 }\n ],\n\n colors: [\n '#990000', '#db403b', '#DE3163', '#f50a25', '#FB4A45', '#f15f74', '#FA8072', '#ff00ff', '#ff99ff', '#f69dc7', '#FDD7E4', '#7E5A6D', '#AA385E', '#bd7a9a ', '#5f2588', '#913ccd',\n '#cc00cc ', '#9686b1', '#9A8CA2', '#8B7A8B', '#ccccff ', '#D1CBDF', '#22657F', '#1F75FE', '#5481e6', '#015F97', '#6280E2', '#12C7FD', '#56B5CA', '#66ccff', '#a8e8f5', '#2ca8c2',\n '#008080', '#2A4F43', '#788D60', '#7D9B89', '#66cc00 ', '#57AA80', '#019D6E', '#98cb4a', '#d1e6d5', '#AFB96A', '#b6873a', '#CBA901', '#fff71a', '#f7d842', '#ffff99 ', '#FFC801',\n '#E6D88E', '#FBE4B3', '#E4CEAC', '#F8AC1D', '#663300', '#E37222', '#ff6600', '#CC6600', '#EB882C', '#C78538', '#ffa500', '#FFBD88', '#E3AB7B', '#c0c0c0 ', '#808080', '#ffffff'\n ],\n\n colorThemes: [\n { label: \"enums.client-portal.themes.custom\", headerFooterBG: '', headerFooterText:'', primaryBtnBG: '', primaryBtnText: '', id: 'CU' },\n { label: \"enums.client-portal.themes.bl-default\", headerFooterBG: \"#FA8072\", headerFooterText:'#FFFFFF', primaryBtnBG: '#9686b1', primaryBtnText: '#FFFFFF', id: 'BL' },\n { label: \"enums.client-portal.themes.something-blue\", headerFooterBG: '#A4B0BE', headerFooterText: '#FFFFFF', primaryBtnBG: '#c4cbd4', primaryBtnText: '#FFFFFF', id:'SB' },\n { label: \"enums.client-portal.themes.dusk\", headerFooterBG: '#969376', headerFooterText: '#FFFFFF', primaryBtnBG: '#878296', primaryBtnText: '#FFFFFF', id:'DK' },\n { label: \"enums.client-portal.themes.meadow\", headerFooterBG: '#d2e0d4', headerFooterText: '#FFFFFF', primaryBtnBG: '#a5998d', primaryBtnText: '#FFFFFF', id:'MW' },\n { label: \"enums.client-portal.themes.blush\", headerFooterBG: '#f7e1db', headerFooterText: '#454545', primaryBtnBG: '#f7e1db', primaryBtnText: '#454545', id:'BH' },\n { label: \"enums.client-portal.themes.wild-and-free\", headerFooterBG: '#f0f0f0', headerFooterText: '#e0baa4', primaryBtnBG: '#f0f0f0', primaryBtnText: '#e0baa4', id:'WF' },\n { label: \"enums.client-portal.themes.island-time\", headerFooterBG: '#2c303a', headerFooterText: '#cad295', primaryBtnBG: '#2c303a', primaryBtnText: '#cad295', id:'IT' },\n { label: \"enums.client-portal.themes.neutral\", headerFooterBG: '#C2C1C0', headerFooterText: '#FFFFFF', primaryBtnBG: '#9B9A9A', primaryBtnText: '#FFFFFF', id:'NL' }\n ],\n\n webformColorThemes: [\n { label: \"enums.client-portal.themes.custom\", backgroundColor: '', textColor: '', primaryColor:'', selectedColor: '', availableColor: '', timeSlotColor: '', inputBorderColor: '', primaryTextColor:'', secondaryColor: '', selectedTextColor: '', availableTextColor: '', timeSlotTextColor: '', id: 'CU' },\n { label: \"enums.client-portal.themes.bl-default\", backgroundColor: '#ffffff', textColor: '#454545', primaryColor:'#9686b1', secondaryColor: '#e8e8e8', selectedColor: '#b9a5cd', availableColor: '#dff0d8', timeSlotColor: '#e8e8e8', inputBorderColor: '#E2E8F0', primaryTextColor:'#ffffff', secondaryTextColor: '#222222', selectedTextColor: '#ffffff', timeSlotTextColor:'#ffffff', availableTextColor: '#ffffff', id: 'BL', transparent: true },\n { label: \"enums.client-portal.themes.something-blue\", backgroundColor: '#A4B0BE', textColor: '#454545', primaryColor:'#c4cbd4', secondaryColor: '#e8e8e8', selectedColor: '#c4cbd4', availableColor: '#dff0d8', timeSlotColor: '#e8e8e8', inputBorderColor: '#E2E8F0', primaryTextColor:'#ffffff', secondaryTextColor: '#454545', selectedTextColor: '#ffffff', timeSlotTextColor:'#ffffff', availableTextColor: '#ffffff', id:'SB', transparent: true },\n { label: \"enums.client-portal.themes.dusk\", backgroundColor: '#969376', textColor: '#454545', primaryColor:'#878296', secondaryColor: '#e8e8e8', selectedColor: '#878296', availableColor: '#dff0d8', timeSlotColor: '#e8e8e8', inputBorderColor: '#E2E8F0', primaryTextColor:'#ffffff', secondaryTextColor: '#454545', selectedTextColor: '#ffffff', timeSlotTextColor:'#ffffff', availableTextColor: '#ffffff', id:'DK', transparent: true },\n { label: \"enums.client-portal.themes.meadow\", backgroundColor: '#d2e0d4', textColor: '#454545', primaryColor:'#a5998d', secondaryColor: '#e8e8e8', selectedColor: '', availableColor: '#dff0d8', timeSlotColor: '#e8e8e8', inputBorderColor: '#E2E8F0', primaryTextColor:'#ffffff', secondaryTextColor: '#454545', selectedTextColor: '#FFFFFF', timeSlotTextColor:'#ffffff', availableTextColor: '#ffffff', id:'MW', transparent: true },\n { label: \"enums.client-portal.themes.blush\", backgroundColor: '#ffffff', textColor: '#454545', primaryColor:'#f7e1db', secondaryColor: '#e8e8e8', selectedColor: '#e0baa4', availableColor: '#dff0d8', timeSlotColor: '#e8e8e8', inputBorderColor: '#E2E8F0', primaryTextColor:'#454545', secondaryTextColor: '#454545', selectedTextColor: '#454545', timeSlotTextColor:'#ffffff', availableTextColor: '#454545', id:'BH', transparent: true },\n { label: \"enums.client-portal.themes.wild-and-free\", backgroundColor: '#ffffff', textColor: '#e0baa4', primaryColor:'#f0f0f0', secondaryColor: '#e8e8e8', selectedColor: '#e0baa4', availableColor: '#dff0d8', timeSlotColor: '#e8e8e8', inputBorderColor: '#E2E8F0', primaryTextColor:'#e0baa4', secondaryTextColor: '#454545', selectedTextColor: '#e0baa4', timeSlotTextColor:'#ffffff', availableTextColor: '#e0baa4', id:'WF', transparent: true },\n { label: \"enums.client-portal.themes.island-time\", backgroundColor: '#ffffff', textColor: '#cad295', primaryColor:'#2c303a', secondaryColor: '#e8e8e8', selectedColor: '#2c303a', availableColor: '#dff0d8', timeSlotColor: '#e8e8e8', inputBorderColor: '#E2E8F0', primaryTextColor:'#cad295', secondaryTextColor: '#454545', selectedTextColor: '#cad295', timeSlotTextColor:'#ffffff', availableTextColor: '#cad295', id:'IT', transparent: true },\n { label: \"enums.client-portal.themes.neutral\", backgroundColor: '#ffffff', textColor: '#222222', primaryColor:'#9B9A9A', secondaryColor: '#e8e8e8', selectedColor: '#9B9A9A', availableColor: '#dff0d8', timeSlotColor: '#e8e8e8', inputBorderColor: '#E2E8F0', primaryTextColor:'#222222', secondaryTextColor: '#454545', selectedTextColor: '#222222', timeSlotTextColor:'#ffffff', availableTextColor: '#222222', id:'NL', transparent: true }\n ],\n\n maxDateAllowedForBooking: [\n { label: 'common.none', value: 0 },\n { label: 'enums.weeks.1', value: 1 },\n { label: 'enums.weeks.2', value: 2 },\n { label: 'enums.weeks.3', value: 3 },\n { label: 'enums.weeks.4', value: 4 },\n { label: 'enums.months.3', value: 13 },\n { label: 'enums.months.6', value: 26 },\n { label: 'enums.months.9', value: 39 },\n { label: 'enums.years.1', value: 52 },\n ],\n\n greetingTypes: [\n { description: 'enums.client-portal.greeting-types.hidden', value:'' },\n { description: 'enums.client-portal.greeting-types.hi-label', value:'HCN' },\n { description: 'enums.client-portal.greeting-types.welcome-label', value:'WCN' }\n ],\n\n fontTypes: [\n { label: 'enums.client-portal.themes.bl-default', value: 'Default' },\n { label: 'enums.client-portal.font-types.work-sans', value: 'Work Sans' },\n { label: 'enums.client-portal.font-types.merienda', value: 'Merienda' },\n { label: 'enums.client-portal.font-types.open-sans', value: 'Open Sans' },\n { label: 'enums.client-portal.font-types.roboto', value: 'Roboto' },\n { label: 'enums.client-portal.font-types.gaegu', value: 'Gaegu' },\n { label: 'enums.client-portal.font-types.oswald', value: 'Oswald' },\n { label: 'enums.client-portal.font-types.montserrat', value: 'Montserrat' },\n { label: 'enums.client-portal.font-types.raleway', value: 'Raleway' },\n { label: 'enums.client-portal.font-types.karla', value: 'Karla' },\n { label: 'enums.client-portal.font-types.questrial', value: 'Questrial' },\n { label: 'enums.client-portal.font-types.quicksand', value: 'Quicksand' },\n { label: 'enums.client-portal.font-types.rubik', value: 'Rubik' },\n { label: 'enums.client-portal.font-types.rufina', value: 'Rufina' },\n { label: 'enums.client-portal.font-types.overpass', value: 'Overpass' },\n { label: 'enums.client-portal.font-types.amethysta', value: 'Amethysta' },\n { label: 'enums.client-portal.font-types.martel', value: 'Martel' },\n { label: 'enums.client-portal.font-types.calligraffitti', value: 'Calligraffitti' },\n { label: 'enums.client-portal.font-types.donegal-one', value: 'Donegal One' },\n { label: 'enums.client-portal.font-types.nunito', value: 'Nunito' }\n ],\n\n heroImageTypes: [\n { label: 'enums.client-portal.themes.custom', value: '', id:'0' },\n { label: 'Hero Image 1', value: '/assets/img/hero-image-1.jpg', id:'1' },\n { label: 'Hero Image 2', value: '/assets/img/hero-image-2.jpg', id:'2' },\n { label: 'Hero Image 3', value: '/assets/img/hero-image-3.jpg', id:'3' },\n { label: 'Hero Image 4', value: '/assets/img/hero-image-4.jpg', id:'4' },\n { label: 'Hero Image 5', value: '/assets/img/hero-image-5.jpg', id:'5' },\n { label: 'Hero Image 6', value: '/assets/img/hero-image-6.jpg', id:'6' }\n ],\n\n locales: [\n { label: \"enums.locales.united-states\", value: \"US\", defaultLanguage: \"en\" },\n { label: \"enums.locales.canada\", value: \"CA\", defaultLanguage: \"en\" },\n { label: \"enums.locales.united-kingdom\", value: \"UK\", defaultLanguage: \"en\" },\n { label: \"enums.locales.ireland\", value: \"IE\", defaultLanguage: \"en\" },\n { label: \"enums.locales.france\", value: \"FR\", defaultLanguage: \"fr\" },\n { label: \"enums.locales.spain\", value: \"SP\", defaultLanguage: \"es\" },\n { label: \"enums.locales.germany\", value: \"DE\", defaultLanguage: \"de\" },\n { label: \"enums.locales.austria\", value: \"AUT\", defaultLanguage: \"de\" },\n { label: \"enums.locales.belgium\", value: \"BG\", defaultLanguage: \"fr\" },\n { label: \"enums.locales.switzerland\", value: \"SZ\", defaultLanguage: \"fr\" },\n { label: \"enums.locales.luxembourg\", value: \"LX\", defaultLanguage: \"fr\" },\n { label: \"enums.locales.australia\", value: \"AU\", defaultLanguage: \"en\" },\n { label: \"enums.locales.new-zealand\", value: \"NZ\", defaultLanguage: \"en\"},\n { label: \"enums.locales.italy\", value: \"IT\", defaultLanguage: \"it\" },\n { label: \"enums.locales.netherlands\", value: \"NL\", defaultLanguage: \"nl\" },\n { label: \"enums.locales.mexico\", value: \"MX\", defaultLanguage: \"es-mx\" },\n { label: \"enums.locales.romania\", value: \"RM\", defaultLanguage: \"en\" },\n { label: \"enums.locales.denmark\", value: \"DM\", defaultLanguage: \"en\" }\n ],\n\n logoutTimerTypes: [\n {label: \"common.none\", value: \"0\"},\n {label: \"enums.appointment-durations.5\", value: \"5\"},\n {label: \"enums.appointment-durations.10\", value: \"10\"},\n {label: \"enums.appointment-durations.15\", value: \"15\"},\n {label: \"enums.appointment-durations.30\", value: \"30\"},\n {label: \"enums.appointment-durations.60\", value: \"60\"}\n ],\n\n countries: [\n { label: \"enums.countries.afghanistan\", value: \"Afghanistan\", iso: \"AF\", code: \"93\" },\n { label: \"enums.countries.åland-islands\", value: \"Åland Islands\", iso: \"AX\", code: \"358\" },\n { label: \"enums.countries.albania\", value: \"Albania\", iso: \"AL\", code: \"355\" },\n { label: \"enums.countries.algeria\", value: \"Algeria\", iso: \"DZ\", code: \"213\" },\n { label: \"enums.countries.american-samoa\", value: \"American Samoa\", iso: \"AS\", code: \"1684\" },\n { label: \"enums.countries.andorra\", value: \"Andorra\", iso: \"AD\", code: \"376\" },\n { label: \"enums.countries.angola\", value: \"Angola\", iso: \"AO\", code: \"244\" },\n { label: \"enums.countries.anguilla\", value: \"Anguilla\", iso: \"AI\", code: \"1264\" },\n { label: \"enums.countries.antarctica\", value: \"Antarctica\", iso: \"AQ\", code: \"672\" },\n { label: \"enums.countries.antigua-and-barbuda\", value: \"Antigua and Barbuda\", iso: \"AG\", code: \"1268\" },\n { label: \"enums.countries.argentina\", value: \"Argentina\", iso: \"AR\", code: \"54\" },\n { label: \"enums.countries.armenia\", value: \"Armenia\", iso: \"AM\", code: \"374\" },\n { label: \"enums.countries.aruba\", value: \"Aruba\", iso: \"AW\", code: \"297\" },\n { label: \"enums.countries.australia\", value: \"Australia\", iso: \"AU\", code: \"61\" },\n { label: \"enums.countries.austria\", value: \"Austria\", iso: \"AUT\", code: \"43\" },\n { label: \"enums.countries.azerbaijan\", value: \"Azerbaijan\", iso: \"AZ\", code: \"994\" },\n { label: \"enums.countries.bahamas\", value: \"Bahamas\", iso: \"BS\", code: \"1242\" },\n { label: \"enums.countries.bahrain\", value: \"Bahrain\", iso: \"BH\", code: \"973\" },\n { label: \"enums.countries.bangladesh\", value: \"Bangladesh\", iso: \"BD\", code: \"880\" },\n { label: \"enums.countries.barbados\", value: \"Barbados\", iso: \"BB\", code: \"1246\" },\n { label: \"enums.countries.belarus\", value: \"Belarus\", iso: \"BY\", code: \"375\" },\n { label: \"enums.countries.belgium\", value: \"Belgium\", iso: \"BE\", code: \"32\" },\n { label: \"enums.countries.belize\", value: \"Belize\", iso: \"BZ\", code: \"501\" },\n { label: \"enums.countries.benin\", value: \"Benin\", iso: \"BJ\", code: \"229\" },\n { label: \"enums.countries.bermuda\", value: \"Bermuda\", iso: \"BM\", code: \"1441\" },\n { label: \"enums.countries.bhutan\", value: \"Bhutan\", iso: \"BT\", code: \"975\" },\n { label: \"enums.countries.bolivia\", value: \"Bolivia\", iso: \"BO\", code: \"591\" },\n { label: \"enums.countries.bonaire\", value: \"Bonaire\", iso: \"BQ\", code: \"599\" },\n { label: \"enums.countries.bosnia-and-herzegovina\", value: \"Bosnia and Herzegovina\", iso: \"BA\", code: \"387\" },\n { label: \"enums.countries.botswana\", value: \"Botswana\", iso: \"BW\", code: \"267\" },\n { label: \"enums.countries.bouvet-island\", value: \"Bouvet Island\", iso: \"BV\", code: \"47\" },\n { label: \"enums.countries.brazil\", value: \"Brazil\", iso: \"BR\", code: \"55\" },\n { label: \"enums.countries.british-indian-ocean-territory\", value: \"British Indian Ocean Territory\", iso: \"IO\", code: \"246\" },\n { label: \"enums.countries.brunei-darussalam\", value: \"Brunei Darussalam\", iso: \"BM\", code: \"673\" },\n { label: \"enums.countries.bulgaria\", value: \"Bulgaria\", iso: \"BG\", code: \"359\" },\n { label: \"enums.countries.burkina faso\", value: \"Burkina Faso\", iso: \"BF\", code: \"226\" },\n { label: \"enums.countries.burundi\", value: \"Burundi\", iso: \"BI\", code: \"257\" },\n { label: \"enums.countries.cambodia\", value: \"Cambodia\", iso: \"KH\", code: \"855\" },\n { label: \"enums.countries.cameroon\", value: \"Cameroon\", iso: \"CM\", code: \"237\" },\n { label: \"enums.countries.canada\", value: \"Canada\", iso: \"CA\", code: \"1\" },\n { label: \"enums.countries.cape-verde\", value: \"Cape Verde\", iso: \"CV\", code: \"238\" },\n { label: \"enums.countries.cayman-islands\", value: \"Cayman Islands\", iso: \"KY\", code: \"1345\" },\n { label: \"enums.countries.central-african-republic\", value: \"Central African Republic\", iso: \"CF\", code: \"236\" },\n { label: \"enums.countries.chad\", value: \"Chad\", iso: \"TD\", code: \"235\" },\n { label: \"enums.countries.chile\", value: \"Chile\", iso: \"CL\", code: \"56\" },\n { label: \"enums.countries.china\", value: \"China\", iso: \"CN\", code: \"86\" },\n { label: \"enums.countries.christmas-island\", value: \"Christmas Island\", iso: \"CX\", code: \"61\" },\n { label: \"enums.countries.cocos-islands\", value: \"Cocos (Keeling) Islands\", iso: \"CC\", code: \"61\" },\n { label: \"enums.countries.colombia\", value: \"Colombia\", iso: \"CO\", code: \"57\" },\n { label: \"enums.countries.comoros\", value: \"Comoros\", iso: \"KM\", code: \"269\" },\n { label: \"enums.countries.congo\", value: \"Congo\", iso: \"CG\", code: \"242\" },\n { label: \"enums.countries.congo-the-democratic-republic-of-the\", value: \"Congo, the Democratic Republic of the\", iso: \"CD\", code: \"243\" },\n { label: \"enums.countries.cook-islands\", value: \"Cook Islands\", iso: \"CK\", code: \"682\" },\n { label: \"enums.countries.costa-rica\", value: \"Costa Rica\", iso: \"CR\", code: \"506\" },\n { label: \"enums.countries.côte-d'ivoire\", value: \"Côte d'Ivoire\", iso: \"CI\", code: \"225\" },\n { label: \"enums.countries.croatia\", value: \"Croatia\", iso: \"HR\", code: \"385\" },\n { label: \"enums.countries.cuba\", value: \"Cuba\", iso: \"CU\", code: \"53\" },\n { label: \"enums.countries.curaçao\", value: \"Curaçao\", iso: \"CW\", code: \"5999\" },\n { label: \"enums.countries.cyprus\", value: \"Cyprus\", iso: \"CY\", code: \"357\" },\n { label: \"enums.countries.czech-republic\", value: \"Czech Republic\", iso: \"CZ\", code: \"420\" },\n { label: \"enums.countries.denmark\", value: \"Denmark\", iso: \"DK\", code: \"45\" },\n { label: \"enums.countries.djibouti\", value: \"Djibouti\", iso: \"DJ\", code: \"253\" },\n { label: \"enums.countries.dominica\", value: \"Dominica\", iso: \"DM\", code: \"1767\" },\n { label: \"enums.countries.dominican-republic\", value: \"Dominican Republic\", iso: \"DO\", code: \"1809\" },\n { label: \"enums.countries.ecuador\", value: \"Ecuador\", iso: \"EC\", code: \"593\" },\n { label: \"enums.countries.egypt\", value: \"Egypt\", iso: \"EG\", code: \"20\" },\n { label: \"enums.countries.el-salvador\", value: \"El Salvador\", iso: \"SV\", code: \"503\" },\n { label: \"enums.countries.equatorial-guinea\", value: \"Equatorial Guinea\", iso: \"GQ\", code: \"240\" },\n { label: \"enums.countries.eritrea\", value: \"Eritrea\", iso: \"ER\", code: \"291\" },\n { label: \"enums.countries.estonia\", value: \"Estonia\", iso: \"EE\", code: \"372\" },\n { label: \"enums.countries.ethiopia\", value: \"Ethiopia\", iso: \"ET\", code: \"251\" },\n { label: \"enums.countries.falkland-islands\", value: \"Falkland Islands (Malvinas)\", iso: \"FK\", code: \"500\" },\n { label: \"enums.countries.faroe-islands\", value: \"Faroe Islands\", iso: \"FO\", code: \"298\" },\n { label: \"enums.countries.fiji\", value: \"Fiji\", iso: \"FJ\", code: \"679\" },\n { label: \"enums.countries.finland\", value: \"Finland\", iso: \"FI\", code: \"358\" },\n { label: \"enums.countries.france\", value: \"France\", iso: \"FR\", code: \"33\" },\n { label: \"enums.countries.french-guiana\", value: \"French Guiana\", iso: \"GF\", code: \"594\" },\n { label: \"enums.countries.french-polynesia\", value: \"French Polynesia\", iso: \"PF\", code: \"689\" },\n { label: \"enums.countries.french-southern-territories\", value: \"French Southern Territories\", iso: \"TF\", code: \"596\" },\n { label: \"enums.countries.gabon\", value: \"Gabon\", iso: \"GA\", code: \"241\" },\n { label: \"enums.countries.gambia\", value: \"Gambia\", iso: \"GM\", code: \"220\" },\n { label: \"enums.countries.georgia\", value: \"Georgia\", iso: \"GE\", code: \"995\" },\n { label: \"enums.countries.germany\", value: \"Germany\", iso: \"DE\", code: \"49\" },\n { label: \"enums.countries.ghana\", value: \"Ghana\", iso: \"GH\", code: \"233\" },\n { label: \"enums.countries.gibraltar\", value: \"Gibraltar\", iso: \"GI\", code: \"350\" },\n { label: \"enums.countries.greece\", value: \"Greece\", iso: \"GR\", code: \"30\" },\n { label: \"enums.countries.greenland\", value: \"Greenland\", iso: \"GL\", code: \"299\" },\n { label: \"enums.countries.grenada\", value: \"Grenada\", iso: \"GD\", code: \"1473\" },\n { label: \"enums.countries.guadeloupe\", value: \"Guadeloupe\", iso: \"GP\", code: \"590\" },\n { label: \"enums.countries.guam\", value: \"Guam\", iso: \"GU\", code: \"1671\" },\n { label: \"enums.countries.guatemala\", value: \"Guatemala\", iso: \"GT\", code: \"502\" },\n { label: \"enums.countries.guernsey\", value: \"Guernsey\", iso: \"GG\", code: \"441481\" },\n { label: \"enums.countries.guinea\", value: \"Guinea\", iso: \"GN\", code: \"224\" },\n { label: \"enums.countries.guinea-bissau\", value: \"Guinea-Bissau\", iso: \"GW\", code: \"245\" },\n { label: \"enums.countries.guyana\", value: \"Guyana\", iso: \"GY\", code: \"592\" },\n { label: \"enums.countries.haiti\", value: \"Haiti\", iso: \"HT\", code: \"509\" },\n { label: \"enums.countries.heard-island-and-mcdonald-islands\", value: \"Heard Island and McDonald Islands\", iso: \"HM\", code: \"334\" },\n { label: \"enums.countries.holy-see\", value: \"Holy See (Vatican City State)\", iso: \"VA\", code: \"39\" },\n { label: \"enums.countries.honduras\", value: \"Honduras\", iso: \"HN\", code: \"504\" },\n { label: \"enums.countries.hong-kong\", value: \"Hong Kong\", iso: \"HK\", code: \"852\" },\n { label: \"enums.countries.hungary\", value: \"Hungary\", iso: \"HU\", code: \"36\" },\n { label: \"enums.countries.iceland\", value: \"Iceland\", iso: \"IS\", code: \"354\" },\n { label: \"enums.countries.india\", value: \"India\", iso: \"IN\", code: \"91\" },\n { label: \"enums.countries.indonesia\", value: \"Indonesia\", iso: \"ID\", code: \"62\" },\n { label: \"enums.countries.iran\", value: \"Iran, Islamic Republic of\", iso: \"IR\", code: \"98\" },\n { label: \"enums.countries.iraq\", value: \"Iraq\", iso: \"IQ\", code: \"964\" },\n { label: \"enums.countries.ireland\", value: \"Ireland\", iso: \"IE\", code: \"353\" },\n { label: \"enums.countries.isle-of-man\", value: \"Isle of Man\", iso: \"IM\", code: \"447924\" },\n { label: \"enums.countries.israel\", value: \"Israel\", iso: \"IL\", code: \"972\" },\n { label: \"enums.countries.italy\", value: \"Italy\", iso: \"IT\", code: \"39\" },\n { label: \"enums.countries.jamaica\", value: \"Jamaica\", iso: \"JM\", code: \"1876\" },\n { label: \"enums.countries.japan\", value: \"Japan\", iso: \"JP\", code: \"81\" },\n { label: \"enums.countries.jersey\", value: \"Jersey\", iso: \"JE\", code: \"441534\" },\n { label: \"enums.countries.jordan\", value: \"Jordan\", iso: \"JO\", code: \"962\" },\n { label: \"enums.countries.kazakhstan\", value: \"Kazakhstan\", iso: \"KZ\", code: \"76\" },\n { label: \"enums.countries.kenya\", value: \"Kenya\", iso: \"KE\", code: \"254\" },\n { label: \"enums.countries.kiribati\", value: \"Kiribati\", iso: \"KI\", code: \"686\" },\n { label: \"enums.countries.korea-north\", value: \"North Korea\", iso: \"KP\", code: \"850\" },\n { label: \"enums.countries.korea-south\", value: \"South Korea\", iso: \"KR\", code: \"82\" },\n { label: \"enums.countries.kuwait\", value: \"Kuwait\", iso: \"KW\", code: \"965\" },\n { label: \"enums.countries.kyrgyzstan\", value: \"Kyrgyzstan\", iso: \"KG\", code: \"996\" },\n { label: \"enums.countries.lao-people's-democratic-republic\", value: \"Lao\", iso: \"LA\", code: \"856\" },\n { label: \"enums.countries.latvia\", value: \"Latvia\", iso: \"LV\", code: \"371\" },\n { label: \"enums.countries.lebanon\", value: \"Lebanon\", iso: \"LB\", code: \"961\" },\n { label: \"enums.countries.lesotho\", value: \"Lesotho\", iso: \"LS\", code: \"266\" },\n { label: \"enums.countries.liberia\", value: \"Liberia\", iso: \"LR\", code: \"231\" },\n { label: \"enums.countries.libya\", value: \"Libya\", iso: \"LY\", code: \"218\" },\n { label: \"enums.countries.liechtenstein\", value: \"Liechtenstein\", iso: \"LI\", code: \"423\" },\n { label: \"enums.countries.lithuania\", value: \"Lithuania\", iso: \"LT\", code: \"370\" },\n { label: \"enums.countries.luxembourg\", value: \"Luxembourg\", iso: \"LU\", code: \"352\" },\n { label: \"enums.countries.macao\", value: \"Macao\", iso: \"MO\", code: \"853\" },\n { label: \"enums.countries.macedonia\", value: \"Macedonia\", iso: \"MK\", code: \"389\" },\n { label: \"enums.countries.madagascar\", value: \"Madagascar\", iso: \"MG\", code: \"261\" },\n { label: \"enums.countries.malawi\", value: \"Malawi\", iso: \"MW\", code: \"265\" },\n { label: \"enums.countries.malaysia\", value: \"Malaysia\", iso: \"MY\", code: \"60\" },\n { label: \"enums.countries.maldives\", value: \"Maldives\", iso: \"MV\", code: \"960\" },\n { label: \"enums.countries.mali\", value: \"Mali\", iso: \"ML\", code: \"223\" },\n { label: \"enums.countries.malta\", value: \"Malta\", iso: \"MT\", code: \"356\" },\n { label: \"enums.countries.marshall-islands\", value: \"Marshall Islands\", iso: \"MH\", code: \"692\" },\n { label: \"enums.countries.martinique\", value: \"Martinique\", iso: \"MQ\", code: \"596\" },\n { label: \"enums.countries.mauritania\", value: \"Mauritania\", iso: \"MR\", code: \"222\" },\n { label: \"enums.countries.mauritius\", value: \"Mauritius\", iso: \"MU\", code: \"230\" },\n { label: \"enums.countries.mayotte\", value: \"Mayotte\", iso: \"YT\", code: \"262269\" },\n { label: \"enums.countries.mexico\", value: \"Mexico\", iso: \"MX\", code: \"52\" },\n { label: \"enums.countries.micronesia\", value: \"Micronesia\", iso: \"FM\", code: \"691\" },\n { label: \"enums.countries.moldova\", value: \"Moldova\", iso: \"MD\", code: \"373\" },\n { label: \"enums.countries.monaco\", value: \"Monaco\", iso: \"MC\", code: \"377\" },\n { label: \"enums.countries.mongolia\", value: \"Mongolia\", iso: \"MN\", code: \"976\" },\n { label: \"enums.countries.montenegro\", value: \"Montenegro\", iso: \"ME\", code: \"382\" },\n { label: \"enums.countries.montserrat\", value: \"Montserrat\", iso: \"MS\", code: \"1664\" },\n { label: \"enums.countries.morocco\", value: \"Morocco\", iso: \"MA\", code: \"212\" },\n { label: \"enums.countries.mozambique\", value: \"Mozambique\", iso: \"MZ\", code: \"258\" },\n { label: \"enums.countries.myanmar\", value: \"Myanmar\", iso: \"MM\", code: \"95\" },\n { label: \"enums.countries.namibia\", value: \"Namibia\", iso: \"NA\", code: \"264\" },\n { label: \"enums.countries.nauru\", value: \"Nauru\", iso: \"NR\", code: \"674\" },\n { label: \"enums.countries.nepal\", value: \"Nepal\", iso: \"NP\", code: \"977\" },\n { label: \"enums.countries.netherlands\", value: \"Netherlands\", iso: \"NL\", code: \"31\" },\n { label: \"enums.countries.new-caledonia\", value: \"New Caledonia\", iso: \"NC\", code: \"687\" },\n { label: \"enums.countries.new-zealand\", value: \"New Zealand\", iso: \"NZ\", code: \"64\" },\n { label: \"enums.countries.nicaragua\", value: \"Nicaragua\", iso: \"NI\", code: \"505\" },\n { label: \"enums.countries.niger\", value: \"Niger\", iso: \"NE\", code: \"227\" },\n { label: \"enums.countries.nigeria\", value: \"Nigeria\", iso: \"NG\", code: \"234\" },\n { label: \"enums.countries.niue\", value: \"Niue\", iso: \"NU\", code: \"683\" },\n { label: \"enums.countries.norfolk-island\", value: \"Norfolk Island\", iso: \"NF\", code: \"672\" },\n { label: \"enums.countries.northern-mariana-islands\", value: \"Northern Mariana Islands\", iso: \"MP\", code: \"1670\" },\n { label: \"enums.countries.norway\", value: \"Norway\", iso: \"NO\", code: \"47\" },\n { label: \"enums.countries.oman\", value: \"Oman\", iso: \"OM\", code: \"968\" },\n { label: \"enums.countries.pakistan\", value: \"Pakistan\", iso: \"PK\", code: \"92\" },\n { label: \"enums.countries.palau\", value: \"Palau\", iso: \"PW\", code: \"680\" },\n { label: \"enums.countries.palestinian-territory\", value: \"Palestinian\", iso: \"PS\", code: \"970\" },\n { label: \"enums.countries.panama\", value: \"Panama\", iso: \"PA\", code: \"507\" },\n { label: \"enums.countries.papua-new-guinea\", value: \"Papua New Guinea\", iso: \"PG\", code: \"675\" },\n { label: \"enums.countries.paraguay\", value: \"Paraguay\", iso: \"PY\", code: \"595\" },\n { label: \"enums.countries.peru\", value: \"Peru\", iso: \"PE\", code: \"51\" },\n { label: \"enums.countries.philippines\", value: \"Philippines\", iso: \"PH\", code: \"63\" },\n { label: \"enums.countries.pitcairn\", value: \"Pitcairn\", iso: \"PN\", code: \"64\" },\n { label: \"enums.countries.poland\", value: \"Poland\", iso: \"PL\", code: \"48\" },\n { label: \"enums.countries.portugal\", value: \"Portugal\", iso: \"PT\", code: \"351\" },\n { label: \"enums.countries.puerto-rico\", value: \"Puerto Rico\", iso: \"PR\", code: \"1787\" },\n { label: \"enums.countries.qatar\", value: \"Qatar\", iso: \"QA\", code: \"974\" },\n { label: \"enums.countries.réunion\", value: \"Réunion\", iso: \"RE\", code: \"262\" },\n { label: \"enums.countries.romania\", value: \"Romania\", iso: \"RO\", code: \"40\" },\n { label: \"enums.countries.russian-federation\", value: \"Russia\", iso: \"RU\", code: \"7\" },\n { label: \"enums.countries.rwanda\", value: \"Rwanda\", iso: \"RW\", code: \"250\" },\n { label: \"enums.countries.saint-barthélemy\", value: \"Saint Barthélemy\", iso: \"BL\", code: \"590\" },\n { label: \"enums.countries.saint-helena\", value: \"Saint Helena, Ascension and Tristan da Cunha\", iso: \"SH\", code: \"290\" },\n { label: \"enums.countries.saint-kitts\", value: \"Saint Kitts and Nevis\", iso: \"KN\", code: \"1869\" },\n { label: \"enums.countries.saint-lucia\", value: \"Saint Lucia\", iso: \"LC\", code: \"1758\" },\n { label: \"enums.countries.saint-martin\", value: \"Saint Martin\", iso: \"MF\", code: \"590\" },\n { label: \"enums.countries.saint-pierre-and-miquelon\", value: \"Saint Pierre and Miquelon\", iso: \"PM\", code: \"508\" },\n { label: \"enums.countries.saint-vincent\", value: \"Saint Vincent and the Grenadines\", iso: \"VC\", code: \"1784\" },\n { label: \"enums.countries.samoa\", value: \"Samoa\", iso: \"WS\", code: \"685\" },\n { label: \"enums.countries.san-marino\", value: \"San Marino\", iso: \"SM\", code: \"378\" },\n { label: \"enums.countries.sao-tome-and-principe\", value: \"Sao Tome and Principe\", iso: \"ST\", code: \"239\" },\n { label: \"enums.countries.saudi-arabia\", value: \"Saudi Arabia\", iso: \"SA\", code: \"966\" },\n { label: \"enums.countries.senegal\", value: \"Senegal\", iso: \"SN\", code: \"221\" },\n { label: \"enums.countries.serbia\", value: \"Serbia\", iso: \"RS\", code: \"381\" },\n { label: \"enums.countries.seychelles\", value: \"Seychelles\", iso: \"SC\", code: \"248\" },\n { label: \"enums.countries.sierra-leone\", value: \"Sierra Leone\", iso: \"SL\", code: \"232\" },\n { label: \"enums.countries.singapore\", value: \"Singapore\", iso: \"SG\", code: \"65\" },\n { label: \"enums.countries.sint-maarten\", value: \"Sint Maarten\", iso: \"SX\", code: \"1721\" },\n { label: \"enums.countries.slovakia\", value: \"Slovakia\", iso: \"SK\", code: \"421\" },\n { label: \"enums.countries.slovenia\", value: \"Slovenia\", iso: \"SI\", code: \"386\" },\n { label: \"enums.countries.solomon-islands\", value: \"Solomon Islands\", iso: \"SB\", code: \"677\" },\n { label: \"enums.countries.somalia\", value: \"Somalia\", iso: \"SO\", code: \"252\" },\n { label: \"enums.countries.south-africa\", value: \"South Africa\", iso: \"ZA\", code: \"27\" },\n { label: \"enums.countries.south-georgia\", value: \"South Georgia and the South Sandwich Islands\", iso: \"GS\", code: \"500\" },\n { label: \"enums.countries.south-sudan\", value: \"South Sudan\", iso: \"SS\", code: \"211\" },\n { label: \"enums.countries.spain\", value: \"Spain\", iso: \"ES\", code: \"34\" },\n { label: \"enums.countries.sri-lanka\", value: \"Sri Lanka\", iso: \"LK\", code: \"94\" },\n { label: \"enums.countries.sudan\", value: \"Sudan\", iso: \"SD\", code: \"249\" },\n { label: \"enums.countries.suriname\", value: \"Suriname\", iso: \"SR\", code: \"597\" },\n { label: \"enums.countries.svalbard-and-jan-mayen\", value: \"Svalbard and Jan Mayen\", iso: \"SJ\", code: \"4779\" },\n { label: \"enums.countries.swaziland\", value: \"Swaziland\", iso: \"SZ\", code: \"268\" },\n { label: \"enums.countries.sweden\", value: \"Sweden\", iso: \"SE\", code: \"46\" },\n { label: \"enums.countries.switzerland\", value: \"Switzerland\", iso: \"CH\", code: \"41\" },\n { label: \"enums.countries.syrian-arab-republic\", value: \"Syrian Arab Republic\", iso: \"SY\", code: \"963\" },\n { label: \"enums.countries.taiwan\", value: \"Taiwan\", iso: \"TW\", code: \"886\" },\n { label: \"enums.countries.tajikistan\", value: \"Tajikistan\", iso: \"TJ\", code: \"992\" },\n { label: \"enums.countries.tanzania\", value: \"Tanzania\", iso: \"TZ\", code: \"255\" },\n { label: \"enums.countries.thailand\", value: \"Thailand\", iso: \"TH\", code: \"66\" },\n { label: \"enums.countries.timor-leste\", value: \"Timor-Leste\", iso: \"TL\", code: \"670\" },\n { label: \"enums.countries.togo\", value: \"Togo\", iso: \"TG\", code: \"228\" },\n { label: \"enums.countries.tokelau\", value: \"Tokelau\", iso: \"TK\", code: \"690\" },\n { label: \"enums.countries.tonga\", value: \"Tonga\", iso: \"TO\", code: \"676\" },\n { label: \"enums.countries.trinidad-and-tobago\", value: \"Trinidad and Tobago\", iso: \"TT\", code: \"1868\" },\n { label: \"enums.countries.tunisia\", value: \"Tunisia\", iso: \"TN\", code: \"216\" },\n { label: \"enums.countries.turkey\", value: \"Turkey\", iso: \"TR\", code: \"90\" },\n { label: \"enums.countries.turkmenistan\", value: \"Turkmenistan\", iso: \"TM\", code: \"993\" },\n { label: \"enums.countries.turks-and-caicos-islands\", value: \"Turks and Caicos Islands\", iso: \"TC\", code: \"1649\" },\n { label: \"enums.countries.tuvalu\", value: \"Tuvalu\", iso: \"TV\", code: \"688\" },\n { label: \"enums.countries.uganda\", value: \"Uganda\", iso: \"UG\", code: \"256\" },\n { label: \"enums.countries.ukraine\", value: \"Ukraine\", iso: \"UA\", code: \"380\" },\n { label: \"enums.countries.united-arab-emirates\", value: \"United Arab Emirates\", iso: \"AE\", code: \"971\" },\n { label: \"enums.countries.united-kingdom\", value: \"United Kingdom\", iso: \"GB\", code: \"44\" },\n { label: \"enums.countries.united-states\", value: \"United States\", iso: \"US\", code: \"1\" },\n { label: \"enums.countries.united-states-minor-outlying-islands\", value: \"United States Minor Outlying Islands\", iso: \"UM\", code: \"\" },\n { label: \"enums.countries.uruguay\", value: \"Uruguay\", iso: \"UY\", code: \"598\" },\n { label: \"enums.countries.uzbekistan\", value: \"Uzbekistan\", iso: \"UZ\", code: \"998\" },\n { label: \"enums.countries.vanuatu\", value: \"Vanuatu\", iso: \"VU\", code: \"678\" },\n { label: \"enums.countries.venezuela\", value: \"Venezuela\", iso: \"VE\", code: \"58\" },\n { label: \"enums.countries.viet-nam\", value: \"Viet Nam\", iso: \"VN\", code: \"84\" },\n { label: \"enums.countries.virgin-islands-british\", value: \"Virgin Islands, British\", iso: \"VG\", code: \"1284\" },\n { label: \"enums.countries.virgin-islands-u.s.\", value: \"Virgin Islands, U.S.\", iso: \"VI\", code: \"1340\" },\n { label: \"enums.countries.wallis-and-futuna\", value: \"Wallis and Futuna\", iso: \"WF\", code: \"681\" },\n { label: \"enums.countries.western-sahara\", value: \"Western Sahara\", iso: \"EH\", code: \"212\" },\n { label: \"enums.countries.yemen\", value: \"Yemen\", iso: \"YE\", code: \"967\" },\n { label: \"enums.countries.zambia\", value: \"Zambia\", iso: \"ZM\", code: \"260\" },\n { label: \"enums.countries.zimbabwe\", value: \"Zimbabwe\", iso: \"ZE\", code: \"263\" }\n ],\n\n languages: [\n { label: \"enums.languages.english\", value: \"en\" },\n { label: \"enums.languages.french\", value: \"fr\" },\n { label: \"enums.languages.spanish\", value: \"es\" },\n { label: \"enums.languages.german\", value: \"de\" },\n { label: \"enums.languages.italian\", value: \"it\" },\n { label: \"enums.languages.dutch\", value: \"nl\" },\n { label: \"enums.languages.spanish-mexico\", value: \"es-mx\" }\n ],\n\n phoneTypes: {\n home: { description: 'enums.phone-types.home', abbr: \"H\", id: 1 },\n work: { description: 'enums.phone-types.work', abbr: \"W\", id: 2 },\n mobile: { description: 'enums.phone-types.mobile', abbr: \"M\", id: 3 }\n },\n\n paymentMethodCategories: [\n {description: 'enums.payment-types.cash', id: 1},\n {description: 'enums.payment-types.check', id: 2},\n {description: 'enums.payment-types.credit-card', id: 3},\n {description: 'enums.payment-types.other', id: 0}\n ],\n\n paymentPlanFrequencies: [\n { description: 'enums.payment-plans.frequencies.monthly', value: 'M' },\n { description: 'enums.payment-plans.frequencies.weekly', value: 'W' },\n { description: 'enums.payment-plans.frequencies.every-other-week', value: 'EOW' }\n ],\n\n physicalInventoryItemTypes: [\n { description: 'common.all', value: '' },\n { description: 'enums.physical-inventory-item-types.items-scanned', value: 'SN' },\n { description: 'enums.physical-inventory-item-types.items-not-scanned', value: 'NS' },\n { description: 'enums.physical-inventory-item-types.items-adjusted', value: 'IA' }\n ],\n\n portalMileStoneTypes: [\n { label: 'enums.portal-event-management-step-milestone.measurements', value: 'M' },\n { label: 'enums.portal-event-management-step-milestone.transaction-created', value: 'TC' },\n { label: 'enums.portal-event-management-step-milestone.one-payment', value: 'PA1' },\n { label: 'enums.portal-event-management-step-milestone.all-items-received', value: 'AR' },\n { label: 'enums.portal-event-management-step-milestone.picked-up-one', value: 'PU1' },\n { label: 'enums.portal-event-management-step-milestone.full-payment', value: 'PA2' },\n { label: 'enums.portal-event-management-step-milestone.picked-up-all', value: 'PU2' },\n { label: 'enums.portal-event-management-step-milestone.feedback', value: 'F' }\n ],\n\n portalMessageSettingMilestoneTypes: [\n { label: 'enums.portal-message-setting-milestone.approved', value: 'A' },\n { label: 'enums.portal-message-setting-milestone.updated', value: 'U' },\n { label: 'enums.portal-message-setting-milestone.deleted', value: 'D' },\n { label: 'enums.portal-message-setting-milestone.created', value: 'C' }\n ],\n\n portalMessageSettingTypes: [\n { label: 'enums.portal-message-setting-type.contact-update-request', value: 'CUR' },\n { label: 'enums.portal-message-setting-type.payment-update-request', value: 'PUR' },\n { label: 'enums.portal-message-setting-type.payment-plan-update-request', value: 'PPUR' },\n { label: 'enums.portal-message-setting-type.measurements-request', value: 'MR' },\n { label: 'enums.portal-message-setting-type.event-registration', value: 'ER' },\n { label: 'enums.portal-message-setting-type.event-update', value: 'EU' }\n ],\n\n portalViews: [\n // { label: 'settings.client-portal-preferences.advanced-settings.general.views.appointments', value: 'appointments', path:'appointments' },\n { label: 'settings.client-portal-preferences.advanced-settings.general.views.dashboard', value: 'dashboard', path: null },\n { label: 'settings.client-portal-preferences.advanced-settings.general.views.orders', value: 'orders', path:'dashboard.my_orders' },\n { label: 'settings.client-portal-preferences.advanced-settings.general.views.events', value: 'events', path:'dashboard.my_event' },\n { label: 'settings.client-portal-preferences.advanced-settings.general.views.measurements', value: 'measurements', path:'measurements' },\n { label: 'settings.client-portal-preferences.advanced-settings.general.views.lookbook', value: 'lookbook', path:'lookbook' },\n { label: 'settings.client-portal-preferences.advanced-settings.general.views.billing', value: 'billing', path:'billing' }\n ],\n\n privateLabelAlgorithms: [\n { description: 'enums.private-label-algorithm.reverse-vendor-item-name', value: '0'},\n { description: 'enums.private-label-algorithm.vc-plus-vendor-item-name', value: '1'},\n { description: 'enums.private-label-algorithm.vc-plus-reverse-vendor-item-name', value: '2'},\n { description: 'enums.private-label-algorithm.vc-plus-vendor-item-name-plus-dc', value: '3'},\n { description: 'enums.private-label-algorithm.vc-plus-reverse-vendor-item-name-plus-dc', value: '4'},\n { description: 'enums.private-label-algorithm.vendor-item-name-plus-color-plus-size', value: '5'},\n { description:'enums.private-label-algorithm.vc-plus-random-four-digits', value: '6'}\n ],\n\n salesPerformanceOverViewTypes: [\n { description: 'reports.associate.commission-report', value: 'CMR' },\n { description: 'reports.sales.by-associate', value: 'SBAR' },\n { description: 'reports.associate.sales-performance-payment-based', value: 'SPR' },\n { description: 'reports.associate.sales-performance-transaction-based', value: 'SPRT'}\n ],\n\n timeOffReasons: [\n {description: 'settings.employee.time-off-type.vacation', value: 'VAC'},\n {description: 'settings.employee.time-off-type.holiday', value: 'HOL'},\n {description: 'settings.employee.time-off-type.pto', value: 'PTO'},\n {description: 'settings.employee.time-off-type.sick', value: 'SIC'},\n {description: 'settings.employee.time-off-type.jury-duty', value: 'JRY'},\n {description: 'settings.employee.time-off-type.bereavement', value: 'BRV'},\n {description: 'settings.employee.time-off-type.other', value: 'OTH'}\n ],\n\n trxTypes: {\n all: { description: 'common.all', value: -1 },\n sale: { description: 'transaction.sale', abbr: 'S', value: 1 },\n special_order: { description: 'transaction.special-order', abbr: 'SO', value: 2 },\n return_trx: { description: 'transaction.return', abbr: 'R', value: 3 },\n layaway: { description: 'transaction.layaway', abbr: 'L', value: 4 }\n },\n\n trxTypesAndQuote: {\n all: { description: 'common.all', value: -1 },\n sale: { description: 'transaction.sale', abbr: 'S', value: 1 },\n special_order: { description: 'transaction.special-order', abbr: 'SO', value: 2 },\n return_trx: { description: 'transaction.return', abbr: 'R', value: 3 },\n layaway: { description: 'transaction.layaway', abbr: 'L', value: 4 },\n quote: { description: 'quote.quote', abbr: 'Q', value: 5 }\n },\n\n labelTemplates: [\n { description: 'enums.labels.avery5160', id: 'averyItem5160' },\n { description: 'enums.labels.avery5167', id: 'averyItem5167' },\n { description: 'enums.labels.dymo-small', id: 'dymoItemSmall' },\n { description: 'enums.labels.dymo-eu-label', id: 'dymoItemEU' },\n { description: 'enums.labels.dymo-large', id: 'dymoItem' },\n { description: 'enums.labels.dymo-large-shipping', id: 'dymoItemLarge' }\n ],\n\n plans: [\n {name:'enums.plans.free', id: \"1\", signupDescription: 'enums.plans.free-plan', price: 0.00 },\n {name:'enums.plans.basic', id: \"2\", signupDescription: 'enums.plans.basic-plan-30-day-free-trial', price: 99.99 },\n {name:'enums.plans.standard', id: \"3\", signupDescription: 'enums.plans.standard-plan-30-day-free-trial', price: 125.00 },\n {name:'enums.plans.standard-plus', id: \"5\", signupDescription: 'enums.plans.standard-plus-plan-30-day-free-trial', price: 199.00 },\n {name:'enums.plans.elite', id: \"4\", signupDescription: 'enums.plans.elite-plan-30-day-free-trial', price: 249.00 }\n ],\n\n months: [\n { id: 0, month: 'settings.months.0' }, { id: 1, month: 'settings.months.1' }, { id: 2, month: 'settings.months.2' }, { id: 3, month: 'settings.months.3' },\n { id: 4, month: 'settings.months.4' }, { id: 5, month: 'settings.months.5' }, { id: 6, month: 'settings.months.6' }, { id: 7, month: 'settings.months.7' },\n { id: 8, month: 'settings.months.8' }, { id: 9, month: 'settings.months.9' }, { id: 10, month: 'settings.months.10' }, { id: 11, month: 'settings.months.11' }\n ],\n\n marketplaceCategories: [\n { name: 'Bridal Gowns', value: 'MKT_CAT_BRIDAL_GOWNS', id: 1 },\n { name: 'Bridesmaid Dresses', value: 'MKT_CAT_BRIDESMAID_DRESSES', id: 2 },\n { name: 'Accessories', value: 'MKT_CAT_ACCESSORIES', id: 3 },\n { name: 'Formals', value: 'MKT_CAT_FORMALS', id: 4 },\n { name: 'Prom Dresses', value: 'MKT_CAT_PROM_DRESSES', id: 5 },\n { name: 'Flower Girl Dresses', value: 'MKT_CAT_FLOWER_GIRL_DRESSES', id: 6 },\n { name: 'Mothers', value: 'MKT_CAT_MOTHERS', id: 7 },\n { name: 'Headpieces', value: 'MKT_CAT_HEADPIECES', id: 8 },\n { name: 'Veils', value: 'MKT_CAT_VEILS', id: 9 },\n { name: 'Jewelry', value: 'MKT_CAT_JEWELRY', id: 11 },\n { name: 'Lingerie', value: 'MKT_CAT_LINGERIE', id: 12 },\n { name: 'Shoes', value: 'MKT_CAT_SHOES', id: 13 },\n { name: 'Men\\'s Wear', value: 'MKT_CAT_MENS_WEAR', id: 14 }\n ],\n\n marketplaceFilterType: {\n all: { description: \"common.all\", value: '' },\n linked: { description: \"common.linked\", value: 'LM' },\n unlinked: { description: \"common.unlinked\", value: 'UM' }\n },\n\n nf525JetTypes: {\n archiving_period: { value: 20, description: \"Archiving period\" },\n archiving_fiscal_year: { value: 30, description: \"Archiving fiscal year\" },\n terminal_shutdown: { value: 40, description: \"Terminal shutdown\" },\n period_closing: { value: 50, description: \"End of period\" },\n fiscal_year_closing: { value: 60, description: \"Year-end closing\" },\n offline_mode_start: { value: 70, description: \"Start of offline mode\" },\n terminal_startup: { value: 80, description: \"Startup of the terminal (and operation)\" },\n integrity_fault_detection: { value: 90, description: \"Detection of an integrity fault\" },\n special_function_execution: { value: 100, description: \"Execution of a special function\" },\n data_export: { value: 110,description: \"Data export\" },\n offline_mode_end: { value: 120, description: \"End of offline mode\" },\n authorization_change: { value: 130, description: \"Authorization change\" },\n data_import: { value: 140, description: \"Importing data\" },\n printer_unavailable: { value: 150, description: \"Unavailable printer\" },\n accounting_entries_generation: { value: 160, description: \"Generation of accounting entries\" },\n cash_drawer_process: { value: 170, description: \"Cash drawer process\" },\n transfer_to_accounting: { value: 180, description: \"Transfer in accounting\" },\n ticket_cancellation: { value: 190, description: \"Ticket cancellation\" },\n purge: { value: 200, description: \"Purge\" },\n data_migration_from_other_software: { value: 210, description: \"Migration of data from other software\" },\n restoration: { value: 220, description: \"Restoration\" },\n backup: { value: 230, description: \"Backup\" },\n follow_up_of_recovery_interventions: { value: 240, description: \"Follow-up of the recovery interventions\" },\n software_upgrade: { value: 250, description: \"Software upgrade\" },\n software_upgrade_minor_major: { value: 255, description: \"Software upgrade minor/major\" },\n initialization_of_data: { value: 260, description: \"Initialization of data\" },\n accountant_access: { value: 290, description: \"Accountant access\" },\n void_and_delete_transaction: { value: 320, description: \"Void transaction\" },\n delete_line_item: { value: 323, description: \"Delete Line Item\" },\n line_item_discount: { value: 328, description: \"Line Item Discount\" },\n company_info_updated: { value: 410, description: \"Company Information Updated\" },\n create_return: { value: 900, description: \"Create Return\" },\n void_return: { value: 901, description: \"Void Return\" },\n delete_return: { value: 902, description: \"Delete Return\" },\n completed_return: { value: 903, description: \"Completed Return\" },\n create_payment_method: { value: 904, description: \"Create Payment Method\" },\n update_payment_method: { value: 905, description: \"Update Payment Method\" },\n delete_payment_method: { value: 906, description: \"Delete Payment Method\" },\n create_quote: { value: 910, description: \"Create Quote\" },\n void_quote: { value: 911, description: \"Void Quote\" },\n delete_quote: { value: 912, description: \"Delete Quote\" },\n convert_quote: { value: 913, description: \"Convert Quote\" },\n editors_functions: { value: 999, description: \"Editors functions\" }\n },\n\n showingOnLookbookFilterType: {\n all: { description: \"common.all\", value: '' },\n showing: { description: \"common.showing-on-lookbook\", value: 'S' },\n not_showing: { description: \"common.not-showing-on-lookbook\", value: 'NS' }\n },\n\n smartMatchedIgnoredFilterType: {\n all: { description: \"common.all\", value: '' },\n ignored: { description: \"common.ignored\", value: 'Y' },\n not_ignored: { description: \"common.not-ignored\", value: 'N' }\n },\n\n purchaseOrderTypes: {\n all: {label: 'common.all', value: ''},\n stock: {label: 'enums.purchase-order-types.stock-order', value: 'S'},\n customer: {label: 'enums.purchase-order-types.customer-order', value:'C'}\n },\n\n quoteStatuses: {\n pending: { description: 'enums.statuses.pending', value: 'P' },\n converted: { description: 'enums.statuses.converted', value: 'C' },\n voided: { description: 'enums.statuses.void', value: 'V' }\n },\n\n tipAmounts: [\n { id: 1, type: 'P', value: 10 },\n { id: 2, type: 'P', value: 15 },\n { id: 3, type: 'P', value: 20 }\n ],\n\n trxItemStatuses: {\n on_order: { description: 'enums.trx-item-statuses.on-order', icon: 'glyphicon-repeat', value: 'O' },\n awaiting_pickup: { description: 'enums.trx-item-statuses.awaiting-pickup', icon: 'glyphicon-tag', value: 'W' },\n picked_up: { description: 'enums.trx-item-statuses.picked-up', icon: 'glyphicon-ok', value: 'P' },\n in_alterations: { description: 'enums.trx-item-statuses.in-alterations', icon: 'glyphicon-scissors', value: 'A' }\n },\n\n salesReps: [\n {\n key: 'leslie',\n firstName: 'Leslie',\n lastName: 'Cimino',\n phone: '(404) 480-4387',\n email: 'leslie@bridallive.com',\n workHours: 'Mon - Fri 9am - 6pm ET',\n headShotURL: 'http://www.bridallive.com/images/aboutus/blleslie.png',\n calendlyEmbed: 'https://calendly.com/bl-leslie',\n useZendesk: true,\n territories: ['US', 'CA', 'UK', 'IE', 'AU', 'NZ', 'US_B']\n },\n {\n key: 'tim',\n firstName: 'Tim',\n lastName: 'McKee',\n phone: '(404) 671-9157',\n email: 'tim@bridallive.com',\n workHours: 'Mon - Fri 8am - 5pm ET',\n headShotURL: 'http://www.bridallive.com/images/aboutus/bltim.jpg',\n calendlyEmbed: 'https://calendly.com/tim-115',\n useZendesk: true,\n territories: ['US', 'CA', 'UK', 'IE', 'AU', 'NZ', 'US_B']\n },\n {\n key: 'ben',\n firstName: 'Ben',\n lastName: 'Brument',\n phone: '+33 648 36 74 69',\n email: 'ben@bridallive.com',\n workHours: 'Mon - Fri 900 - 1900 CET',\n headShotURL: 'http://www.bridallive.com/images/aboutus/blben.jpg',\n calendlyEmbed: '',\n useZendesk: false,\n territories: ['FR', 'BG', 'SZ', 'LX', 'SP', 'DE']\n },\n {\n key: 'alejandro',\n firstName: 'Alejandro',\n lastName: 'Ramos',\n phone: '(656) 437-8302',\n email: 'alejandro@bridallive.com',\n workHours: 'M-F 10am - 4pm MST',\n headShotURL: 'http://www.bridallive.com/images/aboutus/blalejandro.jpg',\n calendlyEmbed: '',\n useZendesk: false,\n territories: ['MX']\n },\n ],\n\n weeks: [\n { label: \"enums.client-portal.weeks.0\", value: 0, id: \"0\" },\n { label: \"enums.client-portal.weeks.1\", value: 1, id: \"1\" },\n { label: \"enums.client-portal.weeks.2\", value: 2, id: \"2\" },\n { label: \"enums.client-portal.weeks.3\", value: 3, id: \"3\" },\n { label: \"enums.client-portal.weeks.4\", value: 4, id: \"4\" },\n { label: \"enums.client-portal.weeks.5\", value: 5, id: \"5\" },\n { label: \"enums.client-portal.weeks.6\", value: 6, id: \"6\" },\n { label: \"enums.client-portal.weeks.7\", value: 7, id: \"7\" },\n { label: \"enums.client-portal.weeks.8\", value: 8, id: \"8\" },\n { label: \"enums.client-portal.weeks.9\", value: 9, id: \"9\" },\n { label: \"enums.client-portal.weeks.10\", value: 10, id: \"10\" },\n { label: \"enums.client-portal.weeks.11\", value: 11, id: \"11\" },\n { label: \"enums.client-portal.weeks.12\", value: 12, id: \"12\" }\n ],\n\n accountManagers: [\n {\n key: 'tim',\n firstName: 'Tim',\n lastName: 'McKee',\n phone: '(404) 671-9157',\n email: 'tim@bridallive.com',\n workHours: 'Mon - Fri 8am - 5pm ET',\n headShotURL: 'http://www.bridallive.com/images/aboutus/bltim.jpg',\n calendlyEmbed: 'https://calendly.com/tim-115',\n useZendesk: true\n },\n {\n key: 'devin',\n firstName: 'Devin',\n lastName: 'Holloway',\n phone: '(404) 537-3101',\n email: 'help@bridallive.com',\n workHours: 'Mon - Fri 8am - 5pm ET',\n headShotURL: 'http://www.bridallive.com/images/aboutus/bldevin.jpg',\n calendlyEmbed: 'https://calendly.com/bl-devin',\n useZendesk: true\n },\n {\n key: 'lauren',\n firstName: 'Lauren',\n lastName: 'Henton',\n phone: '(404) 573-4828',\n email: 'help@bridallive.com',\n workHours: 'Mon - Fri 8am - 5pm ET',\n headShotURL: 'http://www.bridallive.com/images/aboutus/bllauren.jpg',\n calendlyEmbed: 'https://calendly.com/bl-lauren',\n useZendesk: true\n },\n {\n key: 'lindsey',\n firstName: 'Lindsey',\n lastName: 'Phillips',\n phone: '(404) 692-5786',\n email: 'help@bridallive.com',\n workHours: 'Mon - Fri 8am - 5pm ET',\n headShotURL: 'http://www.bridallive.com/images/aboutus/bllindsey.jpg',\n calendlyEmbed: 'https://calendly.com/bl-lindsey',\n useZendesk: true\n },\n {\n key: 'aina',\n firstName: 'Aina',\n lastName: 'Kumar',\n phone: '(404) 602-0988',\n email: 'help@bridallive.com',\n workHours: 'Mon - Fri 8am - 5pm ET',\n headShotURL: 'http://www.bridallive.com/images/aboutus/blaina.jpg',\n calendlyEmbed: 'https://calendly.com/bl-aina',\n useZendesk: true\n },\n {\n key: 'ben',\n firstName: 'Ben',\n lastName: 'Brument',\n phone: '+33 648 36 74 69',\n email: 'ben@bridallive.com',\n workHours: 'Mon - Fri 900 - 1900 CET',\n headShotURL: 'http://www.bridallive.com/images/aboutus/blben.jpg',\n calendlyEmbed: '',\n useZendesk: false\n },\n {\n key: 'alejandro',\n firstName: 'Alejandro',\n lastName: 'Ramos',\n phone: '(656) 437-8302',\n email: 'alejandro@bridallive.com',\n workHours: 'M-F 10am - 4pm MST',\n headShotURL: 'http://www.bridallive.com/images/aboutus/blalejandro.jpg',\n calendlyEmbed: '',\n useZendesk: false\n },\n {\n key: 'leslie',\n firstName: 'Leslie',\n lastName: 'Cimino',\n phone: '(404) 480-4387',\n email: 'leslie@bridallive.com',\n workHours: 'Mon - Fri 9am - 6pm ET',\n headShotURL: 'http://www.bridallive.com/images/aboutus/blleslie.png',\n calendlyEmbed: 'https://calendly.com/bl-leslie',\n useZendesk: true\n },\n {\n key: 'kaylin',\n firstName: 'Kaylin',\n lastName: 'Symons',\n phone: '(404) 573-4828',\n email: 'help@bridallive.com',\n workHours: 'Mon - Fri 8am - 5pm ET',\n headShotURL: 'http://www.bridallive.com/images/aboutus/blkaylin.jpg',\n calendlyEmbed: 'https://calendly.com/bl-kaylin',\n useZendesk: true\n },\n {\n key: 'paige',\n firstName: 'Paige',\n lastName: 'West',\n phone: '(404) 796-7501',\n email: 'help@bridallive.com',\n workHours: 'Mon - Fri 8am - 5pm ET',\n headShotURL: 'http://www.bridallive.com/images/aboutus/blpaige.jpg',\n calendlyEmbed: 'https://calendly.com/bl-paige',\n useZendesk: true\n },\n {\n key: 'kandace',\n firstName: 'Kandace',\n lastName: 'Wade',\n phone: '(404) 305-3858',\n email: 'help@bridallive.com',\n workHours: 'Mon - Fri 9am - 6pm ET',\n headShotURL: 'http://www.bridallive.com/images/aboutus/blkandace.jpg',\n calendlyEmbed: 'https://calendly.com/bl-kandace',\n useZendesk: true\n },\n {\n key: 'maxine',\n firstName: 'Maxine',\n lastName: 'Sogueco',\n phone: '(404) 305-3858',\n email: 'help@bridallive.com',\n workHours: 'Mon - Fri 8am - 5pm ET',\n headShotURL: 'http://www.bridallive.com/images/aboutus/blmaxine.jpg',\n calendlyEmbed: 'https://calendly.com/bl-maxine',\n useZendesk: true\n }\n ]\n\n });\n});\n\n","define('modules/resources/company-setting',[\n 'angular',\n './backend-resource',\n '../security/security-service'\n], function (angular) {\n 'use strict';\n\n return angular.module('bl.resources.company-setting', ['bl.resources.backend-resource', 'bl.security.service'])\n .factory('CompanySetting', function (backendResource, $http, security) {\n\n var resource = backendResource('companySettings');\n\n /**\n *\n * @param type\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.readyByType = function (type, successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/readByType/' + type, null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n *\n * @param type\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.readyByTypeArray = function (type, successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/readByType/' + type, null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getContactSettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getContactSettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getApptAndTaskSettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getApptAndTaskSettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getPOSSettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getPOSSettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getQuoteSettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getQuoteSettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getCustomSalesAgreements = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getCustomSalesAgreements', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getCustomTerminalContracts = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getCustomTerminalContracts', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getCustomPaymentPlanContracts = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getCustomPaymentPlanContracts', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getCustomPaymentPlanAgreements = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getCustomPaymentPlanAgreements', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getQuoteCustomAgreements = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getQuoteCustomAgreements', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getQuoteTerminalContracts = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getQuoteTerminalContracts', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getCommissionSettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getCommissionSettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getCompanySettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getCompanySettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getAccessibilitySettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getAccessibilitySettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getInventorySettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getInventorySettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n *\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getPurchasingSettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getPurchasingSettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.getQuickBooksSettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getQuickBooksSettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.getMarketplaceSettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getMarketplaceSettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.getClientPortalSettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getClientPortalSettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.getBasicClientPortalSettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getBasicClientPortalSettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.getPromRegistrySettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getPromRegistrySettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.getCustomEmailSettings = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getCustomEmailSettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.getPaymentPlanSettings = function(successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getPaymentPlanSettings', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n * @param modelsToUpdate\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.batchUpdate = function (modelsToUpdate, successcb, errorcb) {\n var httpPromise = $http.put(resource.url + '/batchUpdate', modelsToUpdate);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n * @param modelsToUpdate\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.batchUpdateToArray = function (modelsToUpdate, successcb, errorcb) {\n var httpPromise = $http.put(resource.url + '/batchUpdate', modelsToUpdate);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n /**\n * @param modelsToUpdate\n * @param type\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.batchUpdateValidate = function (modelsToUpdate, type, successcb, errorcb) {\n var httpPromise = $http.put(resource.url + '/batchUpdateValidate/' + type, modelsToUpdate);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.uploadLogo = function (formData, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/logo', formData, {\n transformRequest: angular.identity,\n headers: { 'Content-Type': undefined }\n });\n\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n \n resource.deleteLogo = function (successcb, errorcb) {\n var httpPromise = $http.delete(resource.url + '/logo', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.getLogoUrl = function (retailerId) {\n return resource.url + '/' + (retailerId || security.readCookie().retailerId) + '/logo';\n };\n\n resource.uploadPortalLogo = function (formData, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/portalLogo', formData, {\n transformRequest: angular.identity,\n headers: { 'Content-Type': undefined }\n });\n\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.deletePortalLogo = function (successcb, errorcb) {\n var httpPromise = $http.delete(resource.url + '/portalLogo', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.getPortalLogoUrl = function (retailerId) {\n return resource.url + '/' + (retailerId || security.readCookie().retailerId) + '/portalLogo';\n };\n\n resource.isSpecialEventsEnabled = function(successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/isSpecialEventsEnabled', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.AC_PRINT_PREF_CONTACT_NOTES = \"AC_PP_CN\";\n resource.AC_PRINT_PREF_APPOINTMENT_NOTES = \"AC_PP_AN\";\n resource.AC_BOOK_OUTSIDE_SCHEDULE = \"AC_BOOK_OUTSIDE_SCHED\";\n resource.AC_CALENDAR_URL = \"AC_CALENDAR_URL\";\n resource.CC_PRINT_PREF_CONTACT_NOTES = \"CC_PP_CN\";\n resource.CC_DEFAULT_CONTACT_STATE = \"CC_DEFAULT_CONTACT_STATE\";\n resource.CC_HIDE_PROFILE_PICTURE = \"CC_HIDE_PROFILE_PICTURE\";\n resource.CC_DEFAULT_MEASUREMENT_NOTES = \"CC_DEFAULT_MEASUREMENT_NOTES\";\n resource.CC_PRINT_ORIG_PRICE = \"CC_PRINT_ORIG_PRICE\";\n resource.CC_PRINT_LINEITEM_NOTE = \"CC_PRINT_LINEITEM_NOTE\";\n resource.CC_PRINT_DELIVERY_DATE = \"CC_PRINT_DELIVERY_DATE\";\n resource.CC_PRINT_VENDOR = \"CC_PRINT_VENDOR\";\n resource.CC_SHOW_BUDGET_FIELD_REGARDLESS_EVENT_TYPE = \"CC_SHOW_BUDGET_FIELD_REGARDLESS_EVENT_TYPE\";\n resource.CC_USE_ASSOCIATE_FIRST_NAME_ON_PRINTED_DOCS = \"CC_USE_ASSOCIATE_FIRST_NAME_ON_PRINTED_DOCS\";\n resource.CC_DEFAULT_PRINT_FORMAT_TYPE = \"CC_DEFAULT_PRINT_FORMAT_TYPE\";\n resource.POS_SALE_TC_SHOW_TYPE = \"POS_SALE_TC_SHOW\";\n resource.POS_SALE_TC_TYPE = \"POS_SALE_TC\";\n resource.POS_SALES_ORDER_TC_SHOW_TYPE = \"POS_SALES_ORDER_TC_SHOW\";\n resource.POS_SALES_ORDER_TC_TYPE = \"POS_SALES_ORDER_TC\";\n resource.POS_RETURN_TC_SHOW_TYPE = \"POS_RETURN_TC_SHOW\";\n resource.POS_RETURN_TC_TYPE = \"POS_RETURN_TC\";\n resource.POS_LAYAWAY_TC_TYPE = \"POS_LAYAWAY_TC\";\n resource.POS_ALT_PRINT_TYPE = \"POS_ALT_PRINT\";\n resource.POS_PRINT_LOGO = \"POS_PRINT_LOGO\";\n resource.POS_PRINT_LINEITEM_NOTE = \"POS_PRINT_LINEITEM_NOTE\";\n resource.POS_PRINT_VENDOR = \"POS_PRINT_VENDOR\";\n resource.POS_PRINT_MEASUREMENTS = \"POS_PRINT_MEASUREMENTS\";\n resource.POS_DEFAULT_DEPOSIT_PERCENTAGE = \"POS_DEFAULT_DEPOSIT_PERCENTAGE\";\n resource.POS_PRINT_PRICE = \"POS_PRINT_PRICE\";\n resource.POS_PRINT_DELIVERY_DATE = \"POS_PRINT_DELIVERY_DATE\";\n resource.POS_XWEB_ID = \"POS_XWEB_ID\";\n resource.POS_XWEB_TERMINAL_ID = \"POS_XWEB_TERMINAL_ID\";\n resource.POS_XWEB_AUTH_KEY = \"POS_XWEB_AUTH_KEY\";\n resource.POS_XWEB_EMV_ID = \"POS_XWEB_EMV_ID\";\n resource.POS_XWEB_EMV_TERMINAL_ID = \"POS_XWEB_EMV_TERMINAL_ID\";\n resource.POS_XWEB_EMV_AUTH_KEY = \"POS_XWEB_EMV_AUTH_KEY\";\n resource.POS_CIP_API_KEY = \"POS_CIP_API_KEY\";\n resource.POS_CIP_MERCHANT_NAME = \"POS_CIP_MERCHANT_NAME\";\n resource.POS_CIP_URL = \"POS_CIP_URL\";\n resource.POS_CIP_LOCATION_ID = \"POS_CIP_LOCATION_ID\";\n resource.POS_CIP_CONTROLLER_NAME = \"POS_CIP_CONTROLLER_NAME\";\n resource.POS_STRIPE_API_KEY = \"POS_STRIPE_API_KEY\";\n resource.POS_STRIPE_PUB_API_KEY = \"POS_STRIPE_PUB_API_KEY\";\n resource.POS_APPLY_SALES_TAX_TO_SHIPPING = \"POS_APPLY_TAX_TO_SHIPPING\";\n resource.POS_MANUAL_TAX_CALC = \"POS_MANUAL_TAX_CALC\";\n resource.POS_TRX_DISCOUNT = \"POS_TRX_DISCOUNT\";\n resource.POS_USER_ASSIGNED_TRANSACTION = \"POS_USER_ASSIGNED_TRANSACTION\";\n resource.POS_ASSOCIATE_ASSIGNED_TO_PAYMENT = \"POS_ASSOCIATE_ASSIGNED_TO_PAYMENT\";\n resource.POS_COLOR_SIZE_VALID = \"POS_COLOR_SIZE_VALID\";\n resource.POS_COLOR_SIZE_REQUIRED = \"POS_COLOR_SIZE_REQUIRED\";\n resource.POS_COLOR_SIZE_BLANK = \"POS_COLOR_SIZE_BLANK\";\n resource.POS_COLOR_SIZE_BLANK_ON_WR = \"POS_COLOR_SIZE_BLANK_ON_WR\";\n resource.POS_COLOR_SIZE_BLANK_ON_FAVORITES = \"POS_COLOR_SIZE_BLANK_ON_FAVORITES\";\n resource.POS_COPY_LINE_ITEM_NOTES_DEFAULT = \"POS_COPY_LINE_ITEM_NOTES_DEFAULT\";\n resource.POS_UNISSUED_SOS_NON_INV = \"POS_UNISSUED_SOS_NON_INV\";\n resource.POS_UNISSUED_SOS_RENTAL = \"POS_UNISSUED_SOS_RENTAL\";\n resource.POS_UNISSUED_SOS_WED_PARTIES = \"POS_UNISSUED_SOS_WED_PARTIES\";\n resource.POS_CUSTOM_SALES_AGREEMENT = \"POS_CUSTOM_SALES_AGREEMENT\";\n resource.POS_USE_ASSOCIATE_FIRST_NAME_ON_PRINTED_DOCS = \"POS_USE_ASSOCIATE_FIRST_NAME_ON_PRINTED_DOCS\";\n resource.POS_PRINT_UPCOMING_APPOINTMENTS = \"POS_PRINT_UPCOMING_APPOINTMENTS\";\n resource.POS_FULLSTEAM_MERCHANT_API_KEY = \"POS_FULLSTEAM_MERCHANT_API_KEY\";\n resource.POS_FULLSTEAM_ALLOW_CUSTOMER_LEAVE_TIP = \"POS_FULLSTEAM_ALLOW_CUSTOMER_LEAVE_TIP\";\n resource.POS_FULLSTEAM_TIP_SELECTION_TYPE = \"POS_FULLSTEAM_TIP_SELECTION_TYPE\";\n resource.POS_FULLSTEAM_TIP_OTHER_OPTIONS = \"POS_FULLSTEAM_TIP_OTHER_OPTIONS\";\n resource.POS_FULLSTEAM_TIP_SELECTION_1 = \"POS_FULLSTEAM_TIP_SELECTION_1\";\n resource.POS_FULLSTEAM_TIP_SELECTION_2 = \"POS_FULLSTEAM_TIP_SELECTION_2\";\n resource.POS_FULLSTEAM_TIP_SELECTION_3 = \"POS_FULLSTEAM_TIP_SELECTION_3\";\n resource.POS_FULLSTEAM_TIP_SELECTION_4 = \"POS_FULLSTEAM_TIP_SELECTION_4\";\n resource.POS_FULLSTEAM_URL = \"POS_FULLSTEAM_URL\";\n resource.POS_FULLSTEAM_ENABLE_TIP_FEATURE = \"POS_FULLSTEAM_ENABLE_TIP_FEATURE\";\n resource.POS_CUSTOM_TERMINAL_CONTRACTS = \"POS_CUSTOM_TERMINAL_CONTRACTS\";\n resource.POS_FULLSTEAM_INCLUDE_LINE_ITEMS_WITH_CONTRACT = \"POS_FULLSTEAM_INCLUDE_LINE_ITEMS_WITH_CONTRACT\";\n resource.POS_FULLSTEAM_REQUIRE_BILLING_ADDRESS = \"POS_FULLSTEAM_REQUIRE_BILLING_ADDRESS\";\n resource.POS_FULLSTEAM_BL_PAY_RECAPTCHA_SETTINGS_ENABLED = \"POS_FULLSTEAM_BL_PAY_RECAPTCHA_SETTINGS_ENABLED\";\n resource.POS_FULLSTEAM_BL_PAY_RECAPTCHA_SITE_KEY = \"POS_FULLSTEAM_BL_PAY_RECAPTCHA_SITE_KEY\";\n resource.POS_FULLSTEAM_BL_PAY_RECAPTCHA_SECRET_KEY = \"POS_FULLSTEAM_BL_PAY_RECAPTCHA_SECRET_KEY\";\n resource.POS_FULLSTEAM_BL_PAY_ORIGINS = \"POS_FULLSTEAM_BL_PAY_ORIGINS\";\n resource.POS_FULLSTEAM_ENABLE_PLAT_FORM_FEE = \"POS_FULLSTEAM_ENABLE_PLAT_FORM_FEE\";\n resource.POS_FULLSTEAM_PLAT_FORM_FEE_PERCENTAGE = \"POS_FULLSTEAM_PLAT_FORM_FEE_PERCENTAGE\";\n resource.POS_PP_NUMBER_OF_RETRIES = \"POS_PP_NUMBER_OF_RETRIES\";\n resource.POS_PP_SUCCESS_EMAIL_TEMPLATE = \"POS_PP_SUCCESS_EMAIL_TEMPLATE\";\n resource.POS_PP_SUCCESS_SMS_TEMPLATE = \"POS_PP_SUCCESS_SMS_TEMPLATE\";\n resource.POS_PP_ERROR_EMAIL_TEMPLATE = \"POS_PP_ERROR_EMAIL_TEMPLATE\";\n resource.POS_PP_ERROR_SMS_TEMPLATE = \"POS_PP_ERROR_SMS_TEMPLATE\";\n resource.POS_PP_REMINDER_EMAIL_TEMPLATE = \"POS_PP_REMINDER_EMAIL_TEMPLATE\";\n resource.POS_PP_REMINDER_SMS_TEMPLATE = \"POS_PP_REMINDER_SMS_TEMPLATE\";\n resource.POS_PP_DAYS_BEFORE_REMINDER = \"POS_PP_DAYS_BEFORE_REMINDER\";\n resource.POS_PP_REQUIRE_SIG = \"POS_PP_REQUIRE_SIG\";\n resource.POS_CUSTOM_PAYMENT_PLAN_CONTRACTS = \"POS_CUSTOM_PAYMENT_PLAN_CONTRACTS\";\n resource.POS_CUSTOM_PAYMENT_PLAN_AGREEMENT = \"POS_CUSTOM_PAYMENT_PLAN_AGREEMENT\";\n resource.POS_ENABLED_ZERO_DUE_DATE = \"POS_ENABLED_ZERO_DUE_DATE\";\n resource.POS_SHOW_SUBITEMS = \"POS_SHOW_SUBITEMS\";\n resource.POS_SHOW_ITEM_ADD_ON_NOTES = \"POS_SHOW_ITEM_ADD_ON_NOTES\";\n\n resource.POS_PAYMENT_RECEIPT_SHOW_ORIGINAL_PRICE = \"POS_PAYMENT_RECEIPT_SHOW_ORIGINAL_PRICE\";\n resource.POS_PAYMENT_RECEIPT_SHOW_DISCOUNT = \"POS_PAYMENT_RECEIPT_SHOW_DISCOUNT\";\n resource.POS_PAYMENT_RECEIPT_CUSTOM_TEXT = \"POS_PAYMENT_RECEIPT_CUSTOM_TEXT\";\n\n resource.QUOTE_CUSTOM_AGREEMENT = \"QUOTE_CUSTOM_AGREEMENT\";\n resource.QUOTE_CUSTOM_TERMINAL_CONTRACTS = \"QUOTE_CUSTOM_TERMINAL_CONTRACTS\";\n\n resource.QUOTE_ALT_PRINT = \"QUOTE_ALT_PRINT\";\n resource.QUOTE_PRINT_PRICE = \"QUOTE_PRINT_PRICE\";\n resource.QUOTE_PRINT_LINEITEM_NOTE = \"QUOTE_PRINT_LINEITEM_NOTE\";\n resource.QUOTE_PRINT_DELIVERY_DATE = \"QUOTE_PRINT_DELIVERY_DATE\";\n resource.QUOTE_PRINT_MEASUREMENTS = \"QUOTE_PRINT_MEASUREMENTS\";\n resource.QUOTE_COLOR_SIZE_REQUIRED = \"QUOTE_COLOR_SIZE_REQUIRED\";\n resource.QUOTE_COLOR_SIZE_BLANK = \"QUOTE_COLOR_SIZE_BLANK\";\n resource.QUOTE_PRINT_VENDOR = \"QUOTE_PRINT_VENDOR\";\n resource.QUOTE_USE_ASSOCIATE_FIRST_NAME_ON_PRINTED_DOCS = \"QUOTE_USE_ASSOCIATE_FIRST_NAME_ON_PRINTED_DOCS\";\n resource.QUOTE_PRINT_UPCOMING_APPOINTMENTS = \"QUOTE_PRINT_UPCOMING_APPOINTMENTS\";\n resource.QUOTE_SHOW_SUBITEMS = \"QUOTE_SHOW_SUBITEMS\";\n resource.QUOTE_SHOW_ITEM_ADD_ON_NOTES = \"QUOTE_SHOW_ITEM_ADD_ON_NOTES\";\n resource.QUOTE_DEFAULT_AGREEMENT = \"QUOTE_DEFAULT_AGREEMENT\";\n\n resource.USE_DIG_SIGN = \"USE_DIG_SIGN\";\n resource.PMT_METHOD_REQ_SIGN = \"PMT_METHOD_REQ_SIGN\";\n resource.SALES_AGREEMENT_REQ = \"SALES_AGREEMENT_REQ\";\n\n resource.AC_APPT_COLOR_ASSOCIATION = \"AC_APPT_COLOR_ASSOCIATION\";\n resource.AC_APPT_COMPLETION_OPTIONS = \"AC_APPT_COMPLETION_OPTIONS\";\n resource.AC_TASK_COMPLETION_OPTIONS = \"AC_TASK_COMPLETION_OPTIONS\";\n resource.AC_DEFAULT_APPT_ASSOCIATE = \"AC_DEFAULT_APPT_ASSOCIATE\";\n resource.AC_SHOW_ONLY_AVAILABLE_EMPLOYEES = \"AC_SHOW_ONLY_AVAILABLE_EMPLOYEES\";\n resource.AC_HIDE_UNASSIGNED_FITTING_ROOM = \"AC_HIDE_UNASSIGNED_FITTING_ROOM\";\n resource.AC_SORT_SEQUENCE_FITTING_ROOM = \"AC_SORT_SEQUENCE_FITTING_ROOM\";\n resource.AC_USE_SPECIAL_EVENTS_SCHEDULER = \"AC_USE_SPECIAL_EVENTS_SCHEDULER\";\n\n resource.AC_WAIT_LIST_ENABLE_WL = \"AC_WAIT_LIST_ENABLE_WL\";\n resource.AC_WAIT_LIST_BTN_SHOWN_TYPE = \"AC_WAIT_LIST_BTN_SHOWN_TYPE\";\n resource.AC_WAIT_LIST_MAX_TIME_SLOTS = \"AC_WAIT_LIST_MAX_TIME_SLOTS\";\n resource.AC_WAIT_LIST_MAX_WL_ENTRY_LEADS = \"AC_WAIT_LIST_MAX_WL_ENTRY_LEADS\";\n resource.AC_WAIT_LIST_CONFIRM_EMAIL_TEMPLATE = \"AC_WAIT_LIST_CONFIRM_EMAIL_TEMPLATE\";\n resource.AC_WAIT_LIST_CONFIRM_SMS_TEMPLATE = \"AC_WAIT_LIST_CONFIRM_SMS_TEMPLATE\";\n resource.AC_WAIT_LIST_CONFIRMATION = \"AC_WAIT_LIST_CONFIRMATION\";\n resource.AC_HIDE_UNASSIGNED_FITTING_ROOM = \"AC_HIDE_UNASSIGNED_FITTING_ROOM\";\n\n resource.PO_CUSTOM_TEXT = \"PO_CUSTOM_TEXT\";\n resource.PICK_UP_SLIP_TEXT = \"PICK_UP_SLIP_TEXT\";\n resource.PICK_UP_SLIP_LINE_ITEM_NOTES = \"PICK_UP_SLIP_LINE_ITEM_NOTES\";\n resource.PICK_UP_SLIP_VENDOR_DISPLAY = \"PICK_UP_SLIP_VENDOR_DISPLAY\";\n resource.PICK_UP_SLIP_SHOW_ITEM_NUMBER = \"PICK_UP_SLIP_SHOW_ITEM_NUMBER\";\n resource.PICK_UP_SLIP_HIDE_SIG_AND_DATE = \"PICK_UP_SLIP_HIDE_SIG_AND_DATE\";\n resource.PO_PRINT_ITEM_NUMBER = \"PO_PRINT_ITEM_NUMBER\";\n resource.PO_PRINT_CONTACT_NAME = \"PO_PRINT_CONTACT_NAME\";\n resource.PO_DEFAULT_EST_ARRIVAL_DATE_WEEK_PADDING = \"PO_DEFAULT_EST_ARRIVAL_DATE_WEEK_PADDING\";\n resource.PO_PROMPT_EST_ARRIVAL_DATE_WHEN_SHIP_DATE_CHANGES = \"PO_PROMPT_EST_ARRIVAL_DATE_WHEN_SHIP_DATE_CHANGES\";\n resource.PO_PROMPT_TO_COMPLETE_RV_BEFORE_LEAVING = \"PO_PROMPT_TO_COMPLETE_RV_BEFORE_LEAVING\";\n resource.PO_PENDING_PO_PAST_SHIPPING_WINDOW = \"PO_PENDING_PO_PAST_SHIPPING_WINDOW\";\n resource.PO_PRINT_ITEM_ADD_ONS = \"PO_PRINT_ITEM_ADD_ONS\";\n resource.PO_PRINT_ITEM_ADD_ON_NOTES = \"PO_PRINT_ITEM_ADD_ON_NOTES\";\n resource.PO_SEND_PO_WEB_HOOKS = \"PO_SEND_PO_WEB_HOOKS\";\n resource.RV_SEND_RV_WEB_HOOKS = \"RV_SEND_RV_WEB_HOOKS\";\n\n resource.INVTRY_ENABLE_ITEM_WILDCARD = \"INVTRY_ENABLE_WILDCARD\";\n resource.INVTRY_ENABLE_VENDOR_ITEM_WILDCARD = \"INVTRY_ENABLE_VENDOR_ITEM_WILDCARD\";\n resource.INVTRY_PRINT_BARCODE = \"INVTRY_PRINT_BARCODE\";\n resource.INVTRY_PRINT_PRICES = \"INVTRY_PRINT_PRICES\";\n resource.INVTRY_HIDE_SALE_PRICE = \"INVTRY_HIDE_SALE_PRICE\";\n resource.INVTRY_PRINT_AVAILABLE_COLORS = \"INVTRY_PRINT_AVAILABLE_COLORS\";\n resource.INVTRY_PRINT_AVAILABLE_SIZES = \"INVTRY_PRINT_AVAILABLE_SIZES\";\n resource.INVTRY_PRINT_ACCENT_COLOR = \"INVTRY_PRINT_ACCENT_COLOR\";\n resource.INVTRY_REMOVE_COMMAS = \"INVTRY_REMOVE_COMMAS\";\n resource.INVTRY_REMOVE_CENT = \"INVTRY_REMOVE_CENT\";\n resource.INVTRY_VAT_PERCENT = \"POS_VAT_PERCENT\"; //moved from POS to Inventory, but kept the same key\n resource.PROM_REGISTRATION_TYPE = \"PROM_REGISTRATION_TYPE\";\n resource.INVTRY_ENABLE_PRIVATE_LABEL_GENERATION = \"INVTRY_ENABLE_PRIVATE_LABEL_GENERATION\";\n resource.INVTRY_PRIVATE_LABELING_ALGORITHM = \"INVTRY_PRIVATE_LABELING_ALGORITHM\";\n resource.INVTRY_REPLACE_VENDOR_CODE_W_COLOR = \"INVTRY_REPLACE_VENDOR_CODE_W_COLOR\";\n resource.INVTRY_DEFAULT_SORT_FIELD = \"INVTRY_DEFAULT_SORT_FIELD\";\n resource.INVTRY_DEFAULT_SORT_DIRECTION = \"INVTRY_DEFAULT_SORT_DIRECTION\";\n resource.PROM_REGISTRATION_ADVANCED_ITEM_SEARCH = \"PROM_REGISTRATION_ADVANCED_ITEM_SEARCH\";\n\n resource.QB_START_DATE = \"QB_START_DATE\";\n resource.QB_END_DATE = \"QB_END_DATE\";\n resource.QB_EXPORT_TYPE = \"QB_EXPORT_TYPE\";\n resource.QB_EXPORT_RVS = \"QB_EXPORT_RVS\";\n resource.QB_EXPORT_SALES = \"QB_EXPORT_SALES\";\n resource.QB_EXPORT_COGS = \"QB_EXPORT_COGS\";\n resource.QB_EXPORT_CLASS = \"QB_EXPORT_CLASS\";\n resource.QB_EXPORT_UNDEPOSITED_FUNDS = \"QB_EXPORT_UNDEPOSITED_FUNDS\";\n resource.QB_MODE = \"QB_MODE\";\n resource.QB_EXPORT_JE_BREAKDOWN = \"QB_EXPORT_JE_BREAKDOWN\";\n\n resource.COMM_PAID_WHEN = \"COMM_PAID_WHEN\";\n resource.COMM_BASED_ON = \"COMM_BASED_ON\";\n resource.COMM_LEVELS = \"COMM_LEVELS\";\n resource.COMM_STATUS = \"COMM_STATUS\";\n resource.SPH_DEFAULT = \"SPH_DEFAULT\";\n\n resource.MKT_CAT_BRIDAL_GOWNS = \"MKT_CAT_BRIDAL_GOWNS\";\n resource.MKT_CAT_BRIDESMAID_DRESSES = \"MKT_CAT_BRIDESMAID_DRESSES\";\n resource.MKT_CAT_ACCESSORIES = \"MKT_CAT_ACCESSORIES\";\n resource.MKT_CAT_FORMALS = \"MKT_CAT_FORMALS\";\n resource.MKT_CAT_PROM_DRESSES = \"MKT_CAT_PROM_DRESSES\";\n resource.MKT_CAT_FLOWER_GIRL_DRESSES = \"MKT_CAT_FLOWER_GIRL_DRESSES\";\n resource.MKT_CAT_MOTHERS = \"MKT_CAT_MOTHERS\";\n resource.MKT_CAT_HEADPIECES = \"MKT_CAT_HEADPIECES\";\n resource.MKT_CAT_VEILS = \"MKT_CAT_VEILS\";\n resource.MKT_CAT_JEWELRY = \"MKT_CAT_JEWELRY\";\n resource.MKT_CAT_LINGERIE = \"MKT_CAT_LINGERIE\";\n resource.MKT_CAT_SHOES = \"MKT_CAT_SHOES\";\n resource.MKT_CAT_MENS_WEAR=\"MKT_CAT_MENS_WEAR\";\n resource.MKT_ENABLE_SMART_MATCH = \"MKT_ENABLE_SMART_MATCH\";\n\n resource.CS_ASSOCIATE_SALE_GOALS_REPORT_TYPE = \"CS_ASSOCIATE_SALE_GOALS_REPORT_TYPE\";\n resource.CS_AUTO_LOGOUT_TIME = \"CS_AUTO_LOGOUT_TIME\";\n resource.CS_END_OF_DAY = \"CS_END_OF_DAY\";\n resource.CS_END_OF_DAY_APPOINTMENTS = \"CS_END_OF_DAY_APPOINTMENTS\";\n resource.CS_END_OF_DAY_TASKS = \"CS_END_OF_DAY_TASKS\";\n resource.CS_END_OF_DAY_REGISTER = \"CS_END_OF_DAY_REGISTER\";\n resource.CS_END_OF_DAY_REPORTS = \"CS_END_OF_DAY_REPORTS\";\n resource.CS_END_OF_DAY_TIME_PUNCHES = \"CS_END_OF_DAY_TIME_PUNCHES\";\n resource.CS_END_OF_DAY_PAYMENT_PLANS = \"CS_END_OF_DAY_PAYMENT_PLANS\";\n\n resource.CP_FEATURE_PIN_ENABLED = \"CP_FEATURE_PIN_ENABLED\";\n resource.CP_FEATURE_PAYMENTS = \"CP_FEATURE_PAYMENTS\";\n resource.CP_FEATURE_EVENT_MANAGEMENT = \"CP_FEATURE_EVENT_MANAGEMENT\";\n resource.CP_FEATURE_LOOKBOOK = \"CP_FEATURE_LOOKBOOK\";\n resource.CP_FEATURE_DIGITAL_SIGNATURES = \"CP_FEATURE_DIGITAL_SIGNATURES\";\n resource.CP_FEATURE_MEASUREMENTS = \"CP_FEATURE_MEASUREMENTS\";\n resource.CP_FEATURE_APPOINTMENTS = \"CP_FEATURE_APPOINTMENTS\";\n resource.CP_FEATURE_ORDERS = \"CP_FEATURE_ORDERS\";\n resource.CP_FEATURE_BILLING = \"CP_FEATURE_BILLING\";\n\n resource.CP_LOOK_COLOR_THEME = \"CP_LOOK_COLOR_THEME\";\n resource.CP_LOOK_HEADER_FOOTER_BG_COLOR = \"CP_LOOK_HEADER_FOOTER_BG_COLOR\";\n resource.CP_LOOK_HEADER_FOOTER_TEXT_COLOR = \"CP_LOOK_HEADER_FOOTER_TEXT_COLOR\";\n resource.CP_LOOK_PRIMARY_BTN_BG_COLOR = \"CP_LOOK_PRIMARY_BTN_BG_COLOR\";\n resource.CP_LOOK_PRIMARY_BTN_TEXT_COLOR = \"CP_LOOK_PRIMARY_BTN_TEXT_COLOR\";\n resource.CP_LOOK_FONT_PACKAGE = \"CP_LOOK_FONT_PACKAGE\";\n resource.CP_LOOK_GREETING_FORMAT = \"CP_LOOK_GREETING_FORMAT\";\n resource.CP_LOOK_GREETING_SUB_TEXT = \"CP_LOOK_GREETING_SUB_TEXT\";\n resource.CP_LOOK_HERO_IMAGE = \"CP_LOOK_HERO_IMAGE\";\n resource.CP_LOOK_HERO_IMAGE_TYPE = \"CP_LOOK_HERO_IMAGE_TYPE\";\n resource.CP_LOOK_PORTAL_LOGO_URL = \"CP_LOOK_PORTAL_LOGO_URL\";\n resource.CP_LOOK_GREETING_TEXT_COLOR = \"CP_LOOK_GREETING_TEXT_COLOR\";\n\n resource.CP_ADV_GENERAL_HIDE_BREADCRUMB = \"CP_ADV_GENERAL_HIDE_BREADCRUMB\";\n resource.CP_ADV_DASHBOARD_HIDE_TIMELINE = \"CP_ADV_DASHBOARD_HIDE_TIMELINE\";\n resource.CP_ADV_LOOKBOOK_HIDE_ITEM_NAME = \"CP_ADV_LOOKBOOK_HIDE_ITEM_NAME\";\n resource.CP_ADV_LOOKBOOK_HIDE_VENDOR_NAME = \"CP_ADV_LOOKBOOK_HIDE_VENDOR_NAME\";\n resource.CP_ADV_LOOKBOOK_PRICE_DISPLAY = \"CP_ADV_LOOKBOOK_PRICE_DISPLAY\";\n resource.CP_ADV_LOOKBOOK_DISPLAY_SIZES = \"CP_ADV_LOOKBOOK_DISPLAY_SIZES\";\n resource.CP_ADV_LOOKBOOK_DISPLAY_COLORS = \"CP_ADV_LOOKBOOK_DISPLAY_COLORS\";\n resource.CP_ADV_LOOKBOOK_HIDE_DESIGNER_FILTER = \"CP_ADV_LOOKBOOK_HIDE_DESIGNER_FILTER\";\n resource.CP_ADV_LOOKBOOK_HIDE_CATEGORY_FILTER = \"CP_ADV_LOOKBOOK_HIDE_CATEGORY_FILTER\";\n resource.CP_ADV_LOOKBOOK_HIDE_PRICE_FILTER = \"CP_ADV_LOOKBOOK_HIDE_PRICE_FILTER\";\n resource.CP_ADV_LOOKBOOK_HIDE_SILHOUETTE_FILTER = \"CP_ADV_LOOKBOOK_HIDE_SILHOUETTE_FILTER\";\n resource.CP_ADV_LOOKBOOK_HIDE_NOTES = \"CP_ADV_LOOKBOOK_HIDE_NOTES\";\n resource.CP_ADV_LOOKBOOK_HIDE_IN_STOCK_LABEL = \"CP_ADV_LOOKBOOK_HIDE_IN_STOCK_LABEL\";\n resource.CP_ADV_LOOKBOOK_DISPLAY_ANY_PRICE_FILTER = \"CP_ADV_LOOKBOOK_DISPLAY_ANY_PRICE_FILTER\";\n resource.CP_ADV_LOOKBOOK_PRICE_FILTER_TYPE = \"CP_ADV_LOOKBOOK_PRICE_FILTER_TYPE\";\n resource.CP_ADV_ORDERS_HIDE_PAYMENT_BUTTON = \"CP_ADV_ORDERS_HIDE_PAYMENT_BUTTON\";\n resource.CP_ADV_ORDERS_HIDE_PRODUCT_IMAGE = \"CP_ADV_ORDERS_HIDE_PRODUCT_IMAGE\";\n resource.CP_ADV_ORDERS_SHOW_ORDER_LVL_DISCOUNT = \"CP_ADV_ORDERS_SHOW_ORDER_LVL_DISCOUNT\";\n resource.CP_ADV_ORDERS_HIDE_ORDER_NOTES = \"CP_ADV_ORDERS_HIDE_ORDER_NOTES\";\n resource.CP_ADV_MEASUREMENTS_HIDE_GUIDE = \"CP_ADV_MEASUREMENTS_HIDE_GUIDE\";\n resource.CP_ADV_MEASUREMENTS_AGREEMENT = \"CP_ADV_MEASUREMENTS_AGREEMENT\";\n resource.CP_ADV_MEASUREMENTS_HELP_TEXT = \"CP_ADV_MEASUREMENTS_HELP_TEXT\";\n resource.CP_ADV_SHOW_GENDER_NEUTRAL_MEASUREMENTS_GUIDE = \"CP_ADV_SHOW_GENDER_NEUTRAL_MEASUREMENTS_GUIDE\";\n resource.CP_ADV_DASHBOARD_HIDE_HERO_IMAGE_AND_GREETING = \"CP_ADV_DASHBOARD_HIDE_HERO_IMAGE_AND_GREETING\";\n resource.CP_ADV_EM_HIDE_MEMBERS_PROGRESS_FROM_OTHER_MEMBERS = \"CP_ADV_EM_HIDE_MEMBERS_PROGRESS_FROM_OTHER_MEMBERS\";\n resource.CP_ADV_EM_EVENT_TYPES_TO_DISPLAY = \"CP_ADV_EM_EVENT_TYPES_TO_DISPLAY\";\n resource.CP_ADV_EM_EVENT_TYPE_BTN_1 = \"CP_ADV_EM_EVENT_TYPE_BTN_1\";\n resource.CP_ADV_EM_EVENT_TYPE_BTN_2 = \"CP_ADV_EM_EVENT_TYPE_BTN_2\";\n resource.CP_ADV_EM_DONT_REQUIRE_EMAIL_ON_ADD_MEMBER_SECTION = \"CP_ADV_EM_DONT_REQUIRE_EMAIL_ON_ADD_MEMBER_SECTION\";\n resource.CP_ADV_EM_ROLE_TYPES_TO_DISPLAY = \"CP_ADV_EM_ROLE_TYPES_TO_DISPLAY\";\n resource.CP_ADV_LOOKBOOK_HELP_TEXT = \"CP_ADV_LOOKBOOK_HELP_TEXT\";\n resource.CP_ADV_HIDE_LOOKBOOK_WHEN_PURCHASE_HISTORY = \"CP_ADV_HIDE_LOOKBOOK_WHEN_PURCHASE_HISTORY\";\n resource.CP_ADV_LOOKBOOK_MIN_RANGE_PRICE = \"CP_ADV_LOOKBOOK_MIN_RANGE_PRICE\";\n resource.CP_ADV_LOOKBOOK_MAX_RANGE_PRICE = \"CP_ADV_LOOKBOOK_MAX_RANGE_PRICE\";\n resource.CP_ADV_LOOKBOOK_DISPLAY_VENDOR_CODE = \"CP_ADV_LOOKBOOK_DISPLAY_VENDOR_CODE\";\n resource.CP_ADV_MEASUREMENTS_WOMEN_GUIDE_IMAGE_URL = \"CP_ADV_MEASUREMENTS_WOMEN_GUIDE_IMAGE_URL\";\n resource.CP_ADV_MEASUREMENTS_MEN_GUIDE_IMAGE_URL = \"CP_ADV_MEASUREMENTS_MEN_GUIDE_IMAGE_URL\";\n resource.CP_ADV_EM_ALLOW_CONTACT_HEAD_VIEW_DETAILS = \"CP_ADV_EM_ALLOW_CONTACT_HEAD_VIEW_DETAILS\";\n resource.CP_ADV_EM_SHOW_BUDGET_REGARDLESS_OF_TYPE = \"CP_ADV_EM_SHOW_BUDGET_REGARDLESS_OF_TYPE\";\n resource.CP_ADV_EM_SHOW_BUDGET_RANGE_FIELD = \"CP_ADV_EM_SHOW_BUDGET_RANGE_FIELD\";\n resource.CP_ADV_EM_REQUIRE_BUDGET = \"CP_ADV_EM_REQUIRE_BUDGET\";\n resource.CP_ADV_ORDERS_SHOW_SIGNED_SALES_AGREEMENTS = \"CP_ADV_ORDERS_SHOW_SIGNED_SALES_AGREEMENTS\";\n resource.CP_ADV_HIDE_FAVORITES = \"CP_ADV_HIDE_FAVORITES\";\n resource.CP_ADV_LOOKBOOK_DISPLAY_ADDITIONAL_IMAGES = \"CP_ADV_LOOKBOOK_DISPLAY_ADDITIONAL_IMAGES\";\n resource.CP_ADV_ORDERS_SHOW_TIP_AMOUNT = \"CP_ADV_ORDERS_SHOW_TIP_AMOUNT\";\n resource.CP_ADV_ORDERS_TIP_OPTIONS = \"CP_ADV_ORDERS_TIP_OPTIONS\";\n resource.CP_ADV_ORDERS_SHOW_RECEIPT = \"CP_ADV_ORDERS_SHOW_RECEIPT\";\n resource.CP_ADV_BILLING_PAYMENT_RECEIPT = \"CP_ADV_BILLING_PAYMENT_RECEIPT\";\n resource.CP_ADV_BILLING_INVOICE_RECEIPT = \"CP_ADV_BILLING_INVOICE_RECEIPT\";\n resource.CP_ADV_BILLING_UPDATE_PAYMENT = \"CP_ADV_BILLING_UPDATE_PAYMENT\";\n resource.CP_ADV_BILLING_SHOW_PAYMENT_HISTORY = \"CP_ADV_BILLING_SHOW_PAYMENT_HISTORY\";\n resource.CP_ADV_ORDERS_SHOW_ITEM_ADD_ONS = \"CP_ADV_ORDERS_SHOW_ITEM_ADD_ONS\";\n resource.CP_ADV_GENERAL_SELF_HELP_TEXT = \"CP_ADV_GENERAL_SELF_HELP_TEXT\";\n resource.CP_ADV_GENERAL_SELF_REG_REDIRECT = \"CP_ADV_GENERAL_SELF_REG_REDIRECT\";\n resource.CP_ADV_LOOKBOOK_SHOW_TEXT_SEARCH_BOX = \"CP_ADV_LOOKBOOK_SHOW_TEXT_SEARCH_BOX\";\n resource.CP_ADV_ORDERS_ENABLE_PLATFORM_FEE_AMOUNT = \"CP_ADV_ORDERS_ENABLE_PLATFORM_FEE_AMOUNT\";\n\n resource.AO_FAVORITES_EMAIL_SETTINGS = \"AO_FAVORITES_EMAIL_SETTINGS\";\n resource.AO_PAYMENTS_EMAIL_SETTINGS = \"AO_PAYMENTS_EMAIL_SETTINGS\";\n\n resource.CS_ACCESSIBILITY = \"CS_ACCESSIBILITY\";\n resource.CP_ADV_ACCESSIBILITY = \"CP_ADV_ACCESSIBILITY\";\n resource.WF_ACCESSIBILITY = \"WF_ACCESSIBILITY\";\n\n return resource;\n });\n});\n\n","define('modules/resources/contact',['angular', 'moment', './backend-resource'], function (angular, moment) {\n 'use strict';\n\n return angular.module('bl.resources.contact', ['bl.resources.backend-resource', 'bl.security.service'])\n .factory('Contact', function (backendResource, $http, $window, security, PrintHelper) {\n\n var resource = backendResource('contacts');\n\n /**\n *\n * @param contactId - the contact to find the notes for\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getNotes = function (contactId, successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/' + contactId + '/notes/', null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n * This call saves the contact, note and event (if present).\n *\n * @param contact - the fully populated contact\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.saveMultiple = function (contact, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/saveMultiple', contact);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.updateAddressFieldsFromTransaction = function (transaction, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/updateAddressFieldsFromTransaction', transaction);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.updateAddressFieldsFromQuote = function (quote, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/updateAddressFieldsFromQuote', quote);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.updateOptIn = function (contactId, smsOptIn, successcb, errorcb) {\n var httpPromise = $http.put(resource.url + '/updateOptIn/' + contactId, {smsOptIn: smsOptIn});\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.getEventMemberships = function (contactId, successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/' + contactId + '/eventMemberships/');\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.bulkUpdateStatus = function (status, contactIdList, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/bulkUpdateStatus/' + status, contactIdList);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.bulkUpdateEmployee = function (empId, idList, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/bulkUpdateEmployee/' + empId, idList);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.bulkUpdateCategory = function (catId, idList, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/bulkUpdateCategory/' + catId, idList);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.bulkUpdateHowHeard = function (howId, idList, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/bulkUpdateHowHeard/' + howId, idList);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.bulkSubscribeToMailChimpList = function (listId, contactList, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/bulkSubscribeToMailChimpList/' + listId, contactList);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.bulkUpdateSMSOptIn = function (optInValue, idList, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/bulkUpdateSMSOptIn/' + optInValue, idList);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.updateEventDate = function (contactId, eventDate, successcb, errorcb) {\n if (typeof eventDate !== 'string') {\n eventDate = moment(eventDate).format('YYYY-MM-DD');\n }\n\n var httpPromise = $http.put(resource.url + '/updateEventDate/' + contactId + '/' + eventDate);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.updatePaymentProfile = function (contactId, token, provider, id, type, requestId, successcb, errorcb) {\n var httpPromise = $http.put(resource.url + '/updatePaymentProfile/' + contactId , { paymentProfileToken: token, paymentProfileTokenProvider: provider, appointmentRequestId: id, updateType: type, updateRequestId: requestId } );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.reassignSmsToExistingContact = function (existingContactId, unknownContactId, notificationId, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/reassignSmsToExistingContact/' + existingContactId + \"/\" + unknownContactId + '/' + notificationId , {});\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.assignSmsToExistingContact = function (existingContactId, smsMessageId, notificationId, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/assignSmsToExistingContact/' + existingContactId + \"/\" + smsMessageId + '/' + notificationId, {});\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.queryByEventDate = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/byEventDate/' +\n (filterObj.filterObject.eventDateAfter ? moment(filterObj.filterObject.eventDateAfter).format('YYYY-MM-DD') : 'null') + '/' +\n (filterObj.filterObject.eventDateBefore ? moment(filterObj.filterObject.eventDateBefore).format('YYYY-MM-DD') : 'null') + '/' +\n (filterObj.filterObject.eventTypeId || 0) + '/' +\n (filterObj.filterObject.categoryId) + '?' +\n queryParameters.join('&')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.queryByEventLocation = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/byEventLocation/' +\n (filterObj.filterObject.locationTypeId || -1) + '/' +\n (filterObj.filterObject.status || -1) +\n '?' + queryParameters.join('&')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.queryByHowHeard = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/byHowHeard/' +\n (filterObj.filterObject.howHeardId) + '/' +\n (filterObj.filterObject.status || -1) + '/' +\n (filterObj.filterObject.categoryId) +\n '?' + queryParameters.join('&')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.queryByBudgetRange = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/byBudgetRange/' +\n (filterObj.filterObject.budgetRangeId) + '/' +\n (filterObj.filterObject.status || -1) + '/' +\n (filterObj.filterObject.categoryId) +\n '?' + queryParameters.join('&')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.queryByDateAdded = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/byDateAdded/' +\n (filterObj.filterObject.startDate ? moment(filterObj.filterObject.startDate).format('YYYY-MM-DD') : 'null') + '/' +\n (filterObj.filterObject.endDate ? moment(filterObj.filterObject.endDate).format('YYYY-MM-DD') : 'null') + '/' +\n (filterObj.filterObject.eventTypeId || 0) + '/' +\n (filterObj.filterObject.categoryId) + '?' +\n queryParameters.join('&') + (filterObj.filterObject.createdBy ? '&createdBy=' + filterObj.filterObject.createdBy : '')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.queryByDateMerged = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/byDateMerged/' +\n (filterObj.filterObject.startDate ? moment(filterObj.filterObject.startDate).format('YYYY-MM-DD') : 'null') + '/' +\n (filterObj.filterObject.endDate ? moment(filterObj.filterObject.endDate).format('YYYY-MM-DD') : 'null') + '/' +\n (filterObj.filterObject.status || '') + '?' +\n queryParameters.join('&')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.incompleteBMRegistries = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/eventContactsIncompleteBMs?' +\n 'eventDateStart=' + (filterObj.filterObject.eventDateAfter ? moment(filterObj.filterObject.eventDateAfter).format('YYYY-MM-DD') : '') + '&' +\n 'eventDateEnd=' + (filterObj.filterObject.eventDateBefore ? moment(filterObj.filterObject.eventDateBefore).format('YYYY-MM-DD') : '') + '&' +\n 'itemId=' + (filterObj.filterObject.itemId ? filterObj.filterObject.itemId : 0) + '&' +\n 'itemColor=' + (filterObj.filterObject.itemColor ? filterObj.filterObject.itemColor : '') + '&' +\n 'roleIds=' + (filterObj.filterObject.roleIds ? filterObj.filterObject.roleIds : '') + '&' +\n queryParameters.join('&')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.incompleteTuxRegistries = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/eventContactsIncompleteTux?' +\n 'eventDateStart=' + (filterObj.filterObject.eventDateAfter ? moment(filterObj.filterObject.eventDateAfter).format('YYYY-MM-DD') : '') + '&' +\n 'eventDateEnd=' + (filterObj.filterObject.eventDateBefore ? moment(filterObj.filterObject.eventDateBefore).format('YYYY-MM-DD') : '') + '&' +\n 'itemId=' + (filterObj.filterObject.itemId ? filterObj.filterObject.itemId : 0) + '&' +\n 'itemColor=' + (filterObj.filterObject.itemColor ? filterObj.filterObject.itemColor : '') + '&' +\n 'roleIds=' + (filterObj.filterObject.roleIds ? filterObj.filterObject.roleIds : '') + '&' +\n queryParameters.join('&')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.completeBMRegistriesWOPO = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/eventContactCompleteWithoutPOBM?' +\n 'eventDateStart=' + (filterObj.filterObject.eventDateAfter ? moment(filterObj.filterObject.eventDateAfter).format('YYYY-MM-DD') : '') + '&' +\n 'eventDateEnd=' + (filterObj.filterObject.eventDateBefore ? moment(filterObj.filterObject.eventDateBefore).format('YYYY-MM-DD') : '') + '&' +\n 'itemId=' + (filterObj.filterObject.itemId ? filterObj.filterObject.itemId : 0) + '&' +\n 'itemColor=' + (filterObj.filterObject.itemColor ? filterObj.filterObject.itemColor : '') + '&' +\n 'roleIds=' + (filterObj.filterObject.roleIds ? filterObj.filterObject.roleIds : '') + '&' +\n queryParameters.join('&')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.completeTuxRegistriesWOPO = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/eventContactCompleteWithoutPOTux?' +\n 'eventDateStart=' + (filterObj.filterObject.eventDateAfter ? moment(filterObj.filterObject.eventDateAfter).format('YYYY-MM-DD') : '') + '&' +\n 'eventDateEnd=' + (filterObj.filterObject.eventDateBefore ? moment(filterObj.filterObject.eventDateBefore).format('YYYY-MM-DD') : '') + '&' +\n 'itemId=' + (filterObj.filterObject.itemId ? filterObj.filterObject.itemId : 0) + '&' +\n 'itemColor=' + (filterObj.filterObject.itemColor ? filterObj.filterObject.itemColor : '') + '&' +\n 'roleIds=' + (filterObj.filterObject.roleIds ? filterObj.filterObject.roleIds : '') + '&' +\n queryParameters.join('&')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.completeBMRegistries = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/eventContactCompleteBMs?' +\n 'eventDateStart=' + (filterObj.filterObject.eventDateAfter ? moment(filterObj.filterObject.eventDateAfter).format('YYYY-MM-DD') : '') + '&' +\n 'eventDateEnd=' + (filterObj.filterObject.eventDateBefore ? moment(filterObj.filterObject.eventDateBefore).format('YYYY-MM-DD') : '') + '&' +\n 'itemId=' + (filterObj.filterObject.itemId ? filterObj.filterObject.itemId : 0) + '&' +\n 'itemColor=' + (filterObj.filterObject.itemColor ? filterObj.filterObject.itemColor : '') + '&' +\n 'roleIds=' + (filterObj.filterObject.roleIds ? filterObj.filterObject.roleIds : '') + '&' +\n queryParameters.join('&')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.completeTuxRegistries = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/eventContactCompleteTux?' +\n 'eventDateStart=' + (filterObj.filterObject.eventDateAfter ? moment(filterObj.filterObject.eventDateAfter).format('YYYY-MM-DD') : '') + '&' +\n 'eventDateEnd=' + (filterObj.filterObject.eventDateBefore ? moment(filterObj.filterObject.eventDateBefore).format('YYYY-MM-DD') : '') + '&' +\n 'itemId=' + (filterObj.filterObject.itemId ? filterObj.filterObject.itemId : 0) + '&' +\n 'itemColor=' + (filterObj.filterObject.itemColor ? filterObj.filterObject.itemColor : '') + '&' +\n 'roleIds=' + (filterObj.filterObject.roleIds ? filterObj.filterObject.roleIds : '') + '&' +\n queryParameters.join('&')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.withPurchaseHistory = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/contactsWithPurchaseHistory/' +\n (filterObj.filterObject.departmentId || 0) + '/' +\n (filterObj.filterObject.status) + '?' +\n 'dateFrom=' + (filterObj.filterObject.eventDateAfter ? moment(filterObj.filterObject.eventDateAfter).format('YYYY-MM-DD') : '') + '&' +\n 'dateTo=' + (filterObj.filterObject.eventDateBefore ? moment(filterObj.filterObject.eventDateBefore).format('YYYY-MM-DD') : '') + '&' +\n 'trxDateFrom=' + (filterObj.filterObject.trxDateAfter ? moment(filterObj.filterObject.trxDateAfter).format('YYYY-MM-DD') : '') + '&' +\n 'trxDateTo=' + (filterObj.filterObject.trxDateBefore ? moment(filterObj.filterObject.trxDateBefore).format('YYYY-MM-DD') : '') + '&' +\n queryParameters.join('&')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.withoutPurchaseHistory = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/contactsWithNoPurchaseHistory/' +\n (filterObj.filterObject.departmentId || 0) + '/' +\n (filterObj.filterObject.status) + '?' +\n 'dateFrom=' + (filterObj.filterObject.eventDateAfter ? moment(filterObj.filterObject.eventDateAfter).format('YYYY-MM-DD') : '') + '&' +\n 'dateTo=' + (filterObj.filterObject.eventDateBefore ? moment(filterObj.filterObject.eventDateBefore).format('YYYY-MM-DD') : '') + '&' +\n queryParameters.join('&')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.triedOnNoPurchase = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(\n resource.url + '/contactsTriedOnNoPurchase/' +\n (filterObj.filterObject.departmentId1 || 0) + '/' +\n (filterObj.filterObject.vendorId1 || 0) + '/' +\n (filterObj.filterObject.departmentId2 || 0) + '/' +\n (filterObj.filterObject.vendorId2 || 0) + '?' +\n 'itemName=' + (filterObj.filterObject.itemName || '') + '&' +\n queryParameters.join('&')\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n function buildExportForm(url, ids, model, token) {\n var form = document.createElement('form');\n form.setAttribute('method', 'post');\n form.setAttribute('action', resource.url + url);\n form.setAttribute('target', 'view');\n\n var hiddenField = document.createElement('input');\n hiddenField.setAttribute('type', 'hidden');\n hiddenField.setAttribute('name', 'ids');\n hiddenField.setAttribute('value', ids.join());\n form.appendChild(hiddenField);\n\n hiddenField = document.createElement('input');\n hiddenField.setAttribute('type', 'hidden');\n hiddenField.setAttribute('name', 'token');\n hiddenField.setAttribute('value', token);\n form.appendChild(hiddenField);\n\n hiddenField = document.createElement('input');\n hiddenField.setAttribute('type', 'hidden');\n hiddenField.setAttribute('name', 'retailerId');\n hiddenField.setAttribute('value', model.retailerId);\n form.appendChild(hiddenField);\n\n hiddenField = document.createElement('input');\n hiddenField.setAttribute('type', 'hidden');\n hiddenField.setAttribute('name', 'startingRow');\n hiddenField.setAttribute('value', model.startingRow);\n form.appendChild(hiddenField);\n\n hiddenField = document.createElement('input');\n hiddenField.setAttribute('type', 'hidden');\n hiddenField.setAttribute('name', 'startingColumn');\n hiddenField.setAttribute('value', model.startingColumn);\n form.appendChild(hiddenField);\n\n return form;\n }\n\n resource.exportToExcel = function (ids, retailerId) {\n var form = buildExportForm('/contacts.xls', ids, { retailerId: retailerId }, security.readCookie().token);\n document.body.appendChild(form);\n window.open('', 'view');\n form.submit();\n };\n\n resource.createAddressLabels = function (ids, model) {\n if(PrintHelper.usePrintJS()) {\n model.ids = ids.join();\n PrintHelper.buildURLAndPrintPDF(resource.url + '/addressLabels.pdf?', null, model);\n } else {\n var form = buildExportForm('/addressLabels.pdf', ids, model, security.readCookie().token);\n document.body.appendChild(form);\n window.open('', 'view');\n form.submit();\n }\n };\n\n resource.exportContactSheets = function (ids) {\n if(PrintHelper.usePrintJS()) {\n PrintHelper.buildURLAndPrintPDF(resource.url + '/contactSheet.pdf?', null, { ids: ids.join() });\n } else {\n var form = buildExportForm('/contactSheet.pdf', ids, {}, security.readCookie().token);\n document.body.appendChild(form);\n window.open('', 'view');\n form.submit();\n }\n };\n\n resource.import = function (formData, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/import', formData, {\n transformRequest:angular.identity,\n headers: {'Content-Type': undefined}\n });\n\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.findDupes = function (contact, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/findDupes', contact);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.copyToLocationRequest = function (sourceRetailerId, contactId, destRetailerId, successcb, errorcb) {\n var url = resource.url + '/copyToLocationRequest/' + sourceRetailerId + '/' + contactId + '/' + destRetailerId;\n var httpPromise = $http.get(url);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.copyToLocation = function (data, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/copyToLocation', data);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.getDymoLabelConfigs = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/dymoLabelConfigs');\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.getTimeline = function (contact, mode, successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/' + contact.id + '/timeline?' + 'mode=' + (mode || ''));\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.generatePortalDashboardURL = function (contact, successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/' + contact.id + '/generatePortalDashboardURL');\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.generateNewPortalHash = function (contact, successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/' + contact.id + '/generateNewPortalHash');\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.generateEventMemberPortalDashboardURL = function (contact, headContact, successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/' + contact.id + '/' + headContact.id + '/generateEventMemberPortalDashboardURL');\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.generatePortalRegistrationURL = function (successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/generatePortalRegistrationURL');\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.printPurchaseHistory = function (contact, formatType, successcb, errorcb) {\n if(!formatType) {\n formatType = 'SF';\n }\n var httpPromise = $http.post(resource.url + '/printPurchaseHistory/' + formatType, contact);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb);\n };\n\n resource.printQuoteHistory = function (contact, formatType, successcb, errorcb) {\n if(!formatType) {\n formatType = 'SF';\n }\n var httpPromise = $http.post(resource.url + '/printQuoteHistory/' + formatType, contact);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb);\n };\n\n resource.mergePreviewRequest = function (contactId1, contactId2, successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/mergePreviewRequest/'+ contactId1 + '/' + contactId2);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.mergeRequest = function (mergeRequest, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/mergeRequest', mergeRequest);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.portalBillingOverview = function (contactId, successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/portalBillingOverview/'+ contactId);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.validateMergeContactAssociations= function(contact1, contact2, successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/validateMergeContactAssociations/'+ contact1.id + '/' + contact2.id);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.queryCustomFields = function (queryOptions, successcb, errorcb, queryString) {\n var params = {};\n if (queryOptions && queryOptions.filterObject) {\n params = angular.isObject(queryOptions.filterObject) ? JSON.stringify(queryOptions.filterObject) : {};\n }\n\n var queryParameters = resource.buildQueryParameters(queryOptions);\n var httpPromise = $http.post(resource.url + \"/listByCustomFields?\" + queryParameters.join('&') + (queryString || ''), params);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.contactsWithOrWithoutEntity = function(queryOptions, successcb, errorcb, queryString) {\n var params = {};\n if(queryOptions && queryOptions.filterObject) {\n params = angular.isObject(queryOptions.filterObject) ? JSON.stringify(queryOptions.filterObject) : {};\n }\n\n var queryParameters = resource.buildQueryParameters(queryOptions);\n var httpPromise = $http.post(resource.url + \"/contactsWithOrWithoutEntity?\" + queryParameters.join('&') + (queryString || ''), params);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n return resource;\n });\n\n});\n\n","/**\n * @license AngularJS v1.3.15\n * (c) 2010-2014 Google, Inc. http://angularjs.org\n * License: MIT\n */\n(function(window, angular, undefined) {'use strict';\n\n/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n * Any commits to this file should be reviewed with security in mind. *\n * Changes to this file can potentially create security vulnerabilities. *\n * An approval from 2 Core members with history of modifying *\n * this file is required. *\n * *\n * Does the change somehow allow for arbitrary javascript to be executed? *\n * Or allows for someone to change the prototype of built-in objects? *\n * Or gives undesired access to variables likes document or window? *\n * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */\n\nvar $sanitizeMinErr = angular.$$minErr('$sanitize');\n\n/**\n * @ngdoc module\n * @name ngSanitize\n * @description\n *\n * # ngSanitize\n *\n * The `ngSanitize` module provides functionality to sanitize HTML.\n *\n *\n *
\n *\n * See {@link ngSanitize.$sanitize `$sanitize`} for usage.\n */\n\n/*\n * HTML Parser By Misko Hevery (misko@hevery.com)\n * based on: HTML Parser By John Resig (ejohn.org)\n * Original code by Erik Arvidsson, Mozilla Public License\n * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js\n *\n * // Use like so:\n * htmlParser(htmlString, {\n * start: function(tag, attrs, unary) {},\n * end: function(tag) {},\n * chars: function(text) {},\n * comment: function(text) {}\n * });\n *\n */\n\n\n/**\n * @ngdoc service\n * @name $sanitize\n * @kind function\n *\n * @description\n * The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are\n * then serialized back to properly escaped html string. This means that no unsafe input can make\n * it into the returned string, however, since our parser is more strict than a typical browser\n * parser, it's possible that some obscure input, which would be recognized as valid HTML by a\n * browser, won't make it through the sanitizer. The input may also contain SVG markup.\n * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and\n * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.\n *\n * @param {string} html HTML input.\n * @returns {string} Sanitized HTML.\n *\n * @example\n \n \n \n
\n Snippet: \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
DirectiveHowSourceRendered
ng-bind-htmlAutomatically uses $sanitize
<div ng-bind-html=\"snippet\">
</div>
ng-bind-htmlBypass $sanitize by explicitly trusting the dangerous value\n
<div ng-bind-html=\"deliberatelyTrustDangerousSnippet()\">\n</div>
\n
ng-bindAutomatically escapes
<div ng-bind=\"snippet\">
</div>
\n
\n
\n \n it('should sanitize the html snippet by default', function() {\n expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).\n toBe('

an html\\nclick here\\nsnippet

');\n });\n\n it('should inline raw snippet if bound to a trusted value', function() {\n expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).\n toBe(\"

an html\\n\" +\n \"click here\\n\" +\n \"snippet

\");\n });\n\n it('should escape snippet without any filter', function() {\n expect(element(by.css('#bind-default div')).getInnerHtml()).\n toBe(\"<p style=\\\"color:blue\\\">an html\\n\" +\n \"<em onmouseover=\\\"this.textContent='PWN3D!'\\\">click here</em>\\n\" +\n \"snippet</p>\");\n });\n\n it('should update', function() {\n element(by.model('snippet')).clear();\n element(by.model('snippet')).sendKeys('new text');\n expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).\n toBe('new text');\n expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe(\n 'new text');\n expect(element(by.css('#bind-default div')).getInnerHtml()).toBe(\n \"new <b onclick=\\\"alert(1)\\\">text</b>\");\n });\n
\n
\n */\nfunction $SanitizeProvider() {\n this.$get = ['$$sanitizeUri', function($$sanitizeUri) {\n return function(html) {\n var buf = [];\n htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {\n return !/^unsafe/.test($$sanitizeUri(uri, isImage));\n }));\n return buf.join('');\n };\n }];\n}\n\nfunction sanitizeText(chars) {\n var buf = [];\n var writer = htmlSanitizeWriter(buf, angular.noop);\n writer.chars(chars);\n return buf.join('');\n}\n\n\n// Regular Expressions for parsing tags and attributes\nvar START_TAG_REGEXP =\n /^<((?:[a-zA-Z])[\\w:-]*)((?:\\s+[\\w:-]+(?:\\s*=\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*)\\s*(\\/?)\\s*(>?)/,\n END_TAG_REGEXP = /^<\\/\\s*([\\w:-]+)[^>]*>/,\n ATTR_REGEXP = /([\\w:-]+)(?:\\s*=\\s*(?:(?:\"((?:[^\"])*)\")|(?:'((?:[^'])*)')|([^>\\s]+)))?/g,\n BEGIN_TAG_REGEXP = /^/g,\n DOCTYPE_REGEXP = /]*?)>/i,\n CDATA_REGEXP = //g,\n SURROGATE_PAIR_REGEXP = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/g,\n // Match everything outside of normal chars and \" (quote character)\n NON_ALPHANUMERIC_REGEXP = /([^\\#-~| |!])/g;\n\n\n// Good source of info about elements and attributes\n// http://dev.w3.org/html5/spec/Overview.html#semantics\n// http://simon.html5.org/html-elements\n\n// Safe Void Elements - HTML5\n// http://dev.w3.org/html5/spec/Overview.html#void-elements\nvar voidElements = makeMap(\"area,br,col,hr,img,wbr\");\n\n// Elements that you can, intentionally, leave open (and which close themselves)\n// http://dev.w3.org/html5/spec/Overview.html#optional-tags\nvar optionalEndTagBlockElements = makeMap(\"colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr\"),\n optionalEndTagInlineElements = makeMap(\"rp,rt\"),\n optionalEndTagElements = angular.extend({},\n optionalEndTagInlineElements,\n optionalEndTagBlockElements);\n\n// Safe Block Elements - HTML5\nvar blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap(\"address,article,\" +\n \"aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,\" +\n \"h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul\"));\n\n// Inline Elements - HTML5\nvar inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap(\"a,abbr,acronym,b,\" +\n \"bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,\" +\n \"samp,small,span,strike,strong,sub,sup,time,tt,u,var\"));\n\n// SVG Elements\n// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements\nvar svgElements = makeMap(\"animate,animateColor,animateMotion,animateTransform,circle,defs,\" +\n \"desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient,\" +\n \"line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set,\" +\n \"stop,svg,switch,text,title,tspan,use\");\n\n// Special Elements (can contain anything)\nvar specialElements = makeMap(\"script,style\");\n\nvar validElements = angular.extend({},\n voidElements,\n blockElements,\n inlineElements,\n optionalEndTagElements,\n svgElements);\n\n//Attributes that have href and hence need to be sanitized\nvar uriAttrs = makeMap(\"background,cite,href,longdesc,src,usemap,xlink:href\");\n\nvar htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' +\n 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' +\n 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' +\n 'scope,scrolling,shape,size,span,start,summary,target,title,type,' +\n 'valign,value,vspace,width');\n\n// SVG attributes (without \"id\" and \"name\" attributes)\n// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes\nvar svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +\n 'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,' +\n 'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,' +\n 'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,' +\n 'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,' +\n 'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,' +\n 'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,' +\n 'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,' +\n 'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,' +\n 'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,' +\n 'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,' +\n 'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,' +\n 'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,' +\n 'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,' +\n 'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,' +\n 'zoomAndPan');\n\nvar validAttrs = angular.extend({},\n uriAttrs,\n svgAttrs,\n htmlAttrs);\n\nfunction makeMap(str) {\n var obj = {}, items = str.split(','), i;\n for (i = 0; i < items.length; i++) obj[items[i]] = true;\n return obj;\n}\n\n\n/**\n * @example\n * htmlParser(htmlString, {\n * start: function(tag, attrs, unary) {},\n * end: function(tag) {},\n * chars: function(text) {},\n * comment: function(text) {}\n * });\n *\n * @param {string} html string\n * @param {object} handler\n */\nfunction htmlParser(html, handler) {\n if (typeof html !== 'string') {\n if (html === null || typeof html === 'undefined') {\n html = '';\n } else {\n html = '' + html;\n }\n }\n var index, chars, match, stack = [], last = html, text;\n stack.last = function() { return stack[stack.length - 1]; };\n\n while (html) {\n text = '';\n chars = true;\n\n // Make sure we're not in a script or style element\n if (!stack.last() || !specialElements[stack.last()]) {\n\n // Comment\n if (html.indexOf(\"\", index) === index) {\n if (handler.comment) handler.comment(html.substring(4, index));\n html = html.substring(index + 3);\n chars = false;\n }\n // DOCTYPE\n } else if (DOCTYPE_REGEXP.test(html)) {\n match = html.match(DOCTYPE_REGEXP);\n\n if (match) {\n html = html.replace(match[0], '');\n chars = false;\n }\n // end tag\n } else if (BEGING_END_TAGE_REGEXP.test(html)) {\n match = html.match(END_TAG_REGEXP);\n\n if (match) {\n html = html.substring(match[0].length);\n match[0].replace(END_TAG_REGEXP, parseEndTag);\n chars = false;\n }\n\n // start tag\n } else if (BEGIN_TAG_REGEXP.test(html)) {\n match = html.match(START_TAG_REGEXP);\n\n if (match) {\n // We only have a valid start-tag if there is a '>'.\n if (match[4]) {\n html = html.substring(match[0].length);\n match[0].replace(START_TAG_REGEXP, parseStartTag);\n }\n chars = false;\n } else {\n // no ending tag found --- this piece should be encoded as an entity.\n text += '<';\n html = html.substring(1);\n }\n }\n\n if (chars) {\n index = html.indexOf(\"<\");\n\n text += index < 0 ? html : html.substring(0, index);\n html = index < 0 ? \"\" : html.substring(index);\n\n if (handler.chars) handler.chars(decodeEntities(text));\n }\n\n } else {\n // IE versions 9 and 10 do not understand the regex '[^]', so using a workaround with [\\W\\w].\n html = html.replace(new RegExp(\"([\\\\W\\\\w]*)<\\\\s*\\\\/\\\\s*\" + stack.last() + \"[^>]*>\", 'i'),\n function(all, text) {\n text = text.replace(COMMENT_REGEXP, \"$1\").replace(CDATA_REGEXP, \"$1\");\n\n if (handler.chars) handler.chars(decodeEntities(text));\n\n return \"\";\n });\n\n parseEndTag(\"\", stack.last());\n }\n\n if (html == last) {\n throw $sanitizeMinErr('badparse', \"The sanitizer was unable to parse the following block \" +\n \"of html: {0}\", html);\n }\n last = html;\n }\n\n // Clean up any remaining tags\n parseEndTag();\n\n function parseStartTag(tag, tagName, rest, unary) {\n tagName = angular.lowercase(tagName);\n if (blockElements[tagName]) {\n while (stack.last() && inlineElements[stack.last()]) {\n parseEndTag(\"\", stack.last());\n }\n }\n\n if (optionalEndTagElements[tagName] && stack.last() == tagName) {\n parseEndTag(\"\", tagName);\n }\n\n unary = voidElements[tagName] || !!unary;\n\n if (!unary)\n stack.push(tagName);\n\n var attrs = {};\n\n rest.replace(ATTR_REGEXP,\n function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) {\n var value = doubleQuotedValue\n || singleQuotedValue\n || unquotedValue\n || '';\n\n attrs[name] = decodeEntities(value);\n });\n if (handler.start) handler.start(tagName, attrs, unary);\n }\n\n function parseEndTag(tag, tagName) {\n var pos = 0, i;\n tagName = angular.lowercase(tagName);\n if (tagName)\n // Find the closest opened tag of the same type\n for (pos = stack.length - 1; pos >= 0; pos--)\n if (stack[pos] == tagName)\n break;\n\n if (pos >= 0) {\n // Close all the open elements, up the stack\n for (i = stack.length - 1; i >= pos; i--)\n if (handler.end) handler.end(stack[i]);\n\n // Remove the open elements from the stack\n stack.length = pos;\n }\n }\n}\n\nvar hiddenPre=document.createElement(\"pre\");\n/**\n * decodes all entities into regular string\n * @param value\n * @returns {string} A string with decoded entities.\n */\nfunction decodeEntities(value) {\n if (!value) { return ''; }\n\n hiddenPre.innerHTML = value.replace(//g, '>');\n}\n\n/**\n * create an HTML/XML writer which writes to buffer\n * @param {Array} buf use buf.jain('') to get out sanitized html string\n * @returns {object} in the form of {\n * start: function(tag, attrs, unary) {},\n * end: function(tag) {},\n * chars: function(text) {},\n * comment: function(text) {}\n * }\n */\nfunction htmlSanitizeWriter(buf, uriValidator) {\n var ignore = false;\n var out = angular.bind(buf, buf.push);\n return {\n start: function(tag, attrs, unary) {\n tag = angular.lowercase(tag);\n if (!ignore && specialElements[tag]) {\n ignore = tag;\n }\n if (!ignore && validElements[tag] === true) {\n out('<');\n out(tag);\n angular.forEach(attrs, function(value, key) {\n var lkey=angular.lowercase(key);\n var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');\n if (validAttrs[lkey] === true &&\n (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {\n out(' ');\n out(key);\n out('=\"');\n out(encodeEntities(value));\n out('\"');\n }\n });\n out(unary ? '/>' : '>');\n }\n },\n end: function(tag) {\n tag = angular.lowercase(tag);\n if (!ignore && validElements[tag] === true) {\n out('');\n }\n if (tag == ignore) {\n ignore = false;\n }\n },\n chars: function(chars) {\n if (!ignore) {\n out(encodeEntities(chars));\n }\n }\n };\n}\n\n\n// define ngSanitize module and register $sanitize service\nangular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);\n\n/* global sanitizeText: false */\n\n/**\n * @ngdoc filter\n * @name linky\n * @kind function\n *\n * @description\n * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and\n * plain email address links.\n *\n * Requires the {@link ngSanitize `ngSanitize`} module to be installed.\n *\n * @param {string} text Input text.\n * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.\n * @returns {string} Html-linkified text.\n *\n * @usage\n \n *\n * @example\n \n \n \n
\n Snippet: \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
FilterSourceRendered
linky filter\n
<div ng-bind-html=\"snippet | linky\">
</div>
\n
\n
\n
linky target\n
<div ng-bind-html=\"snippetWithTarget | linky:'_blank'\">
</div>
\n
\n
\n
no filter
<div ng-bind=\"snippet\">
</div>
\n \n \n it('should linkify the snippet with urls', function() {\n expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).\n toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' +\n 'another@somewhere.org, and one more: ftp://127.0.0.1/.');\n expect(element.all(by.css('#linky-filter a')).count()).toEqual(4);\n });\n\n it('should not linkify snippet without the linky filter', function() {\n expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()).\n toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' +\n 'another@somewhere.org, and one more: ftp://127.0.0.1/.');\n expect(element.all(by.css('#escaped-html a')).count()).toEqual(0);\n });\n\n it('should update', function() {\n element(by.model('snippet')).clear();\n element(by.model('snippet')).sendKeys('new http://link.');\n expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).\n toBe('new http://link.');\n expect(element.all(by.css('#linky-filter a')).count()).toEqual(1);\n expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText())\n .toBe('new http://link.');\n });\n\n it('should work with the target property', function() {\n expect(element(by.id('linky-target')).\n element(by.binding(\"snippetWithTarget | linky:'_blank'\")).getText()).\n toBe('http://angularjs.org/');\n expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank');\n });\n \n \n */\nangular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {\n var LINKY_URL_REGEXP =\n /((ftp|https?):\\/\\/|(www\\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\\S*[^\\s.;,(){}<>\"”’]/,\n MAILTO_REGEXP = /^mailto:/;\n\n return function(text, target) {\n if (!text) return text;\n var match;\n var raw = text;\n var html = [];\n var url;\n var i;\n while ((match = raw.match(LINKY_URL_REGEXP))) {\n // We can not end in these as they are sometimes found at the end of the sentence\n url = match[0];\n // if we did not match ftp/http/www/mailto then assume mailto\n if (!match[2] && !match[4]) {\n url = (match[3] ? 'http://' : 'mailto:') + url;\n }\n i = match.index;\n addText(raw.substr(0, i));\n addLink(url, match[0].replace(MAILTO_REGEXP, ''));\n raw = raw.substring(i + match[0].length);\n }\n addText(raw);\n return $sanitize(html.join(''));\n\n function addText(text) {\n if (!text) {\n return;\n }\n html.push(sanitizeText(text));\n }\n\n function addLink(url, text) {\n html.push('');\n addText(text);\n html.push('');\n }\n };\n}]);\n\n\n})(window, window.angular);\n\ndefine(\"angular-sanitize\", [\"angular\"], function(){});\n\n","/**\n * @preserve\n * FullCalendar v1.5.4\n * http://arshaw.com/fullcalendar/\n *\n * Use fullcalendar.css for basic styling.\n * For event drag & drop, requires jQuery UI draggable.\n * For event resizing, requires jQuery UI resizable.\n *\n * Copyright (c) 2011 Adam Shaw\n * Dual licensed under the MIT and GPL licenses, located in\n * MIT-LICENSE.txt and GPL-LICENSE.txt respectively.\n *\n * Date: Sun Oct 27 16:52:38 2013 +0200\n *\n */\n\n(function($, undefined) {\n\n\nvar defaults = {\n\n\t// display\n\tdefaultView: 'month',\n\taspectRatio: 1.35,\n\theader: {\n\t\tleft: 'title',\n\t\tcenter: '',\n\t\tright: 'today prev,next'\n\t},\n\tweekends: true,\n slotEventOverlap: true,\n\n\t// editing\n\t//editable: false,\n\t//disableDragging: false,\n\t//disableResizing: false,\n\n\tallDayDefault: true,\n\tignoreTimezone: true,\n\n\t// event ajax\n\tlazyFetching: true,\n\tstartParam: 'start',\n\tendParam: 'end',\n\n\t// time formats\n\ttitleFormat: {\n\t\tmonth: 'MMMM yyyy',\n\t\tweek: \"MMM d[ yyyy]{ '—'[ MMM] d yyyy}\",\n\t\tday: 'dddd, MMM d, yyyy'\n\t},\n\tcolumnFormat: {\n\t\tmonth: 'ddd',\n\t\tweek: 'ddd M/d',\n\t\tday: 'dddd M/d'\n\t},\n\ttimeFormat: { // for event elements\n\t\t'': 'h(:mm)t' // default\n\t},\n\n\t// locale\n\tisRTL: false,\n\tfirstDay: 0,\n\tmonthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'],\n\tmonthNamesShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],\n\tdayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],\n\tdayNamesShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],\n\tbuttonText: {\n\t\tprev: ' ◄ ',\n\t\tnext: ' ► ',\n\t\tprevYear: ' << ',\n\t\tnextYear: ' >> ',\n\t\ttoday: 'today',\n\t\tmonth: 'month',\n\t\tweek: 'week',\n\t\tday: 'day',\n\t\tresourceDay: 'resource'\n\t},\n\n\t// jquery-ui theming\n\ttheme: false,\n\tbuttonIcons: {\n\t\tprev: 'circle-triangle-w',\n\t\tnext: 'circle-triangle-e'\n\t},\n\n\t//selectable: false,\n\tunselectAuto: true,\n\n\tdropAccept: '*'\n\n};\n\n// right-to-left defaults\nvar rtlDefaults = {\n\theader: {\n\t\tleft: 'next,prev today',\n\t\tcenter: '',\n\t\tright: 'title'\n\t},\n\tbuttonText: {\n\t\tprev: ' ► ',\n\t\tnext: ' ◄ ',\n\t\tprevYear: ' >> ',\n\t\tnextYear: ' << '\n\t},\n\tbuttonIcons: {\n\t\tprev: 'circle-triangle-e',\n\t\tnext: 'circle-triangle-w'\n\t}\n};\n\n\n\nvar fc = $.fullCalendar = { version: \"1.5.4\" };\nvar fcViews = fc.views = {};\n\n\n$.fn.fullCalendar = function(options) {\n\n\n\t// method calling\n\tif (typeof options == 'string') {\n\t\tvar args = Array.prototype.slice.call(arguments, 1);\n\t\tvar res;\n\t\tthis.each(function() {\n\t\t\tvar calendar = $.data(this, 'fullCalendar');\n\t\t\tif (calendar && $.isFunction(calendar[options])) {\n\t\t\t\tvar r = calendar[options].apply(calendar, args);\n\t\t\t\tif (res === undefined) {\n\t\t\t\t\tres = r;\n\t\t\t\t}\n\t\t\t\tif (options == 'destroy') {\n\t\t\t\t\t$.removeData(this, 'fullCalendar');\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tif (res !== undefined) {\n\t\t\treturn res;\n\t\t}\n\t\treturn this;\n\t}\n\n\n\t// would like to have this logic in EventManager, but needs to happen before options are recursively extended\n\tvar eventSources = options.eventSources || [];\n\tdelete options.eventSources;\n\tif (options.events) {\n\t\teventSources.push(options.events);\n\t\tdelete options.events;\n\t}\n\n\n\toptions = $.extend(true, {},\n\t\tdefaults,\n\t\t(options.isRTL || options.isRTL===undefined && defaults.isRTL) ? rtlDefaults : {},\n\t\toptions\n\t);\n\n\n\tthis.each(function(i, _element) {\n\t\tvar element = $(_element);\n\t\tvar calendar = new Calendar(element, options, eventSources);\n\t\telement.data('fullCalendar', calendar); // TODO: look into memory leak implications\n\t\tcalendar.render();\n\t});\n\n\n\treturn this;\n\n};\n\n\n// function for adding/overriding defaults\nfunction setDefaults(d) {\n\t$.extend(true, defaults, d);\n}\n\n\n\n\nfunction Calendar(element, options, eventSources, resourceSources) {\n\tvar t = this;\n\n\n\t// exports\n\tt.options = options;\n\tt.render = render;\n\tt.destroy = destroy;\n\tt.refetchEvents = refetchEvents;\n\tt.reportEvents = reportEvents;\n\tt.reportEventChange = reportEventChange;\n\tt.rerenderEvents = rerenderEvents;\n\tt.changeView = changeView;\n\tt.select = select;\n\tt.unselect = unselect;\n\tt.prev = prev;\n\tt.next = next;\n\tt.prevYear = prevYear;\n\tt.nextYear = nextYear;\n\tt.today = today;\n\tt.gotoDate = gotoDate;\n\tt.incrementDate = incrementDate;\n\tt.formatDate = function(format, date) { return formatDate(format, date, options) };\n\tt.formatDates = function(format, date1, date2) { return formatDates(format, date1, date2, options) };\n\tt.getDate = getDate;\n\tt.getView = getView;\n\tt.option = option;\n\tt.trigger = trigger;\n\n\n\t// imports\n\tEventManager.call(t, options, eventSources);\n\tvar isFetchNeeded = t.isFetchNeeded;\n\tvar fetchEvents = t.fetchEvents;\n\n ResourceManager.call(t, options);\n\n\t// locals\n\tvar _element = element[0];\n\tvar header;\n\tvar headerElement;\n\tvar content;\n\tvar tm; // for making theme classes\n\tvar currentView;\n\tvar viewInstances = {};\n\tvar elementOuterWidth;\n\tvar suggestedViewHeight;\n\tvar absoluteViewElement;\n\tvar resizeUID = 0;\n\tvar ignoreWindowResize = 0;\n\tvar date = new Date();\n\tvar events = [];\n\tvar _dragElement;\n\n\n\n\t/* Main Rendering\n\t-----------------------------------------------------------------------------*/\n\n\n\tsetYMD(date, options.year, options.month, options.date);\n\n\n\tfunction render(inc) {\n\t\tif (!content) {\n\t\t\tinitialRender();\n\t\t}else{\n\t\t\tcalcSize();\n\t\t\tmarkSizesDirty();\n\t\t\tmarkEventsDirty();\n\t\t\trenderView(inc);\n\t\t}\n\t}\n\n\n\tfunction initialRender() {\n\t\ttm = options.theme ? 'ui' : 'fc';\n\t\telement.addClass('fc');\n\t\tif (options.isRTL) {\n\t\t\telement.addClass('fc-rtl');\n\t\t}\n\t\tif (options.theme) {\n\t\t\telement.addClass('ui-widget');\n\t\t}\n\t\tcontent = $(\"
\")\n\t\t\t.prependTo(element);\n\t\theader = new Header(t, options);\n\t\theaderElement = header.render();\n\t\tif (headerElement) {\n\t\t\telement.prepend(headerElement);\n\t\t}\n\t\tchangeView(options.defaultView);\n\t\t$(window).resize(windowResize);\n\t\t// needed for IE in a 0x0 iframe, b/c when it is resized, never triggers a windowResize\n\t\tif (!bodyVisible()) {\n\t\t\tlateRender();\n\t\t}\n\t}\n\n\n\t// called when we know the calendar couldn't be rendered when it was initialized,\n\t// but we think it's ready now\n\tfunction lateRender() {\n\t\tsetTimeout(function() { // IE7 needs this so dimensions are calculated correctly\n\t\t\tif (!currentView.start && bodyVisible()) { // !currentView.start makes sure this never happens more than once\n\t\t\t\trenderView();\n\t\t\t}\n\t\t},0);\n\t}\n\n\n\tfunction destroy() {\n\t\t$(window).unbind('resize', windowResize);\n\t\theader.destroy();\n\t\tcontent.remove();\n\t\telement.removeClass('fc fc-rtl ui-widget');\n\t}\n\n\tfunction elementVisible() {\n\t\treturn _element.offsetWidth !== 0;\n\t}\n\n\tfunction bodyVisible() {\n\t\treturn $('body')[0].offsetWidth !== 0;\n\t}\n\n\t/* View Rendering\n\t-----------------------------------------------------------------------------*/\n\n\t// TODO: improve view switching (still weird transition in IE, and FF has whiteout problem)\n\n\tfunction changeView(newViewName) {\n\t\tif (!currentView || newViewName != currentView.name) {\n\t\t\tignoreWindowResize++; // because setMinHeight might change the height before render (and subsequently setSize) is reached\n\n\t\t\tunselect();\n\n\t\t\tvar oldView = currentView;\n\t\t\tvar newViewElement;\n\n\t\t\tif (oldView) {\n\t\t\t\t(oldView.beforeHide || noop)(); // called before changing min-height. if called after, scroll state is reset (in Opera)\n\t\t\t\tsetMinHeight(content, content.height());\n\t\t\t\toldView.element.hide();\n\t\t\t}else{\n\t\t\t\tsetMinHeight(content, 1); // needs to be 1 (not 0) for IE7, or else view dimensions miscalculated\n\t\t\t}\n\t\t\tcontent.css('overflow', 'hidden');\n\n\t\t\tcurrentView = viewInstances[newViewName];\n\t\t\tif (currentView) {\n\t\t\t\tcurrentView.element.show();\n\t\t\t}else{\n\t\t\t\tcurrentView = viewInstances[newViewName] = new fcViews[newViewName](\n\t\t\t\t\tnewViewElement = absoluteViewElement =\n\t\t\t\t\t\t$(\"
\")\n\t\t\t\t\t\t\t.appendTo(content),\n\t\t\t\t\tt // the calendar object\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (oldView) {\n\t\t\t\theader.deactivateButton(oldView.name);\n\t\t\t}\n\t\t\theader.activateButton(newViewName);\n\n\t\t\trenderView(); // after height has been set, will make absoluteViewElement's position=relative, then set to null\n\n\t\t\tcontent.css('overflow', '');\n\t\t\tif (oldView) {\n\t\t\t\tsetMinHeight(content, 1);\n\t\t\t}\n\n\t\t\tif (!newViewElement) {\n\t\t\t\t(currentView.afterShow || noop)(); // called after setting min-height/overflow, so in final scroll state (for Opera)\n\t\t\t}\n\n\t\t\tignoreWindowResize--;\n\t\t}\n\t}\n\n\tfunction renderView(inc) {\n\t\tif (elementVisible()) {\n\t\t\tignoreWindowResize++; // because renderEvents might temporarily change the height before setSize is reached\n\n\t\t\tunselect();\n\n\t\t\tif (suggestedViewHeight === undefined) {\n\t\t\t\tcalcSize();\n\t\t\t}\n\n\t\t\tvar forceEventRender = false;\n\t\t\tif (!currentView.start || inc || date < currentView.start || date >= currentView.end) {\n\t\t\t\t// view must render an entire new date range (and refetch/render events)\n\t\t\t\tcurrentView.render(date, inc || 0); // responsible for clearing events\n\t\t\t\tsetSize(true);\n\t\t\t\tforceEventRender = true;\n\t\t\t}\n\t\t\telse if (currentView.sizeDirty) {\n\t\t\t\t// view must resize (and rerender events)\n\t\t\t\tcurrentView.clearEvents();\n\t\t\t\tsetSize();\n\t\t\t\tforceEventRender = true;\n\t\t\t}\n\t\t\telse if (currentView.eventsDirty) {\n\t\t\t\tcurrentView.clearEvents();\n\t\t\t\tforceEventRender = true;\n\t\t\t}\n\t\t\tcurrentView.sizeDirty = false;\n\t\t\tcurrentView.eventsDirty = false;\n\t\t\tupdateEvents(forceEventRender);\n\n\t\t\telementOuterWidth = element.outerWidth();\n\n\t\t\theader.updateTitle(currentView.title);\n\t\t\tvar today = new Date();\n\t\t\tif (today >= currentView.start && today < currentView.end) {\n\t\t\t\theader.disableButton('today');\n\t\t\t}else{\n\t\t\t\theader.enableButton('today');\n\t\t\t}\n\n\t\t\tignoreWindowResize--;\n\t\t\tcurrentView.trigger('viewDisplay', _element);\n\t\t}\n\t}\n\n\t/* Resizing\n\t-----------------------------------------------------------------------------*/\n\n\tfunction updateSize() {\n\t\tmarkSizesDirty();\n\t\tif (elementVisible()) {\n\t\t\tcalcSize();\n\t\t\tsetSize();\n\t\t\tunselect();\n\t\t\tcurrentView.clearEvents();\n\t\t\tcurrentView.renderEvents(events);\n\t\t\tcurrentView.sizeDirty = false;\n\t\t}\n\t}\n\n\tfunction markSizesDirty() {\n\t\t$.each(viewInstances, function(i, inst) {\n\t\t\tinst.sizeDirty = true;\n\t\t});\n\t}\n\n\tfunction calcSize() {\n\t\tif (options.contentHeight) {\n\t\t\tsuggestedViewHeight = options.contentHeight;\n\t\t}\n\t\telse if (options.height) {\n\t\t\tsuggestedViewHeight = options.height - (headerElement ? headerElement.height() : 0) - vsides(content);\n\t\t}\n\t\telse {\n\t\t\tsuggestedViewHeight = Math.round(content.width() / Math.max(options.aspectRatio, .5));\n\t\t}\n\t}\n\n\tfunction setSize(dateChanged) { // todo: dateChanged?\n\t\tignoreWindowResize++;\n\t\tcurrentView.setHeight(suggestedViewHeight, dateChanged);\n\t\tif (absoluteViewElement) {\n\t\t\tabsoluteViewElement.css('position', 'relative');\n\t\t\tabsoluteViewElement = null;\n\t\t}\n\t\tcurrentView.setWidth(content.width(), dateChanged);\n\t\tignoreWindowResize--;\n\t}\n\n\tfunction windowResize() {\n\t\tif (!ignoreWindowResize) {\n\t\t\tif (currentView.start) { // view has already been rendered\n\t\t\t\tvar uid = ++resizeUID;\n\t\t\t\tsetTimeout(function() { // add a delay\n\t\t\t\t\tif (uid == resizeUID && !ignoreWindowResize && elementVisible()) {\n\t\t\t\t\t\tif (elementOuterWidth != (elementOuterWidth = element.outerWidth())) {\n\t\t\t\t\t\t\tignoreWindowResize++; // in case the windowResize callback changes the height\n\t\t\t\t\t\t\tupdateSize();\n\t\t\t\t\t\t\tcurrentView.trigger('windowResize', _element);\n\t\t\t\t\t\t\tignoreWindowResize--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}, 200);\n\t\t\t}else{\n\t\t\t\t// calendar must have been initialized in a 0x0 iframe that has just been resized\n\t\t\t\tlateRender();\n\t\t\t}\n\t\t}\n\t}\n\n\t/* Event Fetching/Rendering\n\t-----------------------------------------------------------------------------*/\n\n\t// fetches events if necessary, rerenders events if necessary (or if forced)\n\tfunction updateEvents(forceRender) {\n\t\tif (!options.lazyFetching || isFetchNeeded(currentView.visStart, currentView.visEnd)) {\n\t\t\trefetchEvents();\n\t\t}\n\t\telse if (forceRender) {\n\t\t\trerenderEvents();\n\t\t}\n\t}\n\n\tfunction refetchEvents() {\n\t\tfetchEvents(currentView.visStart, currentView.visEnd); // will call reportEvents\n\t}\n\n\t// called when event data arrives\n\tfunction reportEvents(_events) {\n\t\tevents = _events;\n\t\trerenderEvents();\n\t}\n\n\t// called when a single event's data has been changed\n\tfunction reportEventChange(eventID) {\n\t\trerenderEvents(eventID);\n\t}\n\n\t// attempts to rerenderEvents\n\tfunction rerenderEvents(modifiedEventID) {\n\t\tmarkEventsDirty();\n\t\tif (elementVisible()) {\n\t\t\tcurrentView.clearEvents();\n\t\t\tcurrentView.renderEvents(events, modifiedEventID);\n\t\t\tcurrentView.eventsDirty = false;\n\t\t}\n\t}\n\n\tfunction markEventsDirty() {\n\t\t$.each(viewInstances, function(i, inst) {\n\t\t\tinst.eventsDirty = true;\n\t\t});\n\t}\n\n\t/* Selection\n\t-----------------------------------------------------------------------------*/\n\n\tfunction select(start, end, allDay) {\n\t\tcurrentView.select(start, end, allDay===undefined ? true : allDay);\n\t}\n\n\tfunction unselect() { // safe to be called before renderView\n\t\tif (currentView) {\n\t\t\tcurrentView.unselect();\n\t\t}\n\t}\n\n\t/* Date\n\t-----------------------------------------------------------------------------*/\n\n\tfunction prev() {\n\t\trenderView(-1);\n\t}\n\n\tfunction next() {\n\t\trenderView(1);\n\t}\n\n\tfunction prevYear() {\n\t\taddYears(date, -1);\n\t\trenderView();\n\t}\n\n\tfunction nextYear() {\n\t\taddYears(date, 1);\n\t\trenderView();\n\t}\n\n\tfunction today() {\n\t\tdate = new Date();\n\t\trenderView();\n\t}\n\n\tfunction gotoDate(year, month, dateOfMonth) {\n\t\tif (year instanceof Date) {\n\t\t\tdate = cloneDate(year); // provided 1 argument, a Date\n\t\t}else{\n\t\t\tsetYMD(date, year, month, dateOfMonth);\n\t\t}\n\t\trenderView();\n\t}\n\n\tfunction incrementDate(years, months, days) {\n\t\tif (years !== undefined) {\n\t\t\taddYears(date, years);\n\t\t}\n\t\tif (months !== undefined) {\n\t\t\taddMonths(date, months);\n\t\t}\n\t\tif (days !== undefined) {\n\t\t\taddDays(date, days);\n\t\t}\n\t\trenderView();\n\t}\n\n\tfunction getDate() {\n\t\treturn cloneDate(date);\n\t}\n\n\t/* Misc\n\t-----------------------------------------------------------------------------*/\n\n\tfunction getView() {\n\t\treturn currentView;\n\t}\n\n\tfunction option(name, value) {\n\t\tif (value === undefined) {\n\t\t\treturn options[name];\n\t\t}\n\t\tif (name == 'height' || name == 'contentHeight' || name == 'aspectRatio') {\n\t\t\toptions[name] = value;\n\t\t\tupdateSize();\n\t\t}\n\t}\n\n\tfunction trigger(name, thisObj) {\n\t\tif (options[name]) {\n\t\t\treturn options[name].apply(\n\t\t\t\tthisObj || _element,\n\t\t\t\tArray.prototype.slice.call(arguments, 2)\n\t\t\t);\n\t\t}\n\t}\n\n\t/* External Dragging\n\t------------------------------------------------------------------------*/\n\n\tif (options.droppable) {\n\t\t$(document)\n\t\t\t.bind('dragstart', function(ev, ui) {\n\t\t\t\tvar _e = ev.target;\n\t\t\t\tvar e = $(_e);\n\t\t\t\tif (!e.parents('.fc').length) { // not already inside a calendar\n\t\t\t\t\tvar accept = options.dropAccept;\n\t\t\t\t\tif ($.isFunction(accept) ? accept.call(_e, e) : e.is(accept)) {\n\t\t\t\t\t\t_dragElement = _e;\n\t\t\t\t\t\tcurrentView.dragStart(_dragElement, ev, ui);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t\t.bind('dragstop', function(ev, ui) {\n\t\t\t\tif (_dragElement) {\n\t\t\t\t\tcurrentView.dragStop(_dragElement, ev, ui);\n\t\t\t\t\t_dragElement = null;\n\t\t\t\t}\n\t\t\t});\n\t}\n}\n\nfunction Header(calendar, options) {\n\tvar t = this;\n\n\t// exports\n\tt.render = render;\n\tt.destroy = destroy;\n\tt.updateTitle = updateTitle;\n\tt.activateButton = activateButton;\n\tt.deactivateButton = deactivateButton;\n\tt.disableButton = disableButton;\n\tt.enableButton = enableButton;\n\n\n\t// locals\n\tvar element = $([]);\n\tvar tm;\n\n\n\n\tfunction render() {\n\t\ttm = options.theme ? 'ui' : 'fc';\n\t\tvar sections = options.header;\n\t\tif (sections) {\n\t\t\telement = $(\"\")\n\t\t\t\t.append(\n\t\t\t\t\t$(\"\")\n\t\t\t\t\t\t.append(renderSection('left'))\n\t\t\t\t\t\t.append(renderSection('center'))\n\t\t\t\t\t\t.append(renderSection('right'))\n\t\t\t\t);\n\t\t\treturn element;\n\t\t}\n\t}\n\n\n\tfunction destroy() {\n\t\telement.remove();\n\t}\n\n\n\tfunction renderSection(position) {\n\t\tvar e = $(\"\" +\n\t\t\t\"\";\n\t\tfor (i=0; i\"; // need fc- for setDayID\n\t\t}\n\t\ts +=\n\t\t\t\"\" +\n\t\t\t\"\" +\n\t\t\t\"\";\n\t\tfor (i=0; i\";\n\t\t\tfor (j=0; j\" + // need fc- for setDayID\n\t\t\t\t\t\"
\" +\n\t\t\t\t\t(showNumbers ?\n\t\t\t\t\t\t\"
\" :\n\t\t\t\t\t\t''\n\t\t\t\t\t\t) +\n\t\t\t\t\t\"
\" +\n\t\t\t\t\t\"
 
\" +\n\t\t\t\t\t\"
\" +\n\t\t\t\t\t\"
\" +\n\t\t\t\t\t\"\";\n\t\t\t}\n\t\t\ts +=\n\t\t\t\t\"\";\n\t\t}\n\t\ts +=\n\t\t\t\"
\" +\n\t\t\t\"
\");\n\t\tvar buttonStr = options.header[position];\n\t\tif (buttonStr) {\n\t\t\t$.each(buttonStr.split(' '), function(i) {\n\t\t\t\tif (i > 0) {\n\t\t\t\t\te.append(\"\");\n\t\t\t\t}\n\t\t\t\tvar prevButton;\n\t\t\t\t$.each(this.split(','), function(j, buttonName) {\n\t\t\t\t\tif (buttonName == 'title') {\n\t\t\t\t\t\te.append(\"

 

\");\n\t\t\t\t\t\tif (prevButton) {\n\t\t\t\t\t\t\tprevButton.addClass(tm + '-corner-right');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tprevButton = null;\n\t\t\t\t\t}else{\n\t\t\t\t\t\tvar buttonClick;\n\t\t\t\t\t\tif (calendar[buttonName]) {\n\t\t\t\t\t\t\tbuttonClick = calendar[buttonName]; // calendar method\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (fcViews[buttonName]) {\n\t\t\t\t\t\t\tbuttonClick = function() {\n\t\t\t\t\t\t\t\tbutton.removeClass(tm + '-state-hover'); // forget why\n\t\t\t\t\t\t\t\tcalendar.changeView(buttonName);\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (buttonClick) {\n\t\t\t\t\t\t\tvar icon = options.theme ? smartProperty(options.buttonIcons, buttonName) : null; // why are we using smartProperty here?\n\t\t\t\t\t\t\tvar text = smartProperty(options.buttonText, buttonName); // why are we using smartProperty here?\n\t\t\t\t\t\t\tvar button = $(\n\t\t\t\t\t\t\t\t\"\" +\n\t\t\t\t\t\t\t\t\t\"\" +\n\t\t\t\t\t\t\t\t\t\t\"\" +\n\t\t\t\t\t\t\t\t\t\t\t(icon ?\n\t\t\t\t\t\t\t\t\t\t\t\t\"\" +\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"\" +\n\t\t\t\t\t\t\t\t\t\t\t\t\"\" :\n\t\t\t\t\t\t\t\t\t\t\t\ttext\n\t\t\t\t\t\t\t\t\t\t\t\t) +\n\t\t\t\t\t\t\t\t\t\t\"\" +\n\t\t\t\t\t\t\t\t\t\t\"\" +\n\t\t\t\t\t\t\t\t\t\"\" +\n\t\t\t\t\t\t\t\t\"\"\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (button) {\n\t\t\t\t\t\t\t\tbutton\n\t\t\t\t\t\t\t\t\t.click(function() {\n\t\t\t\t\t\t\t\t\t\tif (!button.hasClass(tm + '-state-disabled')) {\n\t\t\t\t\t\t\t\t\t\t\tbuttonClick();\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t.mousedown(function() {\n\t\t\t\t\t\t\t\t\t\tbutton\n\t\t\t\t\t\t\t\t\t\t\t.not('.' + tm + '-state-active')\n\t\t\t\t\t\t\t\t\t\t\t.not('.' + tm + '-state-disabled')\n\t\t\t\t\t\t\t\t\t\t\t.addClass(tm + '-state-down');\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t.mouseup(function() {\n\t\t\t\t\t\t\t\t\t\tbutton.removeClass(tm + '-state-down');\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t.hover(\n\t\t\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t\t\tbutton\n\t\t\t\t\t\t\t\t\t\t\t\t.not('.' + tm + '-state-active')\n\t\t\t\t\t\t\t\t\t\t\t\t.not('.' + tm + '-state-disabled')\n\t\t\t\t\t\t\t\t\t\t\t\t.addClass(tm + '-state-hover');\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t\t\tbutton\n\t\t\t\t\t\t\t\t\t\t\t\t.removeClass(tm + '-state-hover')\n\t\t\t\t\t\t\t\t\t\t\t\t.removeClass(tm + '-state-down');\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t.appendTo(e);\n\t\t\t\t\t\t\t\tif (!prevButton) {\n\t\t\t\t\t\t\t\t\tbutton.addClass(tm + '-corner-left');\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tprevButton = button;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (prevButton) {\n\t\t\t\t\tprevButton.addClass(tm + '-corner-right');\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\treturn e;\n\t}\n\n\n\tfunction updateTitle(html) {\n\t\telement.find('h2')\n\t\t\t.html(html);\n\t}\n\n\n\tfunction activateButton(buttonName) {\n\t\telement.find('span.fc-button-' + buttonName)\n\t\t\t.addClass(tm + '-state-active');\n\t}\n\n\n\tfunction deactivateButton(buttonName) {\n\t\telement.find('span.fc-button-' + buttonName)\n\t\t\t.removeClass(tm + '-state-active');\n\t}\n\n\n\tfunction disableButton(buttonName) {\n\t\telement.find('span.fc-button-' + buttonName)\n\t\t\t.addClass(tm + '-state-disabled');\n\t}\n\n\n\tfunction enableButton(buttonName) {\n\t\telement.find('span.fc-button-' + buttonName)\n\t\t\t.removeClass(tm + '-state-disabled');\n\t}\n\n\n}\n\nfc.sourceNormalizers = [];\nfc.sourceFetchers = [];\n\nvar ajaxDefaults = {\n\tdataType: 'json',\n\tcache: false\n};\n\nvar eventGUID = 1;\n\n\nfunction EventManager(options, _sources) {\n\tvar t = this;\n\n\n\t// exports\n\tt.isFetchNeeded = isFetchNeeded;\n\tt.fetchEvents = fetchEvents;\n\tt.addEventSource = addEventSource;\n\tt.removeEventSource = removeEventSource;\n\tt.updateEvent = updateEvent;\n\tt.renderEvent = renderEvent;\n\tt.removeEvents = removeEvents;\n\tt.clientEvents = clientEvents;\n\tt.normalizeEvent = normalizeEvent;\n\n\n\t// imports\n\tvar trigger = t.trigger;\n\tvar getView = t.getView;\n\tvar reportEvents = t.reportEvents;\n\n\n\t// locals\n\tvar stickySource = { events: [] };\n\tvar sources = [ stickySource ];\n\tvar rangeStart, rangeEnd;\n\tvar currentFetchID = 0;\n\tvar pendingSourceCnt = 0;\n\tvar loadingLevel = 0;\n\tvar cache = [];\n\n\n\tfor (var i=0; i<_sources.length; i++) {\n\t\t_addEventSource(_sources[i]);\n\t}\n\n\n\n\t/* Fetching\n\t-----------------------------------------------------------------------------*/\n\n\n\tfunction isFetchNeeded(start, end) {\n\t\treturn !rangeStart || start < rangeStart || end > rangeEnd;\n\t}\n\n\n\tfunction fetchEvents(start, end) {\n\t\trangeStart = start;\n\t\trangeEnd = end;\n\t\tcache = [];\n\t\tvar fetchID = ++currentFetchID;\n\t\tvar len = sources.length;\n\t\tpendingSourceCnt = len;\n\t\tfor (var i=0; i)), return null instead\n\treturn null;\n}\n\n\nfunction parseISO8601(s, ignoreTimezone) { // ignoreTimezone defaults to false\n\t// derived from http://delete.me.uk/2005/03/iso8601.html\n\t// TODO: for a know glitch/feature, read tests/issue_206_parseDate_dst.html\n\tvar m = s.match(/^([0-9]{4})(-([0-9]{2})(-([0-9]{2})([T ]([0-9]{2}):([0-9]{2})(:([0-9]{2})(\\.([0-9]+))?)?(Z|(([-+])([0-9]{2})(:?([0-9]{2}))?))?)?)?)?$/);\n\tif (!m) {\n\t\treturn null;\n\t}\n\tvar date = new Date(m[1], 0, 1);\n\tif (ignoreTimezone || !m[13]) {\n\t\tvar check = new Date(m[1], 0, 1, 9, 0);\n\t\tif (m[3]) {\n\t\t\tdate.setMonth(m[3] - 1);\n\t\t\tcheck.setMonth(m[3] - 1);\n\t\t}\n\t\tif (m[5]) {\n\t\t\tdate.setDate(m[5]);\n\t\t\tcheck.setDate(m[5]);\n\t\t}\n\t\tfixDate(date, check);\n\t\tif (m[7]) {\n\t\t\tdate.setHours(m[7]);\n\t\t}\n\t\tif (m[8]) {\n\t\t\tdate.setMinutes(m[8]);\n\t\t}\n\t\tif (m[10]) {\n\t\t\tdate.setSeconds(m[10]);\n\t\t}\n\t\tif (m[12]) {\n\t\t\tdate.setMilliseconds(Number(\"0.\" + m[12]) * 1000);\n\t\t}\n\t\tfixDate(date, check);\n\t}else{\n\t\tdate.setUTCFullYear(\n\t\t\tm[1],\n\t\t\tm[3] ? m[3] - 1 : 0,\n\t\t\tm[5] || 1\n\t\t);\n\t\tdate.setUTCHours(\n\t\t\tm[7] || 0,\n\t\t\tm[8] || 0,\n\t\t\tm[10] || 0,\n\t\t\tm[12] ? Number(\"0.\" + m[12]) * 1000 : 0\n\t\t);\n\t\tif (m[14]) {\n\t\t\tvar offset = Number(m[16]) * 60 + (m[18] ? Number(m[18]) : 0);\n\t\t\toffset *= m[15] == '-' ? 1 : -1;\n\t\t\tdate = new Date(+date + (offset * 60 * 1000));\n\t\t}\n\t}\n\treturn date;\n}\n\n\nfunction parseTime(s) { // returns minutes since start of day\n\tif (typeof s == 'number') { // an hour\n\t\treturn s * 60;\n\t}\n\tif (typeof s == 'object') { // a Date object\n\t\treturn s.getHours() * 60 + s.getMinutes();\n\t}\n\tvar m = s.match(/(\\d+)(?::(\\d+))?\\s*(\\w+)?/);\n\tif (m) {\n\t\tvar h = parseInt(m[1], 10);\n\t\tif (m[3]) {\n\t\t\th %= 12;\n\t\t\tif (m[3].toLowerCase().charAt(0) == 'p') {\n\t\t\t\th += 12;\n\t\t\t}\n\t\t}\n\t\treturn h * 60 + (m[2] ? parseInt(m[2], 10) : 0);\n\t}\n}\n\n\n\n/* Date Formatting\n-----------------------------------------------------------------------------*/\n// TODO: use same function formatDate(date, [date2], format, [options])\n\n\nfunction formatDate(date, format, options) {\n\treturn formatDates(date, null, format, options);\n}\n\n\nfunction formatDates(date1, date2, format, options) {\n\toptions = options || defaults;\n\tvar date = date1,\n\t\totherDate = date2,\n\t\ti, len = format.length, c,\n\t\ti2, formatter,\n\t\tres = '';\n\tfor (i=0; ii; i2--) {\n\t\t\t\tif (formatter = dateFormatters[format.substring(i, i2)]) {\n\t\t\t\t\tif (date) {\n\t\t\t\t\t\tres += formatter(date, options);\n\t\t\t\t\t}\n\t\t\t\t\ti = i2 - 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (i2 == i) {\n\t\t\t\tif (date) {\n\t\t\t\t\tres += c;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn res;\n};\n\n\nvar dateFormatters = {\n\ts\t: function(d)\t{ return d.getSeconds() },\n\tss\t: function(d)\t{ return zeroPad(d.getSeconds()) },\n\tm\t: function(d)\t{ return d.getMinutes() },\n\tmm\t: function(d)\t{ return zeroPad(d.getMinutes()) },\n\th\t: function(d)\t{ return d.getHours() % 12 || 12 },\n\thh\t: function(d)\t{ return zeroPad(d.getHours() % 12 || 12) },\n\tH\t: function(d)\t{ return d.getHours() },\n\tHH\t: function(d)\t{ return zeroPad(d.getHours()) },\n\td\t: function(d)\t{ return d.getDate() },\n\tdd\t: function(d)\t{ return zeroPad(d.getDate()) },\n\tddd\t: function(d,o)\t{ return o.dayNamesShort[d.getDay()] },\n\tdddd: function(d,o)\t{ return o.dayNames[d.getDay()] },\n\tM\t: function(d)\t{ return d.getMonth() + 1 },\n\tMM\t: function(d)\t{ return zeroPad(d.getMonth() + 1) },\n\tMMM\t: function(d,o)\t{ return o.monthNamesShort[d.getMonth()] },\n\tMMMM: function(d,o)\t{ return o.monthNames[d.getMonth()] },\n\tyy\t: function(d)\t{ return (d.getFullYear()+'').substring(2) },\n\tyyyy: function(d)\t{ return d.getFullYear() },\n\tt\t: function(d)\t{ return d.getHours() < 12 ? 'a' : 'p' },\n\ttt\t: function(d)\t{ return d.getHours() < 12 ? 'am' : 'pm' },\n\tT\t: function(d)\t{ return d.getHours() < 12 ? 'A' : 'P' },\n\tTT\t: function(d)\t{ return d.getHours() < 12 ? 'AM' : 'PM' },\n\tu\t: function(d)\t{ return formatDate(d, \"yyyy-MM-dd'T'HH:mm:ss'Z'\") },\n\tS\t: function(d)\t{\n\t\tvar date = d.getDate();\n\t\tif (date > 10 && date < 20) {\n\t\t\treturn 'th';\n\t\t}\n\t\treturn ['st', 'nd', 'rd'][date%10-1] || 'th';\n\t}\n};\n\n\n\nfc.applyAll = applyAll;\n\n\n/* Event Date Math\n-----------------------------------------------------------------------------*/\n\n\nfunction exclEndDay(event) {\n\tif (event.end) {\n\t\treturn _exclEndDay(event.end, event.allDay);\n\t}else{\n\t\treturn addDays(cloneDate(event.start), 1);\n\t}\n}\n\n\nfunction _exclEndDay(end, allDay) {\n\tend = cloneDate(end);\n\treturn allDay || end.getHours() || end.getMinutes() ? addDays(end, 1) : clearTime(end);\n}\n\n\nfunction segCmp(a, b) {\n\treturn (b.msLength - a.msLength) * 100 + (a.event.start - b.event.start);\n}\n\n\nfunction segsCollide(seg1, seg2) {\n\treturn seg1.end > seg2.start && seg1.start < seg2.end;\n}\n\n\n\n/* Event Sorting\n-----------------------------------------------------------------------------*/\n\n\n// event rendering utilities\nfunction sliceSegs(events, visEventEnds, start, end) {\n\tvar segs = [],\n\t\ti, len=events.length, event,\n\t\teventStart, eventEnd,\n\t\tsegStart, segEnd,\n\t\tisStart, isEnd;\n\tfor (i=0; i start && eventStart < end) {\n\t\t\tif (eventStart < start) {\n\t\t\t\tsegStart = cloneDate(start);\n\t\t\t\tisStart = false;\n\t\t\t}else{\n\t\t\t\tsegStart = eventStart;\n\t\t\t\tisStart = true;\n\t\t\t}\n\t\t\tif (eventEnd > end) {\n\t\t\t\tsegEnd = cloneDate(end);\n\t\t\t\tisEnd = false;\n\t\t\t}else{\n\t\t\t\tsegEnd = eventEnd;\n\t\t\t\tisEnd = true;\n\t\t\t}\n\t\t\tsegs.push({\n\t\t\t\tevent: event,\n\t\t\t\tstart: segStart,\n\t\t\t\tend: segEnd,\n\t\t\t\tisStart: isStart,\n\t\t\t\tisEnd: isEnd,\n\t\t\t\tmsLength: segEnd - segStart\n\t\t\t});\n\t\t}\n\t}\n\treturn segs.sort(segCmp);\n}\n\n\n// event rendering calculation utilities\nfunction stackSegs(segs) {\n\tvar levels = [],\n\t\ti, len = segs.length, seg,\n\t\tj, collide, k;\n\tfor (i=0; i=0; i--) {\n\t\tres = obj[parts[i].toLowerCase()];\n\t\tif (res !== undefined) {\n\t\t\treturn res;\n\t\t}\n\t}\n\treturn obj[''];\n}\n\n\nfunction htmlEscape(s) {\n\treturn s.replace(/&/g, '&')\n\t\t.replace(//g, '>')\n\t\t.replace(/'/g, ''')\n\t\t.replace(/\"/g, '"')\n\t\t.replace(/\\n/g, '
');\n}\n\n\nfunction cssKey(_element) {\n\treturn _element.id + '/' + _element.className + '/' + _element.style.cssText.replace(/(^|;)\\s*(top|left|width|height)\\s*:[^;]*/ig, '');\n}\n\n\nfunction disableTextSelection(element) {\n\telement\n\t\t.attr('unselectable', 'on')\n\t\t.css('MozUserSelect', 'none')\n\t\t.bind('selectstart.ui', function() { return false; });\n}\n\n\n/*\nfunction enableTextSelection(element) {\n\telement\n\t\t.attr('unselectable', 'off')\n\t\t.css('MozUserSelect', '')\n\t\t.unbind('selectstart.ui');\n}\n*/\n\n\nfunction markFirstLast(e) {\n\te.children()\n\t\t.removeClass('fc-first fc-last')\n\t\t.filter(':first-child')\n\t\t\t.addClass('fc-first')\n\t\t.end()\n\t\t.filter(':last-child')\n\t\t\t.addClass('fc-last');\n}\n\n\nfunction setDayID(cell, date) {\n\tcell.each(function(i, _cell) {\n\t\t_cell.className = _cell.className.replace(/^fc-\\w*/, 'fc-' + dayIDs[date.getDay()]);\n\t\t// TODO: make a way that doesn't rely on order of classes\n\t});\n}\n\n\nfunction getSkinCss(event, opt) {\n\tvar source = event.source || {};\n\tvar eventColor = event.color;\n\tvar sourceColor = source.color;\n\tvar optionColor = opt('eventColor');\n\tvar backgroundColor =\n\t\tevent.backgroundColor ||\n\t\teventColor ||\n\t\tsource.backgroundColor ||\n\t\tsourceColor ||\n\t\topt('eventBackgroundColor') ||\n\t\toptionColor;\n\tvar borderColor =\n\t\tevent.borderColor ||\n\t\teventColor ||\n\t\tsource.borderColor ||\n\t\tsourceColor ||\n\t\topt('eventBorderColor') ||\n\t\toptionColor;\n\tvar textColor =\n\t\tevent.textColor ||\n\t\tsource.textColor ||\n\t\topt('eventTextColor');\n\tvar statements = [];\n\tif (backgroundColor) {\n\t\tstatements.push('background-color:' + backgroundColor);\n\t}\n\tif (borderColor) {\n\t\tstatements.push('border-color:' + borderColor);\n\t}\n\tif (textColor) {\n\t\tstatements.push('color:' + textColor);\n\t}\n\treturn statements.join(';');\n}\n\n\nfunction applyAll(functions, thisObj, args) {\n\tif ($.isFunction(functions)) {\n\t\tfunctions = [ functions ];\n\t}\n\tif (functions) {\n\t\tvar i;\n\t\tvar ret;\n\t\tfor (i=0; i\" +\n\t\t\t\"
\";\n\t\ttable = $(s).appendTo(element);\n\n\t\thead = table.find('thead');\n\t\theadCells = head.find('th');\n\t\tbody = table.find('tbody');\n\t\tbodyRows = body.find('tr');\n\t\tbodyCells = body.find('td');\n\t\tbodyFirstCells = bodyCells.filter(':first-child');\n\t\tbodyCellTopInners = bodyRows.eq(0).find('div.fc-day-content div');\n\n\t\tmarkFirstLast(head.add(head.find('tr'))); // marks first+last tr/th's\n\t\tmarkFirstLast(bodyRows); // marks first+last td's\n\t\tbodyRows.eq(0).addClass('fc-first'); // fc-last is done in updateCells\n\n\t\tdayBind(bodyCells);\n\n\t\tdaySegmentContainer =\n\t\t\t$(\"
\")\n\t\t\t\t.appendTo(element);\n\t}\n\n\tfunction updateCells(firstTime) {\n\t\tvar dowDirty = firstTime || rowCnt == 1; // could the cells' day-of-weeks need updating?\n\t\tvar month = t.start.getMonth();\n\t\tvar today = clearTime(new Date());\n\t\tvar cell;\n\t\tvar date;\n\t\tvar row;\n\n\t\tif (dowDirty) {\n\t\t\theadCells.each(function(i, _cell) {\n\t\t\t\tcell = $(_cell);\n\t\t\t\tdate = indexDate(i);\n\t\t\t\tcell.html(formatDate(date, colFormat));\n\t\t\t\tsetDayID(cell, date);\n\t\t\t});\n\t\t}\n\n\t\tbodyCells.each(function(i, _cell) {\n\t\t\tcell = $(_cell);\n\t\t\tdate = indexDate(i);\n\t\t\tif (date.getMonth() == month) {\n\t\t\t\tcell.removeClass('fc-other-month');\n\t\t\t}else{\n\t\t\t\tcell.addClass('fc-other-month');\n\t\t\t}\n\t\t\tif (+date == +today) {\n\t\t\t\tcell.addClass(tm + '-state-highlight fc-today');\n\t\t\t}else{\n\t\t\t\tcell.removeClass(tm + '-state-highlight fc-today');\n\t\t\t}\n\t\t\tcell.find('div.fc-day-number').text(date.getDate());\n\t\t\tif (dowDirty) {\n\t\t\t\tsetDayID(cell, date);\n\t\t\t}\n\t\t});\n\n\t\tbodyRows.each(function(i, _row) {\n\t\t\trow = $(_row);\n\t\t\tif (i < rowCnt) {\n\t\t\t\trow.show();\n\t\t\t\tif (i == rowCnt-1) {\n\t\t\t\t\trow.addClass('fc-last');\n\t\t\t\t}else{\n\t\t\t\t\trow.removeClass('fc-last');\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\trow.hide();\n\t\t\t}\n\t\t});\n\t}\n\n\tfunction setHeight(height) {\n\t\tviewHeight = height;\n\n\t\tvar bodyHeight = viewHeight - head.height();\n\t\tvar rowHeight;\n\t\tvar rowHeightLast;\n\t\tvar cell;\n\n\t\tif (opt('weekMode') == 'variable') {\n\t\t\trowHeight = rowHeightLast = Math.floor(bodyHeight / (rowCnt==1 ? 2 : 6));\n\t\t}else{\n\t\t\trowHeight = Math.floor(bodyHeight / rowCnt);\n\t\t\trowHeightLast = bodyHeight - rowHeight * (rowCnt-1);\n\t\t}\n\n\t\tbodyFirstCells.each(function(i, _cell) {\n\t\t\tif (i < rowCnt) {\n\t\t\t\tcell = $(_cell);\n\t\t\t\tsetMinHeight(\n\t\t\t\t\tcell.find('> div'),\n\t\t\t\t\t(i==rowCnt-1 ? rowHeightLast : rowHeight) - vsides(cell)\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t}\n\n\tfunction setWidth(width) {\n\t\tviewWidth = width;\n\t\tcolContentPositions.clear();\n\t\tcolWidth = Math.floor(viewWidth / colCnt);\n\t\tsetOuterWidth(headCells.slice(0, -1), colWidth);\n\t}\n\n\t/* Day clicking and binding\n\t-----------------------------------------------------------*/\n\n\n\tfunction dayBind(days) {\n\t\tdays.click(dayClick)\n\t\t\t.mousedown(daySelectionMousedown);\n\t}\n\n\n\tfunction dayClick(ev) {\n\t\tif (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick\n\t\t\tvar index = parseInt(this.className.match(/fc\\-day(\\d+)/)[1]); // TODO: maybe use .data\n\t\t\tvar date = indexDate(index);\n\t\t\ttrigger('dayClick', this, date, true, ev);\n\t\t}\n\t}\n\n\n\n\t/* Semi-transparent Overlay Helpers\n\t------------------------------------------------------*/\n\n\n\tfunction renderDayOverlay(overlayStart, overlayEnd, refreshCoordinateGrid) { // overlayEnd is exclusive\n\t\tif (refreshCoordinateGrid) {\n\t\t\tcoordinateGrid.build();\n\t\t}\n\t\tvar rowStart = cloneDate(t.visStart);\n\t\tvar rowEnd = addDays(cloneDate(rowStart), colCnt);\n\t\tfor (var i=0; i\" +\n \"\" +\n \"\" +\n \" \";\n\n for (i = 0; i < colCnt; i++) {\n s +=\n \"\"; // fc- needed for setDayID\n }\n\n s +=\n \" \" +\n \"\" +\n \"\" +\n \"\" +\n \"\" +\n \" \";\n\n for (i = 0; i < colCnt; i++) {\n s +=\n \"\" + // fc- needed for setDayID\n \"
\" +\n \"
\" +\n \"
 
\" +\n \"
\" +\n \"
\" +\n \"\";\n }\n\n s +=\n \" \" +\n \"\" +\n \"\" +\n \"\";\n dayTable = $(s).appendTo(element);\n dayHead = dayTable.find('thead');\n dayHeadCells = dayHead.find('th').slice(1, -1);\n dayBody = dayTable.find('tbody');\n dayBodyCells = dayBody.find('td').slice(0, -1);\n dayBodyCellInners = dayBodyCells.find('div.fc-day-content div');\n dayBodyFirstCell = dayBodyCells.eq(0);\n dayBodyFirstCellStretcher = dayBodyFirstCell.find('> div');\n\n markFirstLast(dayHead.add(dayHead.find('tr')));\n markFirstLast(dayBody.add(dayBody.find('tr')));\n\n axisFirstCells = dayHead.find('th:first');\n gutterCells = dayTable.find('.fc-agenda-gutter');\n\n slotLayer =\n $(\"
\")\n .appendTo(element);\n\n if (opt('allDaySlot')) {\n daySegmentContainer =\n $(\"
\")\n .appendTo(slotLayer);\n\n s =\n \"\" +\n \"\" +\n \"\" +\n \"\" +\n \"\" +\n \"\" +\n \"
\" + opt('allDayText') + \"\" +\n \"
\" +\n \"
 
\";\n allDayTable = $(s).appendTo(slotLayer);\n allDayRow = allDayTable.find('tr');\n\n dayBind(allDayRow.find('td'));\n\n axisFirstCells = axisFirstCells.add(allDayTable.find('th:first'));\n gutterCells = gutterCells.add(allDayTable.find('th.fc-agenda-gutter'));\n\n slotLayer.append(\n \"
\" +\n \"
\" +\n \"
\"\n );\n } else {\n daySegmentContainer = $([]); // in jQuery 1.4, we can just do $()\n }\n\n slotScroller =\n $(\"
\")\n .appendTo(slotLayer);\n\n slotContent =\n $(\"
\")\n .appendTo(slotScroller);\n\n slotSegmentContainer =\n $(\"
\")\n .appendTo(slotContent);\n\n s =\n \"\" +\n \"\";\n d = zeroDate();\n maxd = addMinutes(cloneDate(d), maxMinute);\n addMinutes(d, minMinute);\n slotCnt = 0;\n\n for (i = 0; d < maxd; i++) {\n minutes = d.getMinutes();\n s +=\n \"\" +\n \"\" +\n \"\" +\n \"\";\n\n addMinutes(d, opt('slotMinutes'));\n slotCnt++;\n }\n\n s +=\n \"\" +\n \"
\" +\n ((!slotNormal || !minutes) ? formatDate(d, opt('axisFormat')) : ' ') +\n \"\" +\n \"
 
\" +\n \"
\";\n\n buildFixedTimeColumn(maxd, headerClass, slotNormal, slotContent);\n\n slotTable = $(s).appendTo(slotContent);\n slotTableFirstInner = slotTable.find('div:first');\n\n slotBind(slotTable.find('td'));\n\n axisFirstCells = axisFirstCells.add(slotTable.find('th:first'));\n }\n\n // bridallive custom\n function buildFixedTimeColumn(maxd, headerClass, slotNormal, slotContent) {\n var d = zeroDate();\n var fixedSlotsHtml = \"
\" +\n \"\" +\n \"\";\n var minutes;\n\n for (var i = 0; d < maxd; i++) {\n minutes = d.getMinutes();\n\n fixedSlotsHtml += \"\" +\n \"\" +\n \"\";\n\n addMinutes(d, opt('slotMinutes'));\n }\n\n fixedSlotsHtml +=\n \"\" +\n \"\" +\n \"\";\n\n fixedSlots = $(fixedSlotsHtml).appendTo(slotContent);\n\n slotContent.parents('.fc-content').on('scroll', function (event) {\n fixedSlots.css('left', event.currentTarget.scrollLeft);\n })\n }\n\n function updateCells() {\n var i;\n var headCell;\n var bodyCell;\n var date;\n var today = clearTime(new Date());\n for (i = 0; i < colCnt; i++) {\n date = resourceDate(i);\n headCell = dayHeadCells.eq(i);\n headCell.html(resources[i].name);\n headCell.attr(\"id\", resources[i].id);\n bodyCell = dayBodyCells.eq(i);\n if (+date == +today) {\n bodyCell.addClass(tm + '-state-highlight fc-today');\n }else{\n bodyCell.removeClass(tm + '-state-highlight fc-today');\n }\n setDayID(headCell.add(bodyCell), date);\n }\n }\n\n function setHeight(height, dateChanged) {\n if (height === undefined) {\n height = viewHeight;\n }\n viewHeight = height;\n slotTopCache = {};\n\n var headHeight = dayBody.position().top;\n var allDayHeight = slotScroller.position().top; // including divider\n var bodyHeight = Math.min( // total body height, including borders\n height - headHeight, // when scrollbars\n slotTable.height() + allDayHeight + 1 // when no scrollbars. +1 for bottom border\n );\n\n dayBodyFirstCellStretcher\n .height(bodyHeight - vsides(dayBodyFirstCell));\n\n slotLayer.css('top', headHeight);\n\n slotScroller.height(bodyHeight - allDayHeight - 1);\n\n slotHeight = slotTableFirstInner.height() + 1; // +1 for border\n\n if (dateChanged) {\n resetScroll();\n }\n }\n\n function setWidth(width) {\n viewWidth = width;\n colContentPositions.clear();\n\n axisWidth = 0;\n setOuterWidth(\n axisFirstCells\n .width('')\n .each(function(i, _cell) {\n axisWidth = Math.max(axisWidth, $(_cell).outerWidth());\n }),\n axisWidth\n );\n\n var slotTableWidth = slotScroller[0].clientWidth; // needs to be done after axisWidth (for IE7)\n //slotTable.width(slotTableWidth);\n\n gutterWidth = slotScroller.width() - slotTableWidth;\n if (gutterWidth) {\n setOuterWidth(gutterCells, gutterWidth);\n gutterCells\n .show()\n .prev()\n .removeClass('fc-last');\n }else{\n gutterCells\n .hide()\n .prev()\n .addClass('fc-last');\n }\n\n colWidth = Math.floor((slotTableWidth - axisWidth) / colCnt);\n setOuterWidth(dayHeadCells.slice(0, -1), colWidth);\n }\n\n function resetScroll() {\n var d0 = zeroDate();\n var scrollDate = cloneDate(d0);\n scrollDate.setHours(opt('firstHour'));\n var top = timePosition(d0, scrollDate) + 1; // +1 for the border\n function scroll() {\n slotScroller.scrollTop(top);\n }\n scroll();\n setTimeout(scroll, 0); // overrides any previous scroll state made by the browser\n }\n\n\n function beforeHide() {\n savedScrollTop = slotScroller.scrollTop();\n }\n\n\n function afterShow() {\n slotScroller.scrollTop(savedScrollTop);\n }\n\n\n\n /* Slot/Day clicking and binding\n\t-----------------------------------------------------------------------*/\n\n\n function dayBind(cells) {\n cells.click(slotClick)\n .mousedown(daySelectionMousedown);\n }\n\n\n function slotBind(cells) {\n cells.click(slotClick)\n .mousedown(slotSelectionMousedown);\n }\n\n\n function slotClick(ev) {\n if (!opt('selectable')) { // if selectable, SelectionManager will worry about dayClick\n var tableWrapper = dayTable.parents('.fc-content');\n var tableScrollLeft = tableWrapper.scrollLeft();\n var tableOffsetLeft = tableWrapper.offset().left;\n var resourceColumnWidth = dayTable.find('thead > tr > th:eq(2)').outerWidth();\n\n // var clickedColumn = Math.min(colCnt-1, Math.floor((ev.pageX - dayTable.offset().left - axisWidth) / colWidth));\n // take into account horizontal scrolling\n var clickedColumn = Math.min(colCnt - 1, Math.floor((ev.pageX + tableScrollLeft - tableOffsetLeft - axisWidth) / resourceColumnWidth));\n\n var date = resourceDate(clickedColumn);\n var rowMatch = this.parentNode.className.match(/fc-slot(\\d+)/); // TODO: maybe use data\n\n if (rowMatch) {\n var mins = parseInt(rowMatch[1]) * opt('slotMinutes');\n var hours = Math.floor(mins / 60);\n date.setHours(hours);\n date.setMinutes(mins % 60 + minMinute);\n trigger('dayClick', dayBodyCells[clickedColumn], date, false, ev, resources[clickedColumn]);\n } else {\n trigger('dayClick', dayBodyCells[clickedColumn], date, true, ev, resources[clickedColumn]);\n }\n }\n }\n\n\n\n /* Semi-transparent Overlay Helpers\n\t-----------------------------------------------------*/\n\n\n function renderDayOverlay(startDate, endDate, refreshCoordinateGrid, resource) { // endDate is exclusive\n if (refreshCoordinateGrid) {\n coordinateGrid.build();\n }\n var startCol, endCol;\n startCol = resourceCol(resource);\n endCol = startCol + 1;\n dayBind(renderCellOverlay(0, startCol, 0, endCol-1));\n }\n\n\n function renderCellOverlay(row0, col0, row1, col1) { // only for all-day?\n var rect = coordinateGrid.rect(row0, col0, row1, col1, slotLayer);\n return renderOverlay(rect, slotLayer);\n }\n\n\n function renderSlotOverlay(overlayStart, overlayEnd) {\n var dayStart = cloneDate(t.visStart);\n var dayEnd = addDays(cloneDate(dayStart), 1);\n for (var i=0; i= 0) {\n addMinutes(d, minMinute + slotIndex * opt('slotMinutes'));\n }\n return d;\n }\n\n\n function resourceDate(col) {\n return cloneDate(t.visStart);\n }\n\n\n function cellIsAllDay(cell) {\n return opt('allDaySlot') && !cell.row;\n }\n\n\n function dayOfWeekCol(dayOfWeek) {\n return 0;\n }\n\n /* return the column index the resource is at. Return -1 if resource cannot be found. */\n function resourceCol(resource) {\n for (var i=0; i= addMinutes(cloneDate(day), maxMinute)) {\n return slotTable.height();\n }\n var slotMinutes = opt('slotMinutes'),\n minutes = time.getHours()*60 + time.getMinutes() - minMinute,\n slotI = Math.floor(minutes / slotMinutes),\n slotTop = slotTopCache[slotI];\n if (slotTop === undefined) {\n slotTop = slotTopCache[slotI] = slotTable.find('tr:eq(' + slotI + ') td div')[0].offsetTop; //.position().top; // need this optimization???\n }\n return Math.max(0, Math.round(\n slotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)\n ));\n }\n\n\n function allDayBounds() {\n return {\n left: axisWidth,\n right: viewWidth - gutterWidth\n }\n }\n\n\n function getAllDayRow(index) {\n return allDayRow;\n }\n\n\n function defaultEventEnd(event) {\n var start = cloneDate(event.start);\n if (event.allDay) {\n return start;\n }\n return addMinutes(start, opt('defaultEventMinutes'));\n }\n\n\n\n /* Selection\n\t---------------------------------------------------------------------------------*/\n\n\n function defaultSelectionEnd(startDate, allDay) {\n if (allDay) {\n return cloneDate(startDate);\n }\n return addMinutes(cloneDate(startDate), opt('slotMinutes'));\n }\n\n\n function renderSelection(startDate, endDate, allDay, resource) { // only for all-day\n if (allDay) {\n if (opt('allDaySlot')) {\n renderDayOverlay(startDate, addDays(cloneDate(endDate), 1), true, resource);\n }\n }else{\n renderSlotSelection(startDate, endDate, resource);\n }\n }\n\n\n function renderSlotSelection(startDate, endDate, resource) {\n var helperOption = opt('selectHelper');\n coordinateGrid.build();\n if (helperOption) {\n var col = resourceCol(resource);\n if (col >= 0 && col < colCnt) { // only works when times are on same day\n var rect = coordinateGrid.rect(0, col, 0, col, slotContent); // only for horizontal coords\n var top = timePosition(startDate, startDate);\n var bottom = timePosition(startDate, endDate);\n if (bottom > top) { // protect against selections that are entirely before or after visible range\n rect.top = top;\n rect.height = bottom - top;\n rect.left += 2;\n rect.width -= 5;\n if ($.isFunction(helperOption)) {\n var helperRes = helperOption(startDate, endDate);\n if (helperRes) {\n rect.position = 'absolute';\n rect.zIndex = 8;\n selectionHelper = $(helperRes)\n .css(rect)\n .appendTo(slotContent);\n }\n }else{\n rect.isStart = true; // conside rect a \"seg\" now\n rect.isEnd = true; //\n selectionHelper = $(slotSegHtml(\n {\n title: '',\n start: startDate,\n end: endDate,\n className: ['fc-select-helper'],\n editable: false\n },\n rect\n ));\n selectionHelper.css('opacity', opt('dragOpacity'));\n }\n if (selectionHelper) {\n slotBind(selectionHelper);\n slotContent.append(selectionHelper);\n setOuterWidth(selectionHelper, rect.width, true); // needs to be after appended\n setOuterHeight(selectionHelper, rect.height, true);\n }\n }\n }\n }else{\n renderSlotOverlay(startDate, endDate);\n }\n }\n\n\n function clearSelection() {\n clearOverlays();\n if (selectionHelper) {\n selectionHelper.remove();\n selectionHelper = null;\n }\n }\n\n function daySelectionMousedown(ev) {\n var cellDate = t.cellDate;\n var cellIsAllDay = t.cellIsAllDay;\n var hoverListener = t.getHoverListener();\n if (ev.which == 1 && opt('selectable')) { // which==1 means left mouse button\n unselect(ev);\n var _mousedownElement = this;\n var dates;\n var resource;\n hoverListener.start(function(cell, origCell) { // TODO: maybe put cellDate/cellIsAllDay info in cell\n clearSelection();\n if (cell && cellIsAllDay(cell)) {\n resource = resources[cell.col];\n dates = [ cellDate(origCell), cellDate(cell) ].sort(cmp);\n renderSelection(dates[0], dates[1], true, resource);\n }else{\n dates = null;\n }\n }, ev);\n $(document).one('mouseup', function(ev) {\n hoverListener.stop();\n if (dates && resource) {\n reportSelection(dates[0], dates[1], true, ev, resource.id);\n }\n });\n }\n }\n\n\n function slotSelectionMousedown(ev) {\n if (ev.which == 1 && opt('selectable')) { // ev.which==1 means left mouse button\n unselect(ev);\n var dates;\n var resource;\n hoverListener.start(function(cell, origCell) {\n clearSelection();\n if (cell && cell.col == origCell.col && !cellIsAllDay(cell)) {\n resource = resources[cell.col];\n var d1 = cellDate(origCell);\n var d2 = cellDate(cell);\n dates = [\n d1,\n addMinutes(cloneDate(d1), opt('slotMinutes')),\n d2,\n addMinutes(cloneDate(d2), opt('slotMinutes'))\n ].sort(cmp);\n renderSlotSelection(dates[0], dates[3], resource);\n }else{\n dates = null;\n }\n }, ev);\n $(document).one('mouseup', function(ev) {\n hoverListener.stop();\n if (dates && resource) {\n reportSelection(dates[0], dates[3], false, ev, resource.id);\n }\n });\n }\n }\n\n\n function reportDayClick(date, allDay, ev) {\n trigger('dayClick', dayBodyCells[dayOfWeekCol(date.getDay())], date, allDay, ev);\n }\n\n\n\n /* External Dragging\n\t--------------------------------------------------------------------------------*/\n\n\n function dragStart(_dragElement, ev, ui) {\n hoverListener.start(function(cell) {\n clearOverlays();\n if (cell) {\n if (cellIsAllDay(cell)) {\n renderCellOverlay(cell.row, cell.col, cell.row, cell.col);\n }else{\n var d1 = cellDate(cell);\n var d2 = addMinutes(cloneDate(d1), opt('defaultEventMinutes'));\n renderSlotOverlay(d1, d2);\n }\n }\n }, ev);\n }\n\n\n function dragStop(_dragElement, ev, ui) {\n var cell = hoverListener.stop();\n clearOverlays();\n if (cell) {\n trigger('drop', _dragElement, cellDate(cell), cellIsAllDay(cell), ev, ui);\n }\n }\n\n}\n\nfunction ResourceEventRenderer() {\n var t = this;\n\n\n // exports\n t.renderEvents = renderEvents;\n t.compileDaySegs = compileDaySegs; // for DayEventRenderer\n t.clearEvents = clearEvents;\n t.slotSegHtml = slotSegHtml;\n t.bindDaySeg = bindDaySeg;\n\n\n // imports\n DayEventRenderer.call(t);\n var opt = t.opt;\n var trigger = t.trigger;\n //var setOverflowHidden = t.setOverflowHidden;\n var isEventDraggable = t.isEventDraggable;\n var isEventResizable = t.isEventResizable;\n var eventEnd = t.eventEnd;\n var reportEvents = t.reportEvents;\n var reportEventClear = t.reportEventClear;\n var eventElementHandlers = t.eventElementHandlers;\n var setHeight = t.setHeight;\n var getDaySegmentContainer = t.getDaySegmentContainer;\n var getSlotSegmentContainer = t.getSlotSegmentContainer;\n var getHoverListener = t.getHoverListener;\n var getMaxMinute = t.getMaxMinute;\n var getMinMinute = t.getMinMinute;\n var timePosition = t.timePosition;\n var colContentLeft = t.colContentLeft;\n var colContentRight = t.colContentRight;\n var renderDaySegs = t.renderDaySegs;\n var resizableDayEvent = t.resizableDayEvent; // TODO: streamline binding architecture\n var getColCnt = t.getColCnt;\n var getColWidth = t.getColWidth;\n var getSlotHeight = t.getSlotHeight;\n var getBodyContent = t.getBodyContent;\n var reportEventElement = t.reportEventElement;\n var showEvents = t.showEvents;\n var hideEvents = t.hideEvents;\n var eventDrop = t.eventDrop;\n var eventResize = t.eventResize;\n var renderDayOverlay = t.renderDayOverlay;\n var clearOverlays = t.clearOverlays;\n var calendar = t.calendar;\n var formatDate = calendar.formatDate;\n var formatDates = calendar.formatDates;\n var resourceCol = t.resourceCol; // imported from ResourceView.js\n var resources = t.resources; // imported from ResourceView.js\n\n\n\n /* Rendering\n\t----------------------------------------------------------------------------*/\n\n\n function renderEvents(events, modifiedEventId) {\n reportEvents(events);\n var i, len=events.length,\n dayEvents=[],\n slotEvents=[];\n for (i=0; i\" +\n \"
\" +\n \"
\" +\n \"
\" +\n htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\" +\n htmlEscape(event.title) +\n \"
\" +\n \"
\" +\n \"
\" +\n \"
\"; // close inner\n if (seg.isEnd && isEventResizable(event)) {\n html +=\n \"
=
\";\n }\n html +=\n \"\";\n return html;\n }\n\n\n function bindDaySeg(event, eventElement, seg) {\n if (isEventDraggable(event)) {\n draggableDayEvent(event, eventElement, seg.isStart);\n }\n if (seg.isEnd && isEventResizable(event)) {\n resizableDayEvent(event, eventElement, seg);\n }\n eventElementHandlers(event, eventElement);\n // needs to be after, because resizableDayEvent might stopImmediatePropagation on click\n }\n\n\n function bindSlotSeg(event, eventElement, seg) {\n var timeElement = eventElement.find('div.fc-event-time');\n if (isEventDraggable(event)) {\n draggableSlotEvent(event, eventElement, timeElement);\n }\n if (seg.isEnd && isEventResizable(event)) {\n resizableSlotEvent(event, eventElement, timeElement);\n }\n eventElementHandlers(event, eventElement);\n }\n\n\n\n /* Dragging\n\t-----------------------------------------------------------------------------------*/\n\n\n // when event starts out FULL-DAY\n\n function draggableDayEvent(event, eventElement, isStart) {\n var origWidth;\n var revert;\n var allDay=true;\n var dayDelta;\n var dis = opt('isRTL') ? -1 : 1;\n var hoverListener = getHoverListener();\n var colWidth = getColWidth();\n var slotHeight = getSlotHeight();\n var minMinute = getMinMinute();\n eventElement.draggable({\n zIndex: 9,\n opacity: opt('dragOpacity', 'month'), // use whatever the month view was using\n revertDuration: opt('dragRevertDuration'),\n start: function(ev, ui) {\n trigger('eventDragStart', eventElement, event, ev, ui);\n hideEvents(event, eventElement);\n origWidth = eventElement.width();\n hoverListener.start(function(cell, origCell, rowDelta, colDelta) {\n clearOverlays();\n if (cell) {\n //setOverflowHidden(true);\n revert = false;\n dayDelta = colDelta * dis;\n if (!cell.row) {\n // on full-days\n renderDayOverlay(\n addDays(cloneDate(event.start), dayDelta),\n addDays(exclEndDay(event), dayDelta),\n true,\n resources[cell.col]\n );\n resetElement();\n }else{\n // mouse is over bottom slots\n if (isStart) {\n if (allDay) {\n // convert event to temporary slot-event\n eventElement.width(colWidth - 10); // don't use entire width\n setOuterHeight(\n eventElement,\n slotHeight * Math.round(\n (event.end ? ((event.end - event.start) / MINUTE_MS) : opt('defaultEventMinutes'))\n / opt('slotMinutes')\n )\n );\n eventElement.draggable('option', 'grid', [colWidth, 1]);\n allDay = false;\n }\n }else{\n revert = true;\n }\n }\n revert = revert || (allDay && !dayDelta);\n }else{\n resetElement();\n //setOverflowHidden(false);\n revert = true;\n }\n eventElement.draggable('option', 'revert', revert);\n }, ev, 'drag');\n },\n stop: function(ev, ui) {\n var cell = hoverListener.stop();\n clearOverlays();\n event.resourceId = resources[cell.col].id;\n trigger('eventDragStop', eventElement, event, ev, ui);\n if (revert) {\n // hasn't moved or is out of bounds (draggable has already reverted)\n resetElement();\n eventElement.css('filter', ''); // clear IE opacity side-effects\n showEvents(event, eventElement);\n }else{\n // changed!\n var minuteDelta = 0;\n if (!allDay) {\n minuteDelta = Math.round((eventElement.offset().top - getBodyContent().offset().top) / slotHeight)\n * opt('slotMinutes')\n + minMinute\n - (event.start.getHours() * 60 + event.start.getMinutes());\n }\n\n dayDelta = 0;\n eventDrop(this, event, dayDelta, minuteDelta, allDay, ev, ui);\n }\n //setOverflowHidden(false);\n }\n });\n function resetElement() {\n if (!allDay) {\n eventElement\n .width(origWidth)\n .height('')\n .draggable('option', 'grid', null);\n allDay = true;\n }\n }\n }\n\n\n // when event starts out IN TIMESLOTS\n\n function draggableSlotEvent(event, eventElement, timeElement) {\n var origPosition;\n var allDay=false;\n var dayDelta;\n var minuteDelta;\n var prevMinuteDelta;\n var dis = opt('isRTL') ? -1 : 1;\n var hoverListener = getHoverListener();\n var colCnt = getColCnt();\n var colWidth = getColWidth();\n var slotHeight = getSlotHeight();\n eventElement.draggable({\n zIndex: 9,\n scroll: false,\n grid: [colWidth, slotHeight],\n axis: colCnt==1 ? 'y' : false,\n opacity: opt('dragOpacity'),\n revertDuration: opt('dragRevertDuration'),\n start: function(ev, ui) {\n trigger('eventDragStart', eventElement, event, ev, ui);\n hideEvents(event, eventElement);\n origPosition = eventElement.position();\n minuteDelta = prevMinuteDelta = 0;\n hoverListener.start(function(cell, origCell, rowDelta, colDelta) {\n eventElement.draggable('option', 'revert', !cell);\n clearOverlays();\n if (cell) {\n dayDelta = colDelta * dis;\n if (opt('allDaySlot') && !cell.row) {\n // over full days\n if (!allDay) {\n // convert to temporary all-day event\n allDay = true;\n timeElement.hide();\n eventElement.draggable('option', 'grid', null);\n }\n renderDayOverlay(\n addDays(cloneDate(event.start), dayDelta),\n addDays(exclEndDay(event), dayDelta),\n true,\n resources[cell.col]\n );\n }else{\n // on slots\n resetElement();\n }\n }\n }, ev, 'drag');\n },\n drag: function(ev, ui) {\n minuteDelta = Math.round((ui.position.top - origPosition.top) / slotHeight) * opt('slotMinutes');\n if (minuteDelta != prevMinuteDelta) {\n if (!allDay) {\n updateTimeText(minuteDelta);\n }\n prevMinuteDelta = minuteDelta;\n }\n },\n stop: function(ev, ui) {\n var cell = hoverListener.stop();\n clearOverlays();\n trigger('eventDragStop', eventElement, event, ev, ui);\n if (cell && (dayDelta || minuteDelta || allDay)) {\n // changed!\n event.oldResourceId = event.resourceId;\n event.resourceId = resources[cell.col].id;\n dayDelta = 0;\n eventDrop(this, event, dayDelta, allDay ? 0 : minuteDelta, allDay, ev, ui);\n }else{\n // either no change or out-of-bounds (draggable has already reverted)\n resetElement();\n eventElement.css('filter', ''); // clear IE opacity side-effects\n eventElement.css(origPosition); // sometimes fast drags make event revert to wrong position\n updateTimeText(0);\n showEvents(event, eventElement);\n }\n }\n });\n function updateTimeText(minuteDelta) {\n var newStart = addMinutes(cloneDate(event.start), minuteDelta);\n var newEnd;\n if (event.end) {\n newEnd = addMinutes(cloneDate(event.end), minuteDelta);\n }\n timeElement.text(formatDates(newStart, newEnd, opt('timeFormat')));\n }\n function resetElement() {\n // convert back to original slot-event\n if (allDay) {\n timeElement.css('display', ''); // show() was causing display=inline\n eventElement.draggable('option', 'grid', [colWidth, slotHeight]);\n allDay = false;\n }\n }\n }\n\n\n\n /* Resizing\n\t--------------------------------------------------------------------------------------*/\n\n\n function resizableSlotEvent(event, eventElement, timeElement) {\n var slotDelta, prevSlotDelta;\n var slotHeight = getSlotHeight();\n eventElement.resizable({\n handles: {\n s: 'div.ui-resizable-s'\n },\n grid: slotHeight,\n start: function(ev, ui) {\n slotDelta = prevSlotDelta = 0;\n hideEvents(event, eventElement);\n eventElement.css('z-index', 9);\n trigger('eventResizeStart', this, event, ev, ui);\n },\n resize: function(ev, ui) {\n // don't rely on ui.size.height, doesn't take grid into account\n slotDelta = Math.round((Math.max(slotHeight, eventElement.height()) - ui.originalSize.height) / slotHeight);\n if (slotDelta != prevSlotDelta) {\n timeElement.text(\n formatDates(\n event.start,\n (!slotDelta && !event.end) ? null : // no change, so don't display time range\n addMinutes(eventEnd(event), opt('slotMinutes')*slotDelta),\n opt('timeFormat')\n )\n );\n prevSlotDelta = slotDelta;\n }\n },\n stop: function(ev, ui) {\n trigger('eventResizeStop', this, event, ev, ui);\n if (slotDelta) {\n eventResize(this, event, 0, opt('slotMinutes')*slotDelta, ev, ui);\n }else{\n eventElement.css('z-index', 8);\n showEvents(event, eventElement);\n // BUG: if event was really short, need to put title back in span\n }\n }\n });\n }\n\n\n}\nfcViews.agendaWeek = AgendaWeekView;\n\nfunction AgendaWeekView(element, calendar) {\n\tvar t = this;\n\n\n\t// exports\n\tt.render = render;\n\n\n\t// imports\n\tAgendaView.call(t, element, calendar, 'agendaWeek');\n\tvar opt = t.opt;\n\tvar renderAgenda = t.renderAgenda;\n\tvar formatDates = calendar.formatDates;\n\n\n\n\tfunction render(date, delta) {\n\t\tif (delta) {\n\t\t\taddDays(date, delta * 7);\n\t\t}\n\t\tvar start = addDays(cloneDate(date), -((date.getDay() - opt('firstDay') + 7) % 7));\n\t\tvar end = addDays(cloneDate(start), 7);\n\t\tvar visStart = cloneDate(start);\n\t\tvar visEnd = cloneDate(end);\n\t\tvar weekends = opt('weekends');\n\t\tif (!weekends) {\n\t\t\tskipWeekend(visStart);\n\t\t\tskipWeekend(visEnd, -1, true);\n\t\t}\n\t\tt.title = formatDates(\n\t\t\tvisStart,\n\t\t\taddDays(cloneDate(visEnd), -1),\n\t\t\topt('titleFormat')\n\t\t);\n\t\tt.start = start;\n\t\tt.end = end;\n\t\tt.visStart = visStart;\n\t\tt.visEnd = visEnd;\n\t\trenderAgenda(weekends ? 7 : 5);\n\t}\n\n\n}\n\nfcViews.agendaDay = AgendaDayView;\n\nfunction AgendaDayView(element, calendar) {\n\tvar t = this;\n\n\n\t// exports\n\tt.render = render;\n\n\n\t// imports\n\tAgendaView.call(t, element, calendar, 'agendaDay');\n\tvar opt = t.opt;\n\tvar renderAgenda = t.renderAgenda;\n\tvar formatDate = calendar.formatDate;\n\n\n\n\tfunction render(date, delta) {\n\t\tif (delta) {\n\t\t\taddDays(date, delta);\n\t\t\tif (!opt('weekends')) {\n\t\t\t\tskipWeekend(date, delta < 0 ? -1 : 1);\n\t\t\t}\n\t\t}\n\t\tvar start = cloneDate(date, true);\n\t\tvar end = addDays(cloneDate(start), 1);\n\t\tt.title = formatDate(date, opt('titleFormat'));\n\t\tt.start = t.visStart = start;\n\t\tt.end = t.visEnd = end;\n\t\trenderAgenda(1);\n\t}\n\n\n}\n\nsetDefaults({\n\tallDaySlot: true,\n\tallDayText: 'all-day',\n\tfirstHour: 6,\n\tslotMinutes: 30,\n\tdefaultEventMinutes: 120,\n\taxisFormat: 'h(:mm)tt',\n\ttimeFormat: {\n\t\tagenda: 'h:mm{ - h:mm}'\n\t},\n\tdragOpacity: {\n\t\tagenda: .5\n\t},\n\tminTime: 0,\n\tmaxTime: 24\n});\n\n\n// TODO: make it work in quirks mode (event corners, all-day height)\n// TODO: test liquid width, especially in IE6\n\n\nfunction AgendaView(element, calendar, viewName) {\n\tvar t = this;\n\n\n\t// exports\n\tt.renderAgenda = renderAgenda;\n\tt.setWidth = setWidth;\n\tt.setHeight = setHeight;\n\tt.beforeHide = beforeHide;\n\tt.afterShow = afterShow;\n\tt.defaultEventEnd = defaultEventEnd;\n\tt.timePosition = timePosition;\n\tt.dayOfWeekCol = dayOfWeekCol;\n\tt.dateCell = dateCell;\n\tt.cellDate = cellDate;\n\tt.cellIsAllDay = cellIsAllDay;\n\tt.allDayRow = getAllDayRow;\n\tt.allDayBounds = allDayBounds;\n\tt.getHoverListener = function() { return hoverListener };\n\tt.colContentLeft = colContentLeft;\n\tt.colContentRight = colContentRight;\n\tt.getDaySegmentContainer = function() { return daySegmentContainer };\n\tt.getSlotSegmentContainer = function() { return slotSegmentContainer };\n\tt.getMinMinute = function() { return minMinute };\n\tt.getMaxMinute = function() { return maxMinute };\n\tt.getBodyContent = function() { return slotContent }; // !!??\n\tt.getRowCnt = function() { return 1 };\n\tt.getColCnt = function() { return colCnt };\n\tt.getColWidth = function() { return colWidth };\n\tt.getSlotHeight = function() { return slotHeight };\n\tt.defaultSelectionEnd = defaultSelectionEnd;\n\tt.renderDayOverlay = renderDayOverlay;\n\tt.renderSelection = renderSelection;\n\tt.clearSelection = clearSelection;\n\tt.reportDayClick = reportDayClick; // selection mousedown hack\n\tt.dragStart = dragStart;\n\tt.dragStop = dragStop;\n\n\n\t// imports\n\tView.call(t, element, calendar, viewName);\n\tOverlayManager.call(t);\n\tSelectionManager.call(t);\n\tAgendaEventRenderer.call(t);\n\tvar opt = t.opt;\n\tvar trigger = t.trigger;\n\tvar clearEvents = t.clearEvents;\n\tvar renderOverlay = t.renderOverlay;\n\tvar clearOverlays = t.clearOverlays;\n\tvar reportSelection = t.reportSelection;\n\tvar unselect = t.unselect;\n\tvar daySelectionMousedown = t.daySelectionMousedown;\n\tvar slotSegHtml = t.slotSegHtml;\n\tvar formatDate = calendar.formatDate;\n\n\n\t// locals\n\n\tvar dayTable;\n\tvar dayHead;\n\tvar dayHeadCells;\n\tvar dayBody;\n\tvar dayBodyCells;\n\tvar dayBodyCellInners;\n\tvar dayBodyFirstCell;\n\tvar dayBodyFirstCellStretcher;\n\tvar slotLayer;\n\tvar daySegmentContainer;\n\tvar allDayTable;\n\tvar allDayRow;\n\tvar slotScroller;\n\tvar slotContent;\n\tvar slotSegmentContainer;\n\tvar slotTable;\n\tvar slotTableFirstInner;\n\tvar axisFirstCells;\n\tvar gutterCells;\n\tvar selectionHelper;\n\n\tvar viewWidth;\n\tvar viewHeight;\n\tvar axisWidth;\n\tvar colWidth;\n\tvar gutterWidth;\n\tvar slotHeight; // TODO: what if slotHeight changes? (see issue 650)\n\tvar savedScrollTop;\n\n\tvar colCnt;\n\tvar slotCnt;\n\tvar coordinateGrid;\n\tvar hoverListener;\n\tvar colContentPositions;\n\tvar slotTopCache = {};\n\n\tvar tm;\n\tvar firstDay;\n\tvar nwe; // no weekends (int)\n\tvar rtl, dis, dit; // day index sign / translate\n\tvar minMinute, maxMinute;\n\tvar colFormat;\n\n\n\n\t/* Rendering\n\t-----------------------------------------------------------------------------*/\n\n\n\tdisableTextSelection(element.addClass('fc-agenda'));\n\n\n\tfunction renderAgenda(c) {\n\t\tcolCnt = c;\n\t\tupdateOptions();\n\t\tif (!dayTable) {\n\t\t\tbuildSkeleton();\n\t\t}else{\n\t\t\tclearEvents();\n\t\t}\n\t\tupdateCells();\n\t}\n\n\n\n\tfunction updateOptions() {\n\t\ttm = opt('theme') ? 'ui' : 'fc';\n\t\tnwe = opt('weekends') ? 0 : 1;\n\t\tfirstDay = opt('firstDay');\n\t\tif (rtl = opt('isRTL')) {\n\t\t\tdis = -1;\n\t\t\tdit = colCnt - 1;\n\t\t}else{\n\t\t\tdis = 1;\n\t\t\tdit = 0;\n\t\t}\n\t\tminMinute = parseTime(opt('minTime'));\n\t\tmaxMinute = parseTime(opt('maxTime'));\n\t\tcolFormat = opt('columnFormat');\n\t}\n\n\n\n\tfunction buildSkeleton() {\n\t\tvar headerClass = tm + \"-widget-header\";\n\t\tvar contentClass = tm + \"-widget-content\";\n\t\tvar s;\n\t\tvar i;\n\t\tvar d;\n\t\tvar maxd;\n\t\tvar minutes;\n\t\tvar slotNormal = opt('slotMinutes') % 15 == 0;\n\n\t\ts =\n\t\t\t\"
\" +\n ((!slotNormal || !minutes) ? formatDate(d, opt('axisFormat')) : ' ') +\n \"
\" +\n\t\t\t\"\" +\n\t\t\t\"\" +\n\t\t\t\"\";\n\n\t\tfor (i = 0; i < colCnt; i++) {\n\t\t\ts +=\n\t\t\t\t\"\" +\n\t\t\t\"\" +\n\t\t\t\"\" +\n\t\t\t\"\" +\n\t\t\t\"\" +\n\t\t\t\"\";\n\n\t\tfor (i = 0; i < colCnt; i++) {\n\t\t\ts +=\n\t\t\t\t\"\";\n\t\t}\n\n\t\ts +=\n\t\t\t\"\" +\n\t\t\t\"\" +\n\t\t\t\"\" +\n\t\t\t\"
 \"; // fc- needed for setDayID\n\t\t}\n\n\t\ts +=\n\t\t\t\" 
 \" + // fc- needed for setDayID\n\t\t\t\t\"
\" +\n\t\t\t\t\"
\" +\n\t\t\t\t\"
 
\" +\n\t\t\t\t\"
\" +\n\t\t\t\t\"
\" +\n\t\t\t\t\"
 
\";\n\n\t\tdayTable = $(s).appendTo(element);\n\t\tdayHead = dayTable.find('thead');\n\t\tdayHeadCells = dayHead.find('th').slice(1, -1);\n\t\tdayBody = dayTable.find('tbody');\n\t\tdayBodyCells = dayBody.find('td').slice(0, -1);\n\t\tdayBodyCellInners = dayBodyCells.find('div.fc-day-content div');\n\t\tdayBodyFirstCell = dayBodyCells.eq(0);\n\t\tdayBodyFirstCellStretcher = dayBodyFirstCell.find('> div');\n\n\t\tmarkFirstLast(dayHead.add(dayHead.find('tr')));\n\t\tmarkFirstLast(dayBody.add(dayBody.find('tr')));\n\n\t\taxisFirstCells = dayHead.find('th:first');\n\t\tgutterCells = dayTable.find('.fc-agenda-gutter');\n\n\t\tslotLayer =\n\t\t\t$(\"
\")\n\t\t\t\t.appendTo(element);\n\n\t\tif (opt('allDaySlot')) {\n\n\t\t\tdaySegmentContainer =\n\t\t\t\t$(\"
\")\n\t\t\t\t\t.appendTo(slotLayer);\n\n\t\t\ts =\n\t\t\t\t\"\" +\n\t\t\t\t\"\" +\n\t\t\t\t\"\" +\n\t\t\t\t\"\" +\n\t\t\t\t\"\" +\n\t\t\t\t\"\" +\n\t\t\t\t\"
\" + opt('allDayText') + \"\" +\n\t\t\t\t\"
\" +\n\t\t\t\t\"
 
\";\n\t\t\tallDayTable = $(s).appendTo(slotLayer);\n\t\t\tallDayRow = allDayTable.find('tr');\n\n\t\t\tdayBind(allDayRow.find('td'));\n\n\t\t\taxisFirstCells = axisFirstCells.add(allDayTable.find('th:first'));\n\t\t\tgutterCells = gutterCells.add(allDayTable.find('th.fc-agenda-gutter'));\n\n\t\t\tslotLayer.append(\n\t\t\t\t\"
\" +\n\t\t\t\t\"
\" +\n\t\t\t\t\"
\"\n\t\t\t);\n\t\t} else {\n\t\t\tdaySegmentContainer = $([]); // in jQuery 1.4, we can just do $()\n\t\t}\n\n\t\tslotScroller =\n\t\t\t$(\"
\")\n\t\t\t\t.appendTo(slotLayer);\n\n\t\tslotContent =\n\t\t\t$(\"
\")\n\t\t\t\t.appendTo(slotScroller);\n\n\t\tslotSegmentContainer =\n\t\t\t$(\"
\")\n\t\t\t\t.appendTo(slotContent);\n\n\t\ts =\n\t\t\t\"\" +\n\t\t\t\"\";\n\n\t\td = zeroDate();\n\t\tmaxd = addMinutes(cloneDate(d), maxMinute);\n\t\taddMinutes(d, minMinute);\n\t\tslotCnt = 0;\n\n\t\tfor (i = 0; d < maxd; i++) {\n\t\t\tminutes = d.getMinutes();\n\t\t\ts +=\n\t\t\t\t\"\" +\n\t\t\t\t\"\" +\n\t\t\t\t\"\" +\n\t\t\t\t\"\";\n\t\t\taddMinutes(d, opt('slotMinutes'));\n\t\t\tslotCnt++;\n\t\t}\n\n\t\ts +=\n\t\t\t\"\" +\n\t\t\t\"
\" +\n\t\t\t\t((!slotNormal || !minutes) ? formatDate(d, opt('axisFormat')) : ' ') +\n\t\t\t\t\"\" +\n\t\t\t\t\"
 
\" +\n\t\t\t\t\"
\";\n\n\t\tslotTable = $(s).appendTo(slotContent);\n\t\tslotTableFirstInner = slotTable.find('div:first');\n\n\t\tslotBind(slotTable.find('td'));\n\n\t\taxisFirstCells = axisFirstCells.add(slotTable.find('th:first'));\n\t}\n\n\n\n\tfunction updateCells() {\n\t\tvar i;\n\t\tvar headCell;\n\t\tvar bodyCell;\n\t\tvar date;\n\t\tvar today = clearTime(new Date());\n\t\tfor (i=0; i tr > th:eq(2)').outerWidth();\n\n // var clickedColumn = Math.min(colCnt-1, Math.floor((ev.pageX - dayTable.offset().left - axisWidth) / colWidth));\n // take into account horizontal scrolling\n var clickedColumn = Math.min(colCnt-1, Math.floor((ev.pageX + tableScrollLeft - tableOffsetLeft - axisWidth) / resourceColumnWidth));\n\n var date = colDate(clickedColumn);\n var rowMatch = this.parentNode.className.match(/fc-slot(\\d+)/); // TODO: maybe use data\n if (rowMatch) {\n var mins = parseInt(rowMatch[1]) * opt('slotMinutes');\n var hours = Math.floor(mins/60);\n date.setHours(hours);\n date.setMinutes(mins%60 + minMinute);\n trigger('dayClick', dayBodyCells[clickedColumn], date, false, ev);\n }else{\n trigger('dayClick', dayBodyCells[clickedColumn], date, true, ev);\n }\n }\n }\n\n\n\n /* Semi-transparent Overlay Helpers\n -----------------------------------------------------*/\n\n\n\tfunction renderDayOverlay(startDate, endDate, refreshCoordinateGrid) { // endDate is exclusive\n\t\tif (refreshCoordinateGrid) {\n\t\t\tcoordinateGrid.build();\n\t\t}\n\t\tvar visStart = cloneDate(t.visStart);\n\t\tvar startCol, endCol;\n\t\tif (rtl) {\n\t\t\tstartCol = dayDiff(endDate, visStart)*dis+dit+1;\n\t\t\tendCol = dayDiff(startDate, visStart)*dis+dit+1;\n\t\t}else{\n\t\t\tstartCol = dayDiff(startDate, visStart);\n\t\t\tendCol = dayDiff(endDate, visStart);\n\t\t}\n\t\tstartCol = Math.max(0, startCol);\n\t\tendCol = Math.min(colCnt, endCol);\n\t\tif (startCol < endCol) {\n\t\t\tdayBind(\n\t\t\t\trenderCellOverlay(0, startCol, 0, endCol-1)\n\t\t\t);\n\t\t}\n\t}\n\n\n\tfunction renderCellOverlay(row0, col0, row1, col1) { // only for all-day?\n\t\tvar rect = coordinateGrid.rect(row0, col0, row1, col1, slotLayer);\n\t\treturn renderOverlay(rect, slotLayer);\n\t}\n\n\n\tfunction renderSlotOverlay(overlayStart, overlayEnd) {\n\t\tvar dayStart = cloneDate(t.visStart);\n\t\tvar dayEnd = addDays(cloneDate(dayStart), 1);\n\t\tfor (var i=0; i= 0) {\n\t\t\taddMinutes(d, minMinute + slotIndex * opt('slotMinutes'));\n\t\t}\n\t\treturn d;\n\t}\n\n\n\tfunction colDate(col) { // returns dates with 00:00:00\n\t\treturn addDays(cloneDate(t.visStart), col*dis+dit);\n\t}\n\n\n\tfunction cellIsAllDay(cell) {\n\t\treturn opt('allDaySlot') && !cell.row;\n\t}\n\n\n\tfunction dayOfWeekCol(dayOfWeek) {\n\t\treturn ((dayOfWeek - Math.max(firstDay, nwe) + colCnt) % colCnt)*dis+dit;\n\t}\n\n\n\n\n\t// get the Y coordinate of the given time on the given day (both Date objects)\n\tfunction timePosition(day, time) { // both date objects. day holds 00:00 of current day\n\t\tday = cloneDate(day, true);\n\t\tif (time < addMinutes(cloneDate(day), minMinute)) {\n\t\t\treturn 0;\n\t\t}\n\t\tif (time >= addMinutes(cloneDate(day), maxMinute)) {\n\t\t\treturn slotTable.height();\n\t\t}\n\t\tvar slotMinutes = opt('slotMinutes'),\n\t\t\tminutes = time.getHours()*60 + time.getMinutes() - minMinute,\n\t\t\tslotI = Math.floor(minutes / slotMinutes),\n\t\t\tslotTop = slotTopCache[slotI];\n\t\tif (slotTop === undefined) {\n\t\t\tslotTop = slotTopCache[slotI] = slotTable.find('tr:eq(' + slotI + ') td div')[0].offsetTop; //.position().top; // need this optimization???\n\t\t}\n\t\treturn Math.max(0, Math.round(\n\t\t\tslotTop - 1 + slotHeight * ((minutes % slotMinutes) / slotMinutes)\n\t\t));\n\t}\n\n\n\tfunction allDayBounds() {\n\t\treturn {\n\t\t\tleft: axisWidth,\n\t\t\tright: viewWidth - gutterWidth\n\t\t}\n\t}\n\n\n\tfunction getAllDayRow(index) {\n\t\treturn allDayRow;\n\t}\n\n\n\tfunction defaultEventEnd(event) {\n\t\tvar start = cloneDate(event.start);\n\t\tif (event.allDay) {\n\t\t\treturn start;\n\t\t}\n\t\treturn addMinutes(start, opt('defaultEventMinutes'));\n\t}\n\n\n\n\t/* Selection\n\t---------------------------------------------------------------------------------*/\n\n\n\tfunction defaultSelectionEnd(startDate, allDay) {\n\t\tif (allDay) {\n\t\t\treturn cloneDate(startDate);\n\t\t}\n\t\treturn addMinutes(cloneDate(startDate), opt('slotMinutes'));\n\t}\n\n\n\tfunction renderSelection(startDate, endDate, allDay) { // only for all-day\n\t\tif (allDay) {\n\t\t\tif (opt('allDaySlot')) {\n\t\t\t\trenderDayOverlay(startDate, addDays(cloneDate(endDate), 1), true);\n\t\t\t}\n\t\t}else{\n\t\t\trenderSlotSelection(startDate, endDate);\n\t\t}\n\t}\n\n\n\tfunction renderSlotSelection(startDate, endDate) {\n\t\tvar helperOption = opt('selectHelper');\n\t\tcoordinateGrid.build();\n\t\tif (helperOption) {\n\t\t\tvar col = dayDiff(startDate, t.visStart) * dis + dit;\n\t\t\tif (col >= 0 && col < colCnt) { // only works when times are on same day\n\t\t\t\tvar rect = coordinateGrid.rect(0, col, 0, col, slotContent); // only for horizontal coords\n\t\t\t\tvar top = timePosition(startDate, startDate);\n\t\t\t\tvar bottom = timePosition(startDate, endDate);\n\t\t\t\tif (bottom > top) { // protect against selections that are entirely before or after visible range\n\t\t\t\t\trect.top = top;\n\t\t\t\t\trect.height = bottom - top;\n\t\t\t\t\trect.left += 2;\n\t\t\t\t\trect.width -= 5;\n\t\t\t\t\tif ($.isFunction(helperOption)) {\n\t\t\t\t\t\tvar helperRes = helperOption(startDate, endDate);\n\t\t\t\t\t\tif (helperRes) {\n\t\t\t\t\t\t\trect.position = 'absolute';\n\t\t\t\t\t\t\trect.zIndex = 8;\n\t\t\t\t\t\t\tselectionHelper = $(helperRes)\n\t\t\t\t\t\t\t\t.css(rect)\n\t\t\t\t\t\t\t\t.appendTo(slotContent);\n\t\t\t\t\t\t}\n\t\t\t\t\t}else{\n\t\t\t\t\t\trect.isStart = true; // conside rect a \"seg\" now\n\t\t\t\t\t\trect.isEnd = true; //\n\t\t\t\t\t\tselectionHelper = $(slotSegHtml(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttitle: '',\n\t\t\t\t\t\t\t\tstart: startDate,\n\t\t\t\t\t\t\t\tend: endDate,\n\t\t\t\t\t\t\t\tclassName: ['fc-select-helper'],\n\t\t\t\t\t\t\t\teditable: false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\trect\n\t\t\t\t\t\t));\n\t\t\t\t\t\tselectionHelper.css('opacity', opt('dragOpacity'));\n\t\t\t\t\t}\n\t\t\t\t\tif (selectionHelper) {\n\t\t\t\t\t\tslotBind(selectionHelper);\n\t\t\t\t\t\tslotContent.append(selectionHelper);\n\t\t\t\t\t\tsetOuterWidth(selectionHelper, rect.width, true); // needs to be after appended\n\t\t\t\t\t\tsetOuterHeight(selectionHelper, rect.height, true);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}else{\n\t\t\trenderSlotOverlay(startDate, endDate);\n\t\t}\n\t}\n\n\n\tfunction clearSelection() {\n\t\tclearOverlays();\n\t\tif (selectionHelper) {\n\t\t\tselectionHelper.remove();\n\t\t\tselectionHelper = null;\n\t\t}\n\t}\n\n\n\tfunction slotSelectionMousedown(ev) {\n\t\tif (ev.which == 1 && opt('selectable')) { // ev.which==1 means left mouse button\n\t\t\tunselect(ev);\n\t\t\tvar dates;\n\t\t\thoverListener.start(function(cell, origCell) {\n\t\t\t\tclearSelection();\n\t\t\t\tif (cell && cell.col == origCell.col && !cellIsAllDay(cell)) {\n\t\t\t\t\tvar d1 = cellDate(origCell);\n\t\t\t\t\tvar d2 = cellDate(cell);\n\t\t\t\t\tdates = [\n\t\t\t\t\t\td1,\n\t\t\t\t\t\taddMinutes(cloneDate(d1), opt('slotMinutes')),\n\t\t\t\t\t\td2,\n\t\t\t\t\t\taddMinutes(cloneDate(d2), opt('slotMinutes'))\n\t\t\t\t\t].sort(cmp);\n\t\t\t\t\trenderSlotSelection(dates[0], dates[3]);\n\t\t\t\t}else{\n\t\t\t\t\tdates = null;\n\t\t\t\t}\n\t\t\t}, ev);\n\t\t\t$(document).one('mouseup', function(ev) {\n\t\t\t\thoverListener.stop();\n\t\t\t\tif (dates) {\n\t\t\t\t\tif (+dates[0] == +dates[1]) {\n\t\t\t\t\t\treportDayClick(dates[0], false, ev);\n\t\t\t\t\t}\n\t\t\t\t\treportSelection(dates[0], dates[3], false, ev);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\n\tfunction reportDayClick(date, allDay, ev) {\n\t\ttrigger('dayClick', dayBodyCells[dayOfWeekCol(date.getDay())], date, allDay, ev);\n\t}\n\n\n\n\t/* External Dragging\n\t--------------------------------------------------------------------------------*/\n\n\n\tfunction dragStart(_dragElement, ev, ui) {\n\t\thoverListener.start(function(cell) {\n\t\t\tclearOverlays();\n\t\t\tif (cell) {\n\t\t\t\tif (cellIsAllDay(cell)) {\n\t\t\t\t\trenderCellOverlay(cell.row, cell.col, cell.row, cell.col);\n\t\t\t\t}else{\n\t\t\t\t\tvar d1 = cellDate(cell);\n\t\t\t\t\tvar d2 = addMinutes(cloneDate(d1), opt('defaultEventMinutes'));\n\t\t\t\t\trenderSlotOverlay(d1, d2);\n\t\t\t\t}\n\t\t\t}\n\t\t}, ev);\n\t}\n\n\n\tfunction dragStop(_dragElement, ev, ui) {\n\t\tvar cell = hoverListener.stop();\n\t\tclearOverlays();\n\t\tif (cell) {\n\t\t\ttrigger('drop', _dragElement, cellDate(cell), cellIsAllDay(cell), ev, ui);\n\t\t}\n\t}\n\n\n}\n\nfunction AgendaEventRenderer() {\n\tvar t = this;\n\n\n\t// exports\n\tt.renderEvents = renderEvents;\n\tt.compileDaySegs = compileDaySegs; // for DayEventRenderer\n\tt.clearEvents = clearEvents;\n\tt.slotSegHtml = slotSegHtml;\n\tt.bindDaySeg = bindDaySeg;\n\n\n\t// imports\n\tDayEventRenderer.call(t);\n\tvar opt = t.opt;\n\tvar trigger = t.trigger;\n\t//var setOverflowHidden = t.setOverflowHidden;\n\tvar isEventDraggable = t.isEventDraggable;\n\tvar isEventResizable = t.isEventResizable;\n\tvar eventEnd = t.eventEnd;\n\tvar reportEvents = t.reportEvents;\n\tvar reportEventClear = t.reportEventClear;\n\tvar eventElementHandlers = t.eventElementHandlers;\n\tvar setHeight = t.setHeight;\n\tvar getDaySegmentContainer = t.getDaySegmentContainer;\n\tvar getSlotSegmentContainer = t.getSlotSegmentContainer;\n\tvar getHoverListener = t.getHoverListener;\n\tvar getMaxMinute = t.getMaxMinute;\n\tvar getMinMinute = t.getMinMinute;\n\tvar timePosition = t.timePosition;\n\tvar colContentLeft = t.colContentLeft;\n\tvar colContentRight = t.colContentRight;\n\tvar renderDaySegs = t.renderDaySegs;\n\tvar resizableDayEvent = t.resizableDayEvent; // TODO: streamline binding architecture\n\tvar getColCnt = t.getColCnt;\n\tvar getColWidth = t.getColWidth;\n\tvar getSlotHeight = t.getSlotHeight;\n\tvar getBodyContent = t.getBodyContent;\n\tvar reportEventElement = t.reportEventElement;\n\tvar showEvents = t.showEvents;\n\tvar hideEvents = t.hideEvents;\n\tvar eventDrop = t.eventDrop;\n\tvar eventResize = t.eventResize;\n\tvar renderDayOverlay = t.renderDayOverlay;\n\tvar clearOverlays = t.clearOverlays;\n\tvar calendar = t.calendar;\n\tvar formatDate = calendar.formatDate;\n\tvar formatDates = calendar.formatDates;\n\n\n\n\t/* Rendering\n\t----------------------------------------------------------------------------*/\n\n\n\tfunction renderEvents(events, modifiedEventId) {\n\t\treportEvents(events);\n\t\tvar i, len=events.length,\n\t\t\tdayEvents=[],\n\t\t\tslotEvents=[];\n\t\tfor (i=0; i\" +\n\t\t\t\"
\" +\n\t\t\t\"
\" +\n\t\t\t\"
\" +\n\t\t\thtmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) +\n\t\t\t\"
\" +\n\t\t\t\"
\" +\n\t\t\t\"
\" +\n\t\t\t\"
\" +\n\t\t\thtmlEscape(event.title) +\n\t\t\t\"
\" +\n\t\t\t\"
\" +\n\t\t\t\"
\" +\n\t\t\t\"
\"; // close inner\n\t\tif (seg.isEnd && isEventResizable(event)) {\n\t\t\thtml +=\n\t\t\t\t\"
=
\";\n\t\t}\n\t\thtml +=\n\t\t\t\"\";\n\t\treturn html;\n\t}\n\n\n\tfunction bindDaySeg(event, eventElement, seg) {\n\t\tif (isEventDraggable(event)) {\n\t\t\tdraggableDayEvent(event, eventElement, seg.isStart);\n\t\t}\n\t\tif (seg.isEnd && isEventResizable(event)) {\n\t\t\tresizableDayEvent(event, eventElement, seg);\n\t\t}\n\t\teventElementHandlers(event, eventElement);\n\t\t\t// needs to be after, because resizableDayEvent might stopImmediatePropagation on click\n\t}\n\n\n\tfunction bindSlotSeg(event, eventElement, seg) {\n\t\tvar timeElement = eventElement.find('div.fc-event-time');\n\t\tif (isEventDraggable(event)) {\n\t\t\tdraggableSlotEvent(event, eventElement, timeElement);\n\t\t}\n\t\tif (seg.isEnd && isEventResizable(event)) {\n\t\t\tresizableSlotEvent(event, eventElement, timeElement);\n\t\t}\n\t\teventElementHandlers(event, eventElement);\n\t}\n\n\n\n\t/* Dragging\n\t-----------------------------------------------------------------------------------*/\n\n\n\t// when event starts out FULL-DAY\n\n\tfunction draggableDayEvent(event, eventElement, isStart) {\n\t\tvar origWidth;\n\t\tvar revert;\n\t\tvar allDay=true;\n\t\tvar dayDelta;\n\t\tvar dis = opt('isRTL') ? -1 : 1;\n\t\tvar hoverListener = getHoverListener();\n\t\tvar colWidth = getColWidth();\n\t\tvar slotHeight = getSlotHeight();\n\t\tvar minMinute = getMinMinute();\n\t\teventElement.draggable({\n\t\t\tzIndex: 9,\n\t\t\topacity: opt('dragOpacity', 'month'), // use whatever the month view was using\n\t\t\trevertDuration: opt('dragRevertDuration'),\n\t\t\tstart: function(ev, ui) {\n\t\t\t\ttrigger('eventDragStart', eventElement, event, ev, ui);\n\t\t\t\thideEvents(event, eventElement);\n\t\t\t\torigWidth = eventElement.width();\n\t\t\t\thoverListener.start(function(cell, origCell, rowDelta, colDelta) {\n\t\t\t\t\tclearOverlays();\n\t\t\t\t\tif (cell) {\n\t\t\t\t\t\t//setOverflowHidden(true);\n\t\t\t\t\t\trevert = false;\n\t\t\t\t\t\tdayDelta = colDelta * dis;\n\t\t\t\t\t\tif (!cell.row) {\n\t\t\t\t\t\t\t// on full-days\n\t\t\t\t\t\t\trenderDayOverlay(\n\t\t\t\t\t\t\t\taddDays(cloneDate(event.start), dayDelta),\n\t\t\t\t\t\t\t\taddDays(exclEndDay(event), dayDelta)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tresetElement();\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t// mouse is over bottom slots\n\t\t\t\t\t\t\tif (isStart) {\n\t\t\t\t\t\t\t\tif (allDay) {\n\t\t\t\t\t\t\t\t\t// convert event to temporary slot-event\n\t\t\t\t\t\t\t\t\teventElement.width(colWidth - 10); // don't use entire width\n\t\t\t\t\t\t\t\t\tsetOuterHeight(\n\t\t\t\t\t\t\t\t\t\teventElement,\n\t\t\t\t\t\t\t\t\t\tslotHeight * Math.round(\n\t\t\t\t\t\t\t\t\t\t\t(event.end ? ((event.end - event.start) / MINUTE_MS) : opt('defaultEventMinutes'))\n\t\t\t\t\t\t\t\t\t\t\t/ opt('slotMinutes')\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\teventElement.draggable('option', 'grid', [colWidth, 1]);\n\t\t\t\t\t\t\t\t\tallDay = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t\trevert = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\trevert = revert || (allDay && !dayDelta);\n\t\t\t\t\t}else{\n\t\t\t\t\t\tresetElement();\n\t\t\t\t\t\t//setOverflowHidden(false);\n\t\t\t\t\t\trevert = true;\n\t\t\t\t\t}\n\t\t\t\t\teventElement.draggable('option', 'revert', revert);\n\t\t\t\t}, ev, 'drag');\n\t\t\t},\n\t\t\tstop: function(ev, ui) {\n\t\t\t\thoverListener.stop();\n\t\t\t\tclearOverlays();\n\t\t\t\ttrigger('eventDragStop', eventElement, event, ev, ui);\n\t\t\t\tif (revert) {\n\t\t\t\t\t// hasn't moved or is out of bounds (draggable has already reverted)\n\t\t\t\t\tresetElement();\n\t\t\t\t\teventElement.css('filter', ''); // clear IE opacity side-effects\n\t\t\t\t\tshowEvents(event, eventElement);\n\t\t\t\t}else{\n\t\t\t\t\t// changed!\n\t\t\t\t\tvar minuteDelta = 0;\n\t\t\t\t\tif (!allDay) {\n\t\t\t\t\t\tminuteDelta = Math.round((eventElement.offset().top - getBodyContent().offset().top) / slotHeight)\n\t\t\t\t\t\t\t* opt('slotMinutes')\n\t\t\t\t\t\t\t+ minMinute\n\t\t\t\t\t\t\t- (event.start.getHours() * 60 + event.start.getMinutes());\n\t\t\t\t\t}\n\t\t\t\t\teventDrop(this, event, dayDelta, minuteDelta, allDay, ev, ui);\n\t\t\t\t}\n\t\t\t\t//setOverflowHidden(false);\n\t\t\t}\n\t\t});\n\t\tfunction resetElement() {\n\t\t\tif (!allDay) {\n\t\t\t\teventElement\n\t\t\t\t\t.width(origWidth)\n\t\t\t\t\t.height('')\n\t\t\t\t\t.draggable('option', 'grid', null);\n\t\t\t\tallDay = true;\n\t\t\t}\n\t\t}\n\t}\n\n\n\t// when event starts out IN TIMESLOTS\n\n\tfunction draggableSlotEvent(event, eventElement, timeElement) {\n\t\tvar origPosition;\n\t\tvar allDay=false;\n\t\tvar dayDelta;\n\t\tvar minuteDelta;\n\t\tvar prevMinuteDelta;\n\t\tvar dis = opt('isRTL') ? -1 : 1;\n\t\tvar hoverListener = getHoverListener();\n\t\tvar colCnt = getColCnt();\n\t\tvar colWidth = getColWidth();\n\t\tvar slotHeight = getSlotHeight();\n\t\teventElement.draggable({\n\t\t\tzIndex: 9,\n\t\t\tscroll: false,\n\t\t\tgrid: [colWidth, slotHeight],\n\t\t\taxis: colCnt==1 ? 'y' : false,\n\t\t\topacity: opt('dragOpacity'),\n\t\t\trevertDuration: opt('dragRevertDuration'),\n\t\t\tstart: function(ev, ui) {\n\t\t\t\ttrigger('eventDragStart', eventElement, event, ev, ui);\n\t\t\t\thideEvents(event, eventElement);\n\t\t\t\torigPosition = eventElement.position();\n\t\t\t\tminuteDelta = prevMinuteDelta = 0;\n\t\t\t\thoverListener.start(function(cell, origCell, rowDelta, colDelta) {\n\t\t\t\t\teventElement.draggable('option', 'revert', !cell);\n\t\t\t\t\tclearOverlays();\n\t\t\t\t\tif (cell) {\n\t\t\t\t\t\tdayDelta = colDelta * dis;\n\t\t\t\t\t\tif (opt('allDaySlot') && !cell.row) {\n\t\t\t\t\t\t\t// over full days\n\t\t\t\t\t\t\tif (!allDay) {\n\t\t\t\t\t\t\t\t// convert to temporary all-day event\n\t\t\t\t\t\t\t\tallDay = true;\n\t\t\t\t\t\t\t\ttimeElement.hide();\n\t\t\t\t\t\t\t\teventElement.draggable('option', 'grid', null);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\trenderDayOverlay(\n\t\t\t\t\t\t\t\taddDays(cloneDate(event.start), dayDelta),\n\t\t\t\t\t\t\t\taddDays(exclEndDay(event), dayDelta)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}else{\n\t\t\t\t\t\t\t// on slots\n\t\t\t\t\t\t\tresetElement();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}, ev, 'drag');\n\t\t\t},\n\t\t\tdrag: function(ev, ui) {\n\t\t\t\tminuteDelta = Math.round((ui.position.top - origPosition.top) / slotHeight) * opt('slotMinutes');\n\t\t\t\tif (minuteDelta != prevMinuteDelta) {\n\t\t\t\t\tif (!allDay) {\n\t\t\t\t\t\tupdateTimeText(minuteDelta);\n\t\t\t\t\t}\n\t\t\t\t\tprevMinuteDelta = minuteDelta;\n\t\t\t\t}\n\t\t\t},\n\t\t\tstop: function(ev, ui) {\n\t\t\t\tvar cell = hoverListener.stop();\n\t\t\t\tclearOverlays();\n\t\t\t\ttrigger('eventDragStop', eventElement, event, ev, ui);\n\t\t\t\tif (cell && (dayDelta || minuteDelta || allDay)) {\n\t\t\t\t\t// changed!\n\t\t\t\t\teventDrop(this, event, dayDelta, allDay ? 0 : minuteDelta, allDay, ev, ui);\n\t\t\t\t}else{\n\t\t\t\t\t// either no change or out-of-bounds (draggable has already reverted)\n\t\t\t\t\tresetElement();\n\t\t\t\t\teventElement.css('filter', ''); // clear IE opacity side-effects\n\t\t\t\t\teventElement.css(origPosition); // sometimes fast drags make event revert to wrong position\n\t\t\t\t\tupdateTimeText(0);\n\t\t\t\t\tshowEvents(event, eventElement);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tfunction updateTimeText(minuteDelta) {\n\t\t\tvar newStart = addMinutes(cloneDate(event.start), minuteDelta);\n\t\t\tvar newEnd;\n\t\t\tif (event.end) {\n\t\t\t\tnewEnd = addMinutes(cloneDate(event.end), minuteDelta);\n\t\t\t}\n\t\t\ttimeElement.text(formatDates(newStart, newEnd, opt('timeFormat')));\n\t\t}\n\t\tfunction resetElement() {\n\t\t\t// convert back to original slot-event\n\t\t\tif (allDay) {\n\t\t\t\ttimeElement.css('display', ''); // show() was causing display=inline\n\t\t\t\teventElement.draggable('option', 'grid', [colWidth, slotHeight]);\n\t\t\t\tallDay = false;\n\t\t\t}\n\t\t}\n\t}\n\n\n\n\t/* Resizing\n\t--------------------------------------------------------------------------------------*/\n\n\n\tfunction resizableSlotEvent(event, eventElement, timeElement) {\n\t\tvar slotDelta, prevSlotDelta;\n\t\tvar slotHeight = getSlotHeight();\n\t\teventElement.resizable({\n\t\t\thandles: {\n\t\t\t\ts: 'div.ui-resizable-s'\n\t\t\t},\n\t\t\tgrid: slotHeight,\n\t\t\tstart: function(ev, ui) {\n\t\t\t\tslotDelta = prevSlotDelta = 0;\n\t\t\t\thideEvents(event, eventElement);\n\t\t\t\teventElement.css('z-index', 9);\n\t\t\t\ttrigger('eventResizeStart', this, event, ev, ui);\n\t\t\t},\n\t\t\tresize: function(ev, ui) {\n\t\t\t\t// don't rely on ui.size.height, doesn't take grid into account\n\t\t\t\tslotDelta = Math.round((Math.max(slotHeight, eventElement.height()) - ui.originalSize.height) / slotHeight);\n\t\t\t\tif (slotDelta != prevSlotDelta) {\n\t\t\t\t\ttimeElement.text(\n\t\t\t\t\t\tformatDates(\n\t\t\t\t\t\t\tevent.start,\n\t\t\t\t\t\t\t(!slotDelta && !event.end) ? null : // no change, so don't display time range\n\t\t\t\t\t\t\t\taddMinutes(eventEnd(event), opt('slotMinutes')*slotDelta),\n\t\t\t\t\t\t\topt('timeFormat')\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t\tprevSlotDelta = slotDelta;\n\t\t\t\t}\n\t\t\t},\n\t\t\tstop: function(ev, ui) {\n\t\t\t\ttrigger('eventResizeStop', this, event, ev, ui);\n\t\t\t\tif (slotDelta) {\n\t\t\t\t\teventResize(this, event, 0, opt('slotMinutes')*slotDelta, ev, ui);\n\t\t\t\t}else{\n\t\t\t\t\teventElement.css('z-index', 8);\n\t\t\t\t\tshowEvents(event, eventElement);\n\t\t\t\t\t// BUG: if event was really short, need to put title back in span\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\n}\n\n\nfunction countForwardSegs(levels) {\n\tvar i, j, k, level, segForward, segBack;\n\tfor (i=levels.length-1; i>0; i--) {\n\t\tlevel = levels[i];\n\t\tfor (j=0; j\");\n var elements;\n var segmentContainer = getDaySegmentContainer();\n var i;\n var segCnt = segs.length;\n var element;\n tempContainer[0].innerHTML = daySegHTML(segs); // faster than .html()\n elements = tempContainer.children();\n segmentContainer.append(elements);\n daySegElementResolve(segs, elements);\n daySegCalcHSides(segs);\n daySegSetWidths(segs);\n daySegCalcHeights(segs);\n daySegSetTops(segs, getRowTops(getRowDivs()));\n elements = [];\n for (i=0; i\" +\n \"\";\n if (!event.allDay && seg.isStart) {\n html +=\n \"\" +\n htmlEscape(formatDates(event.start, event.end, opt('timeFormat'))) +\n \"\";\n }\n html +=\n \"\" + htmlEscape(event.title) + \"\" +\n \"
\";\n if (seg.isEnd && isEventResizable(event)) {\n html +=\n \"
\" +\n \"   \" + // makes hit area a lot better for IE6/7\n \"
\";\n }\n html +=\n \"\";\n seg.left = left;\n seg.outerWidth = right - left;\n seg.startCol = leftCol;\n seg.endCol = rightCol + 1; // needs to be exclusive\n }\n return html;\n }\n\n\n function daySegElementResolve(segs, elements) { // sets seg.element\n var i;\n var segCnt = segs.length;\n var seg;\n var event;\n var element;\n var triggerRes;\n for (i=0; i div'); // optimal selector?\n }\n return rowDivs;\n }\n\n\n function getRowTops(rowDivs) {\n var i;\n var rowCnt = rowDivs.length;\n var tops = [];\n for (i=0; i selection for IE\n element\n .mousedown(function(ev) { // prevent native selection for others\n ev.preventDefault();\n })\n .click(function(ev) {\n if (isResizing) {\n ev.preventDefault(); // prevent link from being visited (only method that worked in IE6)\n ev.stopImmediatePropagation(); // prevent fullcalendar eventClick handler from being called\n // (eventElementHandlers needs to be bound after resizableDayEvent)\n }\n });\n\n handle.mousedown(function(ev) {\n if (ev.which != 1) {\n return; // needs to be left mouse button\n }\n isResizing = true;\n var hoverListener = t.getHoverListener();\n var rowCnt = getRowCnt();\n var colCnt = getColCnt();\n var dis = rtl ? -1 : 1;\n var dit = rtl ? colCnt-1 : 0;\n var elementTop = element.css('top');\n var dayDelta;\n var helpers;\n var eventCopy = $.extend({}, event);\n var minCell = dateCell(event.start);\n clearSelection();\n $('body')\n .css('cursor', direction + '-resize')\n .one('mouseup', mouseup);\n trigger('eventResizeStart', this, event, ev);\n hoverListener.start(function(cell, origCell) {\n if (cell) {\n var r = Math.max(minCell.row, cell.row);\n var c = cell.col;\n if (rowCnt == 1) {\n r = 0; // hack for all-day area in agenda views\n }\n if (r == minCell.row) {\n if (rtl) {\n c = Math.min(minCell.col, c);\n }else{\n c = Math.max(minCell.col, c);\n }\n }\n dayDelta = (r*7 + c*dis+dit) - (origCell.row*7 + origCell.col*dis+dit);\n var newEnd = addDays(eventEnd(event), dayDelta, true);\n if (dayDelta) {\n eventCopy.end = newEnd;\n var oldHelpers = helpers;\n helpers = renderTempDaySegs(compileDaySegs([eventCopy]), seg.row, elementTop);\n helpers.find('*').css('cursor', direction + '-resize');\n if (oldHelpers) {\n oldHelpers.remove();\n }\n hideEvents(event);\n }else{\n if (helpers) {\n showEvents(event);\n helpers.remove();\n helpers = null;\n }\n }\n clearOverlays();\n renderDayOverlay(event.start, addDays(cloneDate(newEnd), 1)); // coordinate grid already rebuild at hoverListener.start\n }\n }, ev);\n\n function mouseup(ev) {\n trigger('eventResizeStop', this, event, ev);\n $('body').css('cursor', '');\n hoverListener.stop();\n clearOverlays();\n if (dayDelta) {\n eventResize(this, event, dayDelta, 0, ev);\n // event redraw will clear helpers\n }\n // otherwise, the drag handler already restored the old events\n\n setTimeout(function() { // make this happen after the element's click event\n isResizing = false;\n },0);\n }\n\n });\n }\n\n\n}\n\n//BUG: unselect needs to be triggered when events are dragged+dropped\n\nfunction SelectionManager() {\n\tvar t = this;\n\n\n\t// exports\n\tt.select = select;\n\tt.unselect = unselect;\n\tt.reportSelection = reportSelection;\n\tt.daySelectionMousedown = daySelectionMousedown;\n\n\n\t// imports\n\tvar opt = t.opt;\n\tvar trigger = t.trigger;\n\tvar defaultSelectionEnd = t.defaultSelectionEnd;\n\tvar renderSelection = t.renderSelection;\n\tvar clearSelection = t.clearSelection;\n\n\n\t// locals\n\tvar selected = false;\n\n\n\n\t// unselectAuto\n\tif (opt('selectable') && opt('unselectAuto')) {\n\t\t$(document).mousedown(function(ev) {\n\t\t\tvar ignore = opt('unselectCancel');\n\t\t\tif (ignore) {\n\t\t\t\tif ($(ev.target).parents(ignore).length) { // could be optimized to stop after first match\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tunselect(ev);\n\t\t});\n\t}\n\n\n\tfunction select(startDate, endDate, allDay) {\n\t\tunselect();\n\t\tif (!endDate) {\n\t\t\tendDate = defaultSelectionEnd(startDate, allDay);\n\t\t}\n\t\trenderSelection(startDate, endDate, allDay);\n\t\treportSelection(startDate, endDate, allDay);\n\t}\n\n\n\tfunction unselect(ev) {\n\t\tif (selected) {\n\t\t\tselected = false;\n\t\t\tclearSelection();\n\t\t\ttrigger('unselect', null, ev);\n\t\t}\n\t}\n\n\n\tfunction reportSelection(startDate, endDate, allDay, ev, resource) {\n\t\tselected = true;\n\t\ttrigger('select', null, startDate, endDate, allDay, ev, resource);\n\t}\n\n\n\tfunction daySelectionMousedown(ev) { // not really a generic manager method, oh well\n\t\tvar cellDate = t.cellDate;\n\t\tvar cellIsAllDay = t.cellIsAllDay;\n\t\tvar hoverListener = t.getHoverListener();\n\t\tvar reportDayClick = t.reportDayClick; // this is hacky and sort of weird\n\t\tif (ev.which == 1 && opt('selectable')) { // which==1 means left mouse button\n\t\t\tunselect(ev);\n\t\t\tvar _mousedownElement = this;\n\t\t\tvar dates;\n\t\t\thoverListener.start(function(cell, origCell) { // TODO: maybe put cellDate/cellIsAllDay info in cell\n\t\t\t\tclearSelection();\n\t\t\t\tif (cell && cellIsAllDay(cell)) {\n\t\t\t\t\tdates = [ cellDate(origCell), cellDate(cell) ].sort(cmp);\n\t\t\t\t\trenderSelection(dates[0], dates[1], true);\n\t\t\t\t}else{\n\t\t\t\t\tdates = null;\n\t\t\t\t}\n\t\t\t}, ev);\n\t\t\t$(document).one('mouseup', function(ev) {\n\t\t\t\thoverListener.stop();\n\t\t\t\tif (dates) {\n\t\t\t\t\tif (+dates[0] == +dates[1]) {\n\t\t\t\t\t\treportDayClick(dates[0], true, ev);\n\t\t\t\t\t}\n\t\t\t\t\treportSelection(dates[0], dates[1], true, ev);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\n}\n\nfunction OverlayManager() {\n\tvar t = this;\n\n\n\t// exports\n\tt.renderOverlay = renderOverlay;\n\tt.clearOverlays = clearOverlays;\n\n\n\t// locals\n\tvar usedOverlays = [];\n\tvar unusedOverlays = [];\n\n\n\tfunction renderOverlay(rect, parent) {\n\t\tvar e = unusedOverlays.shift();\n\t\tif (!e) {\n\t\t\te = $(\"
\");\n\t\t}\n\t\tif (e[0].parentNode != parent[0]) {\n\t\t\te.appendTo(parent);\n\t\t}\n\t\tusedOverlays.push(e.css(rect).show());\n\t\treturn e;\n\t}\n\n\n\tfunction clearOverlays() {\n\t\tvar e;\n\t\twhile (e = usedOverlays.shift()) {\n\t\t\tunusedOverlays.push(e.hide().unbind());\n\t\t}\n\t}\n\n\n}\n\nfunction CoordinateGrid(buildFunc) {\n\n\tvar t = this;\n\tvar rows;\n\tvar cols;\n\n\n\tt.build = function() {\n\t\trows = [];\n\t\tcols = [];\n\t\tbuildFunc(rows, cols);\n\t};\n\n\n\tt.cell = function(x, y) {\n\t\tvar rowCnt = rows.length;\n\t\tvar colCnt = cols.length;\n\t\tvar i, r=-1, c=-1;\n\t\tfor (i=0; i= rows[i][0] && y < rows[i][1]) {\n\t\t\t\tr = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfor (i=0; i= cols[i][0] && x < cols[i][1]) {\n\t\t\t\tc = i;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn (r>=0 && c>=0) ? { row:r, col:c } : null;\n\t};\n\n\n\tt.rect = function(row0, col0, row1, col1, originElement) { // row1,col1 is inclusive\n\t\tvar origin = originElement.offset();\n\t\treturn {\n\t\t\ttop: rows[row0][0] - origin.top,\n\t\t\tleft: cols[col0][0] - origin.left,\n\t\t\twidth: cols[col1][1] - cols[col0][0],\n\t\t\theight: rows[row1][1] - rows[row0][0]\n\t\t};\n\t};\n\n}\n\nfunction HoverListener(coordinateGrid) {\n\n\n\tvar t = this;\n\tvar bindType;\n\tvar change;\n\tvar firstCell;\n\tvar cell;\n\n\n\tt.start = function(_change, ev, _bindType) {\n\t\tchange = _change;\n\t\tfirstCell = cell = null;\n\t\tcoordinateGrid.build();\n\t\tmouse(ev);\n\t\tbindType = _bindType || 'mousemove';\n\t\t$(document).bind(bindType, mouse);\n\t};\n\n\n\tfunction mouse(ev) {\n\t\t_fixUIEvent(ev); // see below\n\t\tvar newCell = coordinateGrid.cell(ev.pageX, ev.pageY);\n\t\tif (!newCell != !cell || newCell && (newCell.row != cell.row || newCell.col != cell.col)) {\n\t\t\tif (newCell) {\n\t\t\t\tif (!firstCell) {\n\t\t\t\t\tfirstCell = newCell;\n\t\t\t\t}\n\t\t\t\tchange(newCell, firstCell, newCell.row-firstCell.row, newCell.col-firstCell.col);\n\t\t\t}else{\n\t\t\t\tchange(newCell, firstCell);\n\t\t\t}\n\t\t\tcell = newCell;\n\t\t}\n\t}\n\n\n\tt.stop = function() {\n\t\t$(document).unbind(bindType, mouse);\n\t\treturn cell;\n\t};\n\n\n}\n\n\n\n// this fix was only necessary for jQuery UI 1.8.16 (and jQuery 1.7 or 1.7.1)\n// upgrading to jQuery UI 1.8.17 (and using either jQuery 1.7 or 1.7.1) fixed the problem\n// but keep this in here for 1.8.16 users\n// and maybe remove it down the line\n\nfunction _fixUIEvent(event) { // for issue 1168\n\tif (event.pageX === undefined) {\n\t\tevent.pageX = event.originalEvent.pageX;\n\t\tevent.pageY = event.originalEvent.pageY;\n\t}\n}\nfunction HorizontalPositionCache(getElement) {\n\n\tvar t = this,\n\t\telements = {},\n\t\tlefts = {},\n\t\trights = {};\n\n\tfunction e(i) {\n\t\treturn elements[i] = elements[i] || getElement(i);\n\t}\n\n\tt.left = function(i) {\n\t\treturn lefts[i] = lefts[i] === undefined ? e(i).position().left : lefts[i];\n\t};\n\n\tt.right = function(i) {\n\t\treturn rights[i] = rights[i] === undefined ? t.left(i) + e(i).width() : rights[i];\n\t};\n\n\tt.clear = function() {\n\t\telements = {};\n\t\tlefts = {};\n\t\trights = {};\n\t};\n\n}\n\n})(jQuery);\n\ndefine(\"fullcalendar\", [\"jquery\"], function(){});\n\n","define('modules/appointment/search/search-ctrl',[\n './../module',\n 'angular',\n 'underscore'\n], function (module, angular, _) {\n 'use strict';\n\n module.controller('AppointmentSearchCtrl', function ($scope, $rootScope, $location, $stateParams, $q, $controller, $modal, $translate, CompanySetting, Enums, Sms, Appointment, Contact, Employee, FittingRoom, AppointmentType, Category, alerts, modalService, AppointmentModal, InterviewModal, ResourcesHelper, eventsBus) {\n\n var headers = [\n {\n title: '' //status has no heading\n },\n {\n title: 'common.type',\n sortField: 'typeDescription'\n },\n {\n title: 'common.contact-name',\n sortField: 'contactName'\n },\n {\n title: 'common.modal.event-date',\n sortField: 'contactEventDate'\n },\n {\n title: 'contact.personal-information.category',\n sortField: 'categoryDescription'\n },\n {\n title: 'appointment.search-headers.start-date/time',\n sortField: 'startDateTime',\n active: true\n },\n {\n title: 'appointment.search-headers.duration',\n sortField: 'duration'\n },\n {\n title: 'common.associate',\n sortField: 'employeeName'\n }\n ];\n\n if ($scope.config.withoutColumns && $scope.config.withoutColumns.length) {\n _($scope.config.withoutColumns).each(function (column) {\n headers = _(headers).without(_(headers).findWhere({ sortField: column }));\n });\n }\n\n $scope.doIgnoreMemorizeSearch = !!_($stateParams).chain().values().compact().value().length;\n $scope.withoutColumns = $scope.config.withoutColumns || [];\n $scope.columnsCount = headers.length + !!$scope.config.multiSelect + 1/* Actions column */;\n $scope.statuses = [\n Enums.statuses.all,\n Enums.statuses.pending,\n Enums.statuses.complete,\n Enums.statuses.canceled,\n Enums.statuses.didNotShow\n ];\n\n /**\n * Init table after loading employees and appt_types\n * @param resources\n */\n var initResources = function (resources) {\n var employees = ResourcesHelper.adaptList('employees', resources[0]);\n var fittingRooms = ResourcesHelper.adaptList('fittingRooms', resources[1], _(resources[4]).findWhere({ type : 'AC_HIDE_UNASSIGNED_FITTING_ROOM' }));\n var appointmentTypes = resources[2];\n var categories = ResourcesHelper.adaptList('categories', resources[3]);\n\n //add the \"All\" options to the lists\n if (employees) {\n employees.unshift({ fullName: $translate.instant('common.all')});\n }\n\n if (fittingRooms) {\n fittingRooms.unshift({ name: $translate.instant('common.all')});\n }\n\n if (appointmentTypes) {\n appointmentTypes.unshift({ description: $translate.instant('common.all')});\n }\n\n if (categories) {\n categories.unshift({id:-1, description: $translate.instant('common.all')});\n }\n\n //setup data for search form\n $scope.employees = employees;\n $scope.fittingRooms = fittingRooms;\n $scope.appointmentTypes = appointmentTypes;\n $scope.categories = categories;\n $scope.optInValues = Enums.optInOptions;\n };\n\n var employeesPromise = Employee.query({ sortField: 'firstName', filterObject: { status: Enums.statuses.active.value } });\n var fittingRoomsPromise = FittingRoom.query({ filterObject: { status: Enums.statuses.active.value } });\n var appointmentTypesPromise = AppointmentType.query({ filterObject: { status: Enums.statuses.active.value } });\n var categoriesPromise = Category.query({sortField: 'description', filterObject:{status:Enums.statuses.active.value}});\n var apptAndTasksPromise = CompanySetting.getApptAndTaskSettings();\n\n $q.all([employeesPromise, fittingRoomsPromise, appointmentTypesPromise, categoriesPromise, apptAndTasksPromise]).then(initResources);\n\n /**\n * Main logic of the controller\n */\n\n angular.extend(this, $controller('SearchCtrl', { $scope: $scope, headers: headers }));\n // default search values\n var status = $stateParams.status || Enums.statuses.all.value;\n $scope.pagination.sortDirection = 'asc';\n $scope.pagination.sortField = 'startDateTime';\n $scope.initialValues = angular.extend($scope.config.initialFormValues || {}, { status: status,\n createdDateAfter: $stateParams.createdDate,\n createdDateBefore: $stateParams.createdDateBefore,\n categoryId: -1,\n startDateTime: $stateParams.startDateTime,\n endDateTime: $stateParams.endDateTime\n });\n\n $scope.formValues = angular.copy($scope.initialValues);\n\n $scope.results = $scope.selectedResults = [];\n $scope.search = function () {\n if ($scope.config.ignoreInitialValues) {\n return;\n }\n\n var payload = $scope.buildFilterObject();\n\n if ($scope.config.anyStatus) {\n delete payload.filterObject.status;\n }\n\n Appointment[$scope.config.resourceMethod](payload, $scope.updateResults);\n };\n\n /**\n * Opens Add Appointment modal with current datetime\n */\n $scope.showAddAppointmentModal = function ($event) {\n if ($event) {\n $event.preventDefault();\n }\n\n var contactId = $scope.config.initialFormValues && $scope.config.initialFormValues.contactId;\n\n AppointmentModal.openAdd(null, false, contactId)\n .result\n .then(function (createdAppointment) {\n if (createdAppointment) {\n $scope.search();\n }\n });\n };\n\n $scope.showSendTextMessageModal = function (appt) {\n\n var contactObj = {\n id: appt.contactId,\n appointmentId: appt.id,\n mobilePhoneNumber: appt.mobilePhoneNumber\n };\n\n Sms.showSendModal(contactObj);\n };\n\n $scope.showEditAppointmentModal = function ($event, appointment) {\n if ($event) {\n $event.preventDefault();\n }\n\n AppointmentModal\n .openEdit(false, appointment)\n .result\n .then(function (savedAppointment) {\n if (savedAppointment) {\n $scope.search();\n }\n });\n };\n\n $scope.showAppointmentHistoryModal = function($event, appointment) {\n if ($event) {\n $event.preventDefault();\n }\n\n $modal.open({\n templateUrl: 'js/modules/appointment-modal/appointment-history.tpl.html',\n controller: 'ApptHistoryCtrl',\n resolve: {\n appointments: function () {\n return Appointment.listAllAppointmentsForContact(appointment.contactId);\n },\n contactName: function () {\n return appointment.contactName;\n }\n },\n windowClass: '__large'\n });\n };\n\n $scope.remove = function (appt) {\n modalService.showConfirmation('appointment.message.delete', function () {\n appt.$remove(function () {\n $scope.onResultRemoved(appt);\n });\n });\n };\n\n $scope.markAsCompleted = function () {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('appointment.message.select', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'appointment.message.mark-completed-success',\n params: { number: $scope.selectedResults.length }\n });\n };\n\n modalService.showConfirmation({\n key: 'appointment.message.mark-completed-info',\n params: { number: $scope.selectedResults.length }\n }, function () {\n Appointment.bulkUpdateStatus(Enums.statuses.complete.value, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.reset = function () {\n if($stateParams.startDateTime && $stateParams.endDateTime) {\n $location.url($location.path());\n }\n\n $scope.formValues = _($scope.initialValues).clone();\n\n eventsBus.publish('searchForm:reset');\n };\n\n $scope.changeEmployee = function (emp) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('appointment.message.select', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'appointment.message.change-emp-success',\n params: { number: $scope.selectedResults.length, fullName: emp.fullName }\n });\n };\n\n modalService.showConfirmation({\n key: 'appointment.message.change-emp-info',\n params: { number: $scope.selectedResults.length, fullName: emp.fullName }\n }, function () {\n Appointment.bulkUpdateEmployee(emp.id, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.changeFittingRoom = function (room) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('appointment.message.select', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'appointment.message.change-room-success',\n params: { number: $scope.selectedResults.length, room: room.description }\n });\n };\n\n modalService.showConfirmation({\n key: 'appointment.message.change-room-info',\n params: { number: $scope.selectedResults.length, room: room.description }\n }, function () {\n Appointment.bulkUpdateFittingRoom(room.id, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.changeType = function (type) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('appointment.message.select', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'appointment.message.change-type-success',\n params: { number: $scope.selectedResults.length, type: type.description }\n });\n };\n\n modalService.showConfirmation({\n key: 'appointment.message.change-type-info',\n params: { number: $scope.selectedResults.length, type: type.description }\n }, function () {\n Appointment.bulkUpdateType(type.id, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.sendTextMessage = function () {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('appointment.message.select', 'common.message.wooops');\n return false;\n }\n\n if ($scope.selectedResults.length > 250) {\n modalService.showMessage('contact.messages.select-no-more-than-250', 'common.message.cannot-send-sms-messages');\n return false;\n }\n\n var selectedResultsSMS = [];\n\n _.each($scope.selectedResults, function (selectedResults) {\n\n var contactObj = {\n id: selectedResults.contactId,\n appointmentId: selectedResults.id,\n mobilePhoneNumber: selectedResults.mobilePhoneNumber\n };\n\n selectedResultsSMS.push(contactObj);\n });\n\n var successcb = function (result) {\n var modalScope = {\n errors: result.errors,\n successes: result.successes,\n optedErrors: result.optedErrors\n };\n\n $modal.open({\n templateUrl: 'js/modules/contact/modals/bulk-twilio-send-result-modal.tpl.html',\n controller: 'BulkTwilioSendResultModalCtrl',\n resolve: {\n modalScope: function () {\n return modalScope;\n }\n },\n backdrop:'static'\n });\n\n };\n\n Sms.showSendModal(selectedResultsSMS, null, null, null, successcb);\n };\n\n $scope.changeSMSOptIn = function (optIn) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('appointment.message.select', 'common.message.wooops');\n return false;\n }\n\n var selectedResultsOptIn = [];\n\n _.each($scope.selectedResults, function (selectedResults) {\n\n\n var contactObj = {\n id: selectedResults.contactId,\n };\n\n selectedResultsOptIn.push(contactObj);\n });\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.contact.successfully-changed-sms-opt-in',\n params: {\n number: $scope.selectedResults.length,\n optIn: $translate.instant(optIn.description)\n }\n });\n };\n\n modalService.showConfirmation({\n key: 'contact.messages.are-you-sure-you-would-like-to-change-sms-opt-in?',\n params: {\n number: $scope.selectedResults.length,\n optIn: $translate.instant(optIn.description)\n }\n }, function () {\n Contact.bulkUpdateSMSOptIn(optIn.value, _(selectedResultsOptIn).pluck('id'), successcb);\n });\n\n };\n\n $scope.changeCategory = function (cat) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('appointment.message.select', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.contact.successfully-moved',\n params: {\n number: $scope.selectedResults.length,\n category: cat.description\n }\n });\n };\n\n modalService.showConfirmation({\n key: 'contact.messages.are-you-sure-you-would-like-to-move?',\n params: {\n number: $scope.selectedResults.length,\n category: cat.description\n }\n }, function () {\n Contact.bulkUpdateCategory(cat.id, _($scope.selectedResults).pluck('contactId'), successcb);\n });\n };\n\n $scope.exportToExcel = function () {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('appointment.message.select', 'common.message.wooops');\n return false;\n }\n\n modalService.showConfirmation({\n key: 'appointment.message.export-excel',\n params: { number: $scope.selectedResults.length}\n }, function () {\n Appointment.exportToExcel(_($scope.selectedResults).pluck('id'),\n $scope.pagination.sortField,\n $scope.pagination.sortDirection);\n });\n };\n\n $scope.exportToPdf = function () {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('appointment.message.select', 'common.message.wooops');\n return false;\n }\n\n modalService.showConfirmation({\n key: 'appointment.message.export-pdf',\n params: { number: $scope.selectedResults.length}\n }, function () {\n Appointment.exportToPdf(_($scope.selectedResults).pluck('id'),\n $scope.pagination.sortField,\n $scope.pagination.sortDirection);\n });\n };\n\n $scope.exportAppointmentSheets = function () {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('appointment.message.select', 'common.message.wooops');\n return false;\n }\n\n modalService.showConfirmation({\n key: 'appointment.message.export-sheets',\n params: { number: $scope.selectedResults.length}\n }, function () {\n Appointment.exportAppointmentSheets(_($scope.selectedResults).pluck('id'), null, $rootScope.embeddediPadApp);\n });\n };\n\n $scope.openInterviewModal = InterviewModal.open;\n\n $scope.getAppointmentIconClass = function (appointment) {\n var isPending = appointment.status === Enums.statuses.pending.value;\n var isPendingOnly = isPending && !appointment.confirmed && !appointment.checkedIn;\n var isConfirmed = isPending && appointment.confirmed;\n var isCheckedIn = isPending && appointment.checkedIn;\n\n return {\n 'glyphicon-time': isPendingOnly,\n 'glyphicon-thumbs-up': isConfirmed && !isCheckedIn,\n 'glyphicon-hourglass': isCheckedIn,\n 'glyphicon-ok': appointment.status === Enums.statuses.complete.value,\n 'glyphicon-thumbs-down': appointment.status === Enums.statuses.didNotShow.value,\n 'glyphicon-remove': appointment.status === Enums.statuses.canceled.value\n };\n };\n\n $scope.getConfirmedOrCheckedInTooltipSuffix = function (appointment) {\n if (appointment.status === Enums.statuses.complete.value) {\n return '';\n }\n\n if (appointment.confirmed) {\n return 'and Confirmed';\n }\n\n if (appointment.checkedIn) {\n return 'and Checked-In';\n }\n\n return '';\n };\n });\n});\n\n","/*Copyright (c), 2011 Sanford, L.P. All Rights Reserved.*/(function() {var n,aa=aa||{},p=this;p.Aa=!0;function q(){}\nfunction ba(a){var b=typeof a;if(\"object\"==b)if(a){if(a instanceof Array)return\"array\";if(a instanceof Object)return b;var d=Object.prototype.toString.call(a);if(\"[object Window]\"==d)return\"object\";if(\"[object Array]\"==d||\"number\"==typeof a.length&&\"undefined\"!=typeof a.splice&&\"undefined\"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable(\"splice\"))return\"array\";if(\"[object Function]\"==d||\"undefined\"!=typeof a.call&&\"undefined\"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable(\"call\"))return\"function\"}else return\"null\";\nelse if(\"function\"==b&&\"undefined\"==typeof a.call)return\"object\";return b}function ca(a){return\"array\"==ba(a)}function da(a){var b=ba(a);return\"array\"==b||\"object\"==b&&\"number\"==typeof a.length}function t(a){return\"string\"==typeof a}function ea(a){return\"number\"==typeof a}function u(a){return\"function\"==ba(a)}var fa=\"closure_uid_\"+(1E9*Math.random()>>>0),ga=0;function ha(a,b,d){return a.call.apply(a.bind,arguments)}\nfunction ia(a,b,d){if(!a)throw Error();if(2b?1:0};function pa(a,b){b.unshift(a);z.call(this,la.apply(null,b));b.shift()}x(pa,z);pa.prototype.name=\"AssertionError\";function qa(a,b){throw new pa(\"Failure\"+(a?\": \"+a:\"\"),Array.prototype.slice.call(arguments,1));};var B=Array.prototype,ra=B.indexOf?function(a,b,d){return B.indexOf.call(a,b,d)}:function(a,b,d){d=null==d?0:0>d?Math.max(0,a.length+d):d;if(t(a))return t(b)&&1==b.length?a.indexOf(b,d):-1;for(;db?null:t(a)?a.charAt(b):a[b]}function xa(a,b){var d=ra(a,b),e;(e=0<=d)&&B.splice.call(a,d,1);return e}function ya(a){return B.concat.apply(B,arguments)};var C;a:{var za=p.navigator;if(za){var Ba=za.userAgent;if(Ba){C=Ba;break a}}C=\"\"};function Ca(a,b){for(var d in a)b.call(void 0,a[d],d,a)}function Da(a){var b=[],d=0,e;for(e in a)b[d++]=a[e];return b}function Ea(a){var b=[],d=0,e;for(e in a)b[d++]=e;return b}var Fa=\"constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf\".split(\" \");function Ga(a,b){for(var d,e,g=1;gparseFloat(a))?String(b):a}(),Pa={};\nfunction F(a){var b;if(!(b=Pa[a])){b=0;for(var d=ma(String(Oa)).split(\".\"),e=ma(String(a)).split(\".\"),g=Math.max(d.length,e.length),h=0;0==b&&h\");Ua(\"\");function Va(a,b){Ca(b,function(b,e){\"style\"==e?a.style.cssText=b:\"class\"==e?a.className=b:\"for\"==e?a.htmlFor=b:e in Wa?a.setAttribute(Wa[e],b):0==e.lastIndexOf(\"aria-\",0)||0==e.lastIndexOf(\"data-\",0)?a.setAttribute(e,b):a[e]=b})}var Wa={cellpadding:\"cellPadding\",cellspacing:\"cellSpacing\",colspan:\"colSpan\",frameborder:\"frameBorder\",height:\"height\",maxlength:\"maxLength\",role:\"role\",rowspan:\"rowSpan\",type:\"type\",usemap:\"useMap\",valign:\"vAlign\",width:\"width\"};\nfunction Xa(a,b){var d=[];Ya(a,b,d,!1);return d}function Ya(a,b,d,e){if(null!=a)for(a=a.firstChild;a;){if(b(a)&&(d.push(a),e)||Ya(a,b,d,e))return!0;a=a.nextSibling}return!1}var Za={SCRIPT:1,STYLE:1,HEAD:1,IFRAME:1,OBJECT:1},$a={IMG:\" \",BR:\"\\n\"};function ab(a,b,d){if(!(a.nodeName in Za))if(3==a.nodeType)d?b.push(String(a.nodeValue).replace(/(\\r\\n|\\r|\\n)/g,\"\")):b.push(a.nodeValue);else if(a.nodeName in $a)b.push($a[a.nodeName]);else for(a=a.firstChild;a;)ab(a,b,d),a=a.nextSibling};function bb(a){a.prototype.then=a.prototype.then;a.prototype.$goog_Thenable=!0}function cb(a){if(!a)return!1;try{return!!a.$goog_Thenable}catch(b){return!1}};function db(a,b){this.h=a;this.i=b;this.f=0;this.c=null}function eb(a){var b;0a.f&&(a.f++,b.next=a.c,a.c=b)};var hb=new db(function(){return new gb},function(a){a.reset()});function ib(){var a=jb,b=null;a.c&&(b=a.c,a.c=a.c.next,a.c||(a.f=null),b.next=null);return b}function gb(){this.next=this.f=this.c=null}gb.prototype.reset=function(){this.next=this.f=this.c=null};function kb(a){p.setTimeout(function(){throw a;},0)}var lb;\nfunction mb(){var a=p.MessageChannel;\"undefined\"===typeof a&&\"undefined\"!==typeof window&&window.postMessage&&window.addEventListener&&!A(C,\"Presto\")&&(a=function(){var a=document.createElement(\"IFRAME\");a.style.display=\"none\";a.src=\"\";document.documentElement.appendChild(a);var b=a.contentWindow,a=b.document;a.open();a.write(\"\");a.close();var d=\"callImmediate\"+Math.random(),e=\"file:\"==b.location.protocol?\"*\":b.location.protocol+\"//\"+b.location.host,a=v(function(a){if((\"*\"==e||a.origin==e)&&a.data==\nd)this.port1.onmessage()},this);b.addEventListener(\"message\",a,!1);this.port1={};this.port2={postMessage:function(){b.postMessage(d,e)}}});if(\"undefined\"!==typeof a&&!Ia()){var b=new a,d={},e=d;b.port1.onmessage=function(){if(void 0!==d.next){d=d.next;var a=d.fa;d.fa=null;a()}};return function(a){e.next={fa:a};e=e.next;b.port2.postMessage(0)}}return\"undefined\"!==typeof document&&\"onreadystatechange\"in document.createElement(\"SCRIPT\")?function(a){var b=document.createElement(\"SCRIPT\");b.onreadystatechange=\nfunction(){b.onreadystatechange=null;b.parentNode.removeChild(b);b=null;a();a=null};document.documentElement.appendChild(b)}:function(a){p.setTimeout(a,0)}};function nb(a,b){ob||pb();qb||(ob(),qb=!0);var d=jb,e=eb(hb);e.c=a;e.f=b;e.next=null;d.f?d.f.next=e:d.c=e;d.f=e}var ob;function pb(){if(p.Promise&&p.Promise.resolve){var a=p.Promise.resolve();ob=function(){a.then(rb)}}else ob=function(){var a=rb;!u(p.setImmediate)||p.Window&&p.Window.prototype&&p.Window.prototype.setImmediate==p.setImmediate?(lb||(lb=mb()),lb(a)):p.setImmediate(a)}}var qb=!1,jb=new function(){this.f=this.c=null};\nfunction rb(){for(var a=null;a=ib();){try{a.c.call(a.f)}catch(b){kb(b)}fb(hb,a)}qb=!1};function G(a,b){this.c=sb;this.o=void 0;this.i=this.f=this.h=null;this.l=this.m=!1;if(a==tb)ub(this,vb,b);else try{var d=this;a.call(b,function(a){ub(d,vb,a)},function(a){if(!(a instanceof wb))try{if(a instanceof Error)throw a;throw Error(\"Promise rejected.\");}catch(b){}ub(d,H,a)})}catch(e){ub(this,H,e)}}var sb=0,vb=2,H=3;function xb(){this.next=this.h=this.f=this.i=this.c=null;this.l=!1}xb.prototype.reset=function(){this.h=this.f=this.i=this.c=null;this.l=!1};\nvar yb=new db(function(){return new xb},function(a){a.reset()});function zb(a,b,d){var e=eb(yb);e.i=a;e.f=b;e.h=d;return e}function tb(){}function Ab(a){return new G(function(b,d){var e=a.length,g=[];if(e)for(var h=function(a,d){e--;g[a]=d;0==e&&b(g)},k=function(a){d(a)},l=0,m;m=a[l];l++)Bb(m,ja(h,l),k);else b(g)})}G.prototype.then=function(a,b,d){return Cb(this,u(a)?a:null,u(b)?b:null,d)};bb(G);function Bb(a,b,d,e){a instanceof G?Db(a,zb(b||q,d||null,e)):a.then(b,d,e)}n=G.prototype;\nn.ka=function(a,b){return Cb(this,null,a,b)};n.cancel=function(a){this.c==sb&&nb(function(){var b=new wb(a);Eb(this,b)},this)};function Eb(a,b){if(a.c==sb)if(a.h){var d=a.h;if(d.f){for(var e=0,g=null,h=null,k=d.f;k&&(k.l||(e++,k.c==a&&(g=k),!(g&&1=a.keyCode)a.keyCode=-1}catch(b){}};var Vb=\"closure_listenable_\"+(1E6*Math.random()|0),Wb=0;function Xb(a,b,d,e,g){this.listener=a;this.c=null;this.src=b;this.type=d;this.aa=!!e;this.ba=g;++Wb;this.N=this.$=!1}function Yb(a){a.N=!0;a.listener=null;a.c=null;a.src=null;a.ba=null};function Zb(a){this.src=a;this.c={};this.f=0}function $b(a,b,d,e,g,h){var k=b.toString();b=a.c[k];b||(b=a.c[k]=[],a.f++);var l=ac(b,d,g,h);-1g.keyCode||void 0!=g.returnValue)){a:{var h=!1;if(0==g.keyCode)try{g.keyCode=-1;break a}catch(k){h=!0}if(h||void 0==g.returnValue)g.returnValue=!0}g=[];for(h=d.c;h;h=h.parentNode)g.push(h);for(var h=a.type,l=g.length-1;0<=l;l--){d.c=g[l];var m=nc(g[l],h,!0,d),e=e&&m}for(l=0;l>>0);function gc(a){if(u(a))return a;a[pc]||(a[pc]=function(b){return a.handleEvent(b)});return a[pc]};function I(){Mb.call(this);this.D=new Zb(this);this.da=this;this.R=null}x(I,Mb);I.prototype[Vb]=!0;I.prototype.addEventListener=function(a,b,d,e){fc(this,a,b,d,e)};I.prototype.removeEventListener=function(a,b,d,e){lc(this,a,b,d,e)};\nfunction K(a,b){var d,e=a.R;if(e)for(d=[];e;e=e.R)d.push(e);var e=a.da,g=b,h=g.type||g;if(t(g))g=new Sb(g,e);else if(g instanceof Sb)g.target=g.target||e;else{var k=g,g=new Sb(h,e);Ga(g,k)}var k=!0,l;if(d)for(var m=d.length-1;0<=m;m--)l=g.c=d[m],k=qc(l,h,!0,g)&&k;l=g.c=e;k=qc(l,h,!0,g)&&k;k=qc(l,h,!1,g)&&k;if(d)for(m=0;m=Oc(this).value)for(u(b)&&(b=b()),a=new Fc(a,String(b),this.i),d&&(a.c=d),d=\"log:\"+a.f,p.console&&(p.console.timeStamp?p.console.timeStamp(d):p.console.markTimeline&&p.console.markTimeline(d)),p.msWriteProfilerMark&&p.msWriteProfilerMark(d),d=this;d;)d=d.f};var Pc={},Qc=null;\nfunction Rc(a){Qc||(Qc=new Hc(\"\"),Pc[\"\"]=Qc,Qc.c=Mc);var b;if(!(b=Pc[a])){b=new Hc(a);var d=a.lastIndexOf(\".\"),e=a.substr(d+1),d=Rc(a.substr(0,d));d.h||(d.h={});d.h[e]=b;b.f=d;Pc[a]=b}return b};function L(a,b){a&&a.log(Nc,b,void 0)};function Sc(){}Sc.prototype.c=null;function Tc(a){var b;(b=a.c)||(b={},Uc(a)&&(b[0]=!0,b[1]=!0),b=a.c=b);return b};var Vc;function Wc(){}x(Wc,Sc);function Xc(a){return(a=Uc(a))?new ActiveXObject(a):new XMLHttpRequest}function Uc(a){if(!a.f&&\"undefined\"==typeof XMLHttpRequest&&\"undefined\"!=typeof ActiveXObject){for(var b=[\"MSXML2.XMLHTTP.6.0\",\"MSXML2.XMLHTTP.3.0\",\"MSXML2.XMLHTTP\",\"Microsoft.XMLHTTP\"],d=0;db)throw Error(\"Bad port number \"+b);a.s=b}else a.s=null}function vd(a,b,d){b instanceof xd?(a.h=b,Dd(a.h,a.m)):(d||(b=yd(b,Ed)),a.h=new xd(b,0,a.m))}function Fd(a){return a instanceof N?a.clone():new N(a,void 0)}\nfunction Gd(a,b){a instanceof N||(a=Fd(a));b instanceof N||(b=Fd(b));var d=a,e=b,g=d.clone(),h=!!e.i;h?td(g,e.i):h=!!e.o;h?g.o=e.o:h=!!e.c;h?g.c=e.c:h=null!=e.s;var k=e.f;if(h)ud(g,e.s);else if(h=!!e.f)if(\"/\"!=k.charAt(0)&&(d.c&&!d.f?k=\"/\"+k:(d=g.f.lastIndexOf(\"/\"),-1!=d&&(k=g.f.substr(0,d+1)+k))),d=k,\"..\"==d||\".\"==d)k=\"\";else if(A(d,\"./\")||A(d,\"/.\")){for(var k=0==d.lastIndexOf(\"/\",0),d=d.split(\"/\"),l=[],m=0;m>4&15).toString(16)+(a&15).toString(16)}\nvar zd=/[#\\/\\?@]/g,Bd=/[\\#\\?:]/g,Ad=/[\\#\\?]/g,Ed=/[\\#\\?@]/g,Cd=/#/g;function xd(a,b,d){this.h=this.c=null;this.f=a||null;this.i=!!d}function Id(a){a.c||(a.c=new Ac,a.h=0,a.f&&ad(a.f,function(b,d){var e=decodeURIComponent(b.replace(/\\+/g,\" \"));Id(a);a.f=null;var e=Kd(a,e),g=Ec(a.c,e);g||Bc(a.c,e,g=[]);g.push(d);a.h++}))}function Ld(a,b){Id(a);b=Kd(a,b);if(Dc(a.c.f,b)){a.f=null;a.h-=Ec(a.c,b).length;var d=a.c;Dc(d.f,b)&&(delete d.f[b],d.h--,d.i++,d.c.length>2*d.h&&Cc(d))}}n=xd.prototype;\nn.clear=function(){this.c=this.f=null;this.h=0};n.I=function(){Id(this);for(var a=this.c.J(),b=this.c.I(),d=[],e=0;e cachedWebPort : \"+e+\"/\"+g);O(\"checkEnvironment > trying async service discovery\");g?jd(\"https://\"+e+\":\"+g+\"/DYMO/DLS/Printing/StatusConnected\",function(b){rd(b.target)?a():(Rd(null,null),Vd(\"127.0.0.1\",a,d))},\"GET\",void 0,3E3):Vd(\"127.0.0.1\",a,d)}\nfunction Wd(a,b){function d(b,d){O(\"checkEnvironment > web service found at :\"+d+\"/\"+b);Rd(b,d);a();Xd||P.c()}var e=Sd(),g=e.Port,e=e.Host;O(\"checkEnvironment > cachedWebPort : \"+e+\"/\"+g);O(\"checkEnvironment > trying synchronous service discovery\");var g=g||41951,e=e||\"127.0.0.1\",h=\"127.0.0.1\"===e;Yd(g,e)?d(g,e):h&&Yd(g,\"localhost\")?d(g,\"localhost\"):(Rd(null,null),b())}function Yd(a,b){try{return\"true\"===Td(\"https://\"+b+\":\"+a+\"/DYMO/DLS/Printing/StatusConnected\",{},\"GET\")}catch(d){return!1}}\nfunction Vd(a,b,d){for(var e=[],g=41951;41960>=g;++g)e.push(Zd(g,a));Ab(e).then(function(){setTimeout(d,0)}).ka(function(e){ea(e)?(Rd(e,a),b()):d()})}function Zd(a,b){var d=\"https://\"+b+\":\"+a+\"/DYMO/DLS/Printing/StatusConnected\";return new G(function(b,g){jd(d,function(d){rd(d.target)?g(a):b(a)},\"GET\",void 0,3E3)})}\nfunction $d(a,b,d){var e=Sd(),g=\"https://\"+e.Host+\":\"+e.Port+\"/DYMO/DLS/Printing/\"+b;return new G(function(e,k){var l=[],m=null,r;for(r in d)l.push(encodeURIComponent(r)+\"=\"+encodeURIComponent(d[r]));\"POST\"==a?m=l.length?l.join(\"&\"):\"\":g+=l.length?\"?\"+l.join(\"&\"):\"\";jd(g,function(a){var d=a.target;a=null;if(rd(d)){d=sd(d);try{a=window.JSON.parse(d)}catch(g){a=d}e(a)}else a=\"Failed to execute webservice command: \"+b+\". Error: \"+d.w(),O(\"invokeWsCommandAsync > \"+a),k(Error(a))},a||\"GET\",m,1E4)})}\nfunction ae(a,b,d){var e=Sd();a=Td(\"https://\"+e.Host+\":\"+e.Port+\"/DYMO/DLS/Printing/\"+b,d,a);try{return window.JSON.parse(a)}catch(g){return a}}\nfunction be(){this.getPrinters=function(){return ae(\"GET\",\"GetPrinters\",{})};this.openLabelFile=function(a){return ae(\"GET\",\"OpenLabelFile\",{fileName:a})};this.printLabel=function(a,b,d,e){return ae(\"POST\",\"PrintLabel\",{printerName:a,printParamsXml:b,labelXml:d,labelSetXml:e})};this.printLabel2=function(a,b,d,e){return ae(\"POST\",\"PrintLabel2\",{printerName:a,printParamsXml:b,labelXml:d,labelSetXml:e})};this.renderLabel=function(a,b,d){return ae(\"POST\",\"RenderLabel\",{labelXml:a,renderParamsXml:b,printerName:d})};\nthis.loadImageAsPngBase64=function(a){return ae(\"GET\",\"LoadImageAsPngBase64\",{imageUri:a})};this.T=function(){return $d(\"GET\",\"GetPrinters\",{})};this.V=function(a){return $d(\"GET\",\"OpenLabelFile\",{fileName:a})};this.X=function(a,b,d,e){return $d(\"POST\",\"PrintLabel\",{printerName:a,printParamsXml:b,labelXml:d,labelSetXml:e})};this.W=function(a,b,d,e){return $d(\"POST\",\"PrintLabel2\",{printerName:a,printParamsXml:b,labelXml:d,labelSetXml:e})};this.Y=function(a,b,d){return $d(\"POST\",\"RenderLabel\",{labelXml:a,\nrenderParamsXml:b,printerName:d})};this.U=function(a){return $d(\"GET\",\"LoadImageAsPngBase64\",{imageUri:a})}};var ce={};w(\"dymo.label.framework.FlowDirection\",ce);ce.LeftToRight=\"LeftToRight\";ce.RightToLeft=\"RightToLeft\";var de={};w(\"dymo.label.framework.LabelWriterPrintQuality\",de);de.Auto=\"Auto\";de.Text=\"Text\";de.BarcodeAndGraphics=\"BarcodeAndGraphics\";var ee={};w(\"dymo.label.framework.TwinTurboRoll\",ee);ee.Auto=\"Auto\";ee.Left=\"Left\";ee.Right=\"Right\";var fe={};w(\"dymo.label.framework.TapeAlignment\",fe);fe.Center=\"Center\";fe.Left=\"Left\";fe.Right=\"Right\";var ge={};w(\"dymo.label.framework.TapeCutMode\",ge);\nge.AutoCut=\"AutoCut\";ge.ChainMarks=\"ChainMarks\";var he={};w(\"dymo.label.framework.AddressBarcodePosition\",he);he.AboveAddress=\"AboveAddress\";he.BelowAddress=\"BelowAddress\";he.Suppress=\"Suppress\";var Q={};w(\"dymo.label.framework.PrintJobStatus\",Q);Q.S=0;Q.Unknown=Q.S;Q.va=1;Q.Printing=Q.va;Q.na=2;Q.Finished=Q.na;Q.Error=3;Q.Error=Q.Error;Q.ta=4;Q.PaperOut=Q.ta;Q.oa=5;Q.InQueue=Q.oa;Q.ea=-1;Q.ProcessingError=Q.ea;Q.ua=-2;Q.PrinterBusy=Q.ua;Q.pa=-3;Q.InvalidJobId=Q.pa;Q.sa=-4;Q.NotSpooled=Q.sa;function R(a){if(\"undefined\"!=typeof DOMParser)return(new DOMParser).parseFromString(a,\"application/xml\");if(\"undefined\"!=typeof ActiveXObject){var b=new ActiveXObject(\"MSXML2.DOMDocument\");if(b){b.resolveExternals=!1;b.validateOnParse=!1;try{b.setProperty(\"ProhibitDTD\",!0),b.setProperty(\"MaxXMLSize\",2048),b.setProperty(\"MaxElementDepth\",256)}catch(d){}}b.loadXML(a);return b}throw Error(\"Your browser does not support loading xml documents\");}\nfunction ie(a){if(\"undefined\"!=typeof XMLSerializer)return(new XMLSerializer).serializeToString(a);if(a=a.xml)return a;throw Error(\"Your browser does not support serializing XML documents\");};function S(a,b,d,e){b=a.ownerDocument.createElement(b);d&&b.appendChild(a.ownerDocument.createTextNode(d));if(e)for(var g in e)b.setAttribute(g,e[g]);a.appendChild(b)}function T(a){if(a){var b=[];ab(a,b,!1);a=b.join(\"\")}else a=\"\";return a}function U(a,b){var d=a.getElementsByTagName(b);if(0\"),d=b.documentElement,e=0;e\")?(l=R(l),m.appendChild(l.documentElement.cloneNode(!0))):m.appendChild(b.createTextNode(l));h.appendChild(m)}}d.appendChild(h)}return ie(b)}W.toXml=je;W.prototype.toString=function(){return je(this.c)};function X(){}\nX.prototype.h=function(a,b){b=b.toString();0!=b.indexOf(\"\")&&(b=\"\"+b+\"\");this[a]=b;return this};X.prototype.setTextMarkup=X.prototype.h;X.prototype.f=function(a,b){this[a]=b;return this};X.prototype.setText=X.prototype.f;X.prototype.c=function(a,b){this[a]=b;return this};X.prototype.setBase64Image=X.prototype.c;function Y(a){this.f=R(a)}Y.prototype.c=function(){return ie(this.f)};Y.prototype.getLabelXml=Y.prototype.c;Y.prototype.M=function(a,b){return ke(this.c(),a,b)};Y.prototype.render=Y.prototype.M;Y.prototype.O=function(a,b){return le(this.c(),a,b)};Y.prototype.renderAsync=Y.prototype.O;Y.prototype.h=function(a,b,d){me(a,b,this.c(),d)};Y.prototype.print=Y.prototype.h;Y.prototype.H=function(a,b,d){return ne(a,b,this.c(),d)};Y.prototype.printAsync=Y.prototype.H;\nY.prototype.A=function(a,b,d){return oe(a,b,this.c(),d)};Y.prototype.print2=Y.prototype.A;Y.prototype.F=function(a,b,d){return pe(a,b,this.c(),d)};Y.prototype.print2Async=Y.prototype.F;Y.prototype.G=function(a,b,d,e,g){return qe(a,b,this.c(),d,e,g)};Y.prototype.printAndPollStatus=Y.prototype.G;Y.prototype.B=function(a,b,d,e,g){return re(a,b,this.c(),d,e,g)};Y.prototype.printAndPollStatusAsync=Y.prototype.B;var se=\"AddressObject TextObject BarcodeObject ShapeObject CounterObject ImageObject CircularTextObject DateTimeObject\".split(\" \");\nfunction te(a,b){var d=b||se;return Xa(a.f.documentElement,function(a){return 1==a.nodeType&&0<=ra(d,a.tagName)})}Y.prototype.o=function(){for(var a=te(this),b=[],d=0;d').documentElement);\nfor(h=R('').documentElement;e.firstChild;)e.removeChild(e.firstChild);d=d.split(\"\\n\");for(l=0;l is expected but not found: \"+ie(e));e=g.ownerDocument.createElement(\"Image\");V(e,b);d.replaceChild(e,g)}break;case \"CircularTextObject\":V(U(d,\"Text\"),b);break;case \"DateTimeObject\":V(U(d,\n\"PreText\"),b);break;case \"CounterObject\":V(U(d,\"PreText\"),b)}return this};Y.prototype.setObjectText=Y.prototype.da;Y.prototype.Z=function(a){var b=this.f.documentElement;if(\"ContinuousLabel\"!=b.nodeName)throw Error(\"Cannot set length on non-continuous label.\");var d=0==a?\"Auto\":\"Fixed\";a=0==a?7200:a;V(U(b,\"LengthMode\"),d);V(U(b,\"LabelLength\"),a);b=U(b,\"RootCell\");V(U(b,\"Length\"),a);V(U(b,\"LengthMode\"),d);return this};Y.prototype.setLabelLength=Y.prototype.Z;Y.prototype.toString=function(){return this.c()};/*\n Portions of this code are from MochiKit, received by\n The Closure Authors under the MIT license. All other code is Copyright\n 2005-2009 The Closure Authors. All Rights Reserved.\n*/\nfunction ye(a,b){this.l=[];this.B=a;this.G=b||null;this.i=this.c=!1;this.h=void 0;this.A=this.H=this.o=!1;this.m=0;this.f=null;this.s=0}ye.prototype.cancel=function(a){if(this.c)this.h instanceof ye&&this.h.cancel();else{if(this.f){var b=this.f;delete this.f;a?b.cancel(a):(b.s--,0>=b.s&&b.cancel())}this.B?this.B.call(this.G,this):this.A=!0;this.c||(a=new ze,Ae(this),Be(this,!1,a))}};ye.prototype.F=function(a,b){this.o=!1;Be(this,a,b)};function Be(a,b,d){a.c=!0;a.h=d;a.i=!b;Ce(a)}\nfunction Ae(a){if(a.c){if(!a.A)throw new De;a.A=!1}}function Ee(a,b,d,e){a.l.push([b,d,e]);a.c&&Ce(a)}ye.prototype.then=function(a,b,d){var e,g,h=new G(function(a,b){e=a;g=b});Ee(this,e,function(a){a instanceof ze?h.cancel():g(a)});return h.then(a,b,d)};bb(ye);function Fe(a){return ua(a.l,function(a){return u(a[1])})}\nfunction Ce(a){if(a.m&&a.c&&Fe(a)){var b=a.m,d=Ge[b];d&&(p.clearTimeout(d.u),delete Ge[b]);a.m=0}a.f&&(a.f.s--,delete a.f);for(var b=a.h,e=d=!1;a.l.length&&!a.o;){var g=a.l.shift(),h=g[0],k=g[1],g=g[2];if(h=a.i?k:h)try{var l=h.call(g||a.G,b);void 0!==l&&(a.i=a.i&&(l==b||l instanceof Error),a.h=b=l);if(cb(b)||\"function\"===typeof p.Promise&&b instanceof p.Promise)e=!0,a.o=!0}catch(m){b=m,a.i=!0,Fe(a)||(d=!0)}}a.h=b;e&&(l=v(a.F,a,!0),e=v(a.F,a,!1),b instanceof ye?(Ee(b,l,e),b.H=!0):b.then(l,e));d&&(b=\nnew He(b),Ge[b.u]=b,a.m=b.u)}function De(){z.call(this)}x(De,z);De.prototype.message=\"Deferred has already fired\";De.prototype.name=\"AlreadyCalledError\";function ze(){z.call(this)}x(ze,z);ze.prototype.message=\"Deferred was canceled\";ze.prototype.name=\"CanceledError\";function He(a){this.u=p.setTimeout(v(this.f,this),0);this.c=a}He.prototype.f=function(){delete Ge[this.u];throw this.c;};var Ge={};function Ie(a,b){var d=b||{},e=d.document||document,g=document.createElement(\"SCRIPT\"),h={ja:g,L:void 0},k=new ye(Je,h),l=null,m=null!=d.timeout?d.timeout:5E3;0>>=8)&255;k[g++]=(h>>>=8)&255;k[g++]=h>>>8&255;h=4294967296*Math.random();k[g++]=h&255;k[g++]=(h>>>=8)&255;k[g++]=(h>>>=8)&15|64;k[g++]=h>>>8&255;h=4294967296*Math.random();k[g++]=h&63|128;k[g++]=\n(h>>>=8)&255;k[g++]=(h>>>=8)&255;k[g++]=h>>>8&255;h=4294967296*Math.random();k[g++]=h&255;k[g++]=(h>>>=8)&255;k[g++]=(h>>>=8)&255;k[g++]=h>>>8&255;return void 0===b?a(k):k}for(var d=Array,e=new d(16),g=[],h={},k=0;256>k;k++)g[k]=(k+256).toString(16).substr(1).toUpperCase(),h[g[k]]=k;b.f=function(a){var b=new d(16),e=0;a.toUpperCase().replace(/[0-9A-F][0-9A-F]/g,function(a){b[e++]=h[a]});return b};b.h=a;b.c=d;return b}();function Xe(a,b,d,e){this.printerName=a;this.jobId=b;this.status=d;this.statusMessage=e}function Ye(a){var b={};a=a.split(\" \");1<=a.length&&(b.status=parseInt(a[0],10));b.statusMessage=a.slice(1).join(\" \");return b}function Ze(a){for(var b=0;b WebServicePresent\");var d=new be;if(d)a={getPrinters:function(){return d.getPrinters()},openLabelFile:function(a){return d.openLabelFile(a)},printLabel:function(a,b,e,g){d.printLabel(a,b,e,g)},printLabel2:function(a,b,e,g){d.printLabel2(a,b,e,g)},renderLabel:function(a,b,e){return d.renderLabel(a,\nb,e)},loadImageAsPngBase64:function(a){return d.loadImageAsPngBase64(a)},getJobStatus:function(a,b){var e;u(d.getJobStatus)?e=Ye(d.getJobStatus(a,parseInt(b,10))):e={status:Q.S,statusMessage:\"not implemented\"};return new Xe(a,b,e.status,e.statusMessage)},T:function(){return d.T()},V:function(a){return d.V(a)},X:function(a,b,e,g){return d.X(a,b,e,g)},W:function(a,b,e,g){return d.W(a,b,e,g)},Y:function(a,b,e){return d.Y(a,b,e)},U:function(a){return d.U(a)}};else throw Error(\"Cannot establish connection to the web service. Is DYMO Label Framework installed?\");\nreturn a}if(\"ActiveXObject\"in window){O(\"chooseEnvironment > ActiveXObject\");a={};var e=ef();a.getPrinters=function(){return e.GetPrinters()};a.openLabelFile=function(a){return e.OpenLabelFile(a)};a.printLabel=function(a,b,d,g){e.PrintLabel(a,b,d,g)};a.renderLabel=function(a,b,d){return e.RenderLabel(a,b,d)};a.loadImageAsPngBase64=function(a){return e.LoadImageAsPngBase64(a)};a.printLabel2=function(a,b,d,g){if(u(e.PrintLabel2))return e.PrintLabel2(a,b,d,g).toString();e.PrintLabel(a,b,d,g)};a.getJobStatus=\nfunction(a,b){var d;u(e.GetJobStatus)?d=Ye(e.GetJobStatus(a,parseInt(b,10))):d={status:Q.S,statusMessage:\"not implemented\"};return new Xe(a,b,d.status,d.statusMessage)}}else if(-1!=navigator.platform.indexOf(\"Win\")){O(\"chooseEnvironment > WIN\");var g=bf();if(g)a={getPrinters:function(){return g.getPrinters()},openLabelFile:function(a){return g.openLabelFile(a)},printLabel:function(a,b,d,e){g.printLabel(a,b,d,e)},renderLabel:function(a,b,d){return g.renderLabel(a,b,d)},loadImageAsPngBase64:function(a){return g.loadImageAsPngBase64(a)},\nprintLabel2:function(a,b,d,e){if(u(g.printLabel2))return g.printLabel2(a,b,d,e).toString();g.printLabel(a,b,d,e)},getJobStatus:function(a,b){var d;u(g.getJobStatus)?d=Ye(g.getJobStatus(a,parseInt(b,10))):d={status:Q.S,statusMessage:\"not implemented\"};return new Xe(a,b,d.status,d.statusMessage)}};else throw Error(\"DYMO Label Framework is not installed\");}else{O(\"chooseEnvironment > not WIN\");var h;Ze(\"application/x-dymolabel\")?(O(\"chooseEnvironment > _createSafariPlugin\"),h=$e()):(O(\"chooseEnvironment > _createMacNsapiPlugin\"),\nh=df());O(\"chooseEnvironment > safariPlugin : \"+!!h);if(h)a={getPrinters:function(){return h.getPrinters()},openLabelFile:function(a){var b=h.openLabelFile(a);if(!b)throw Error(\"Unable to open label file '\"+a+\"'\");return b},printLabel:function(a,b,d,e){h.printLabel(d,a,b,e)},renderLabel:function(a,b,d){return h.renderLabel(a,b,d)},loadImageAsPngBase64:function(a){var b=h.loadImageAsPngBase64(a);if(!b)throw Error(\"Unable to load image from uri '\"+a+\"'\");return b},printLabel2:function(a,b,d,e){if(u(h.printLabel2))return h.printLabel2(d,\na,b,e).toString();h.printLabel(d,a,b,e)},getJobStatus:function(a,b){var d;u(h.getJobStatus)?d=Ye(h.getJobStatus(a,parseInt(b,10))):d={status:Q.S,statusMessage:\"not implemented\"};return new Xe(a,b,d.status,d.statusMessage)}};else throw Error(\"DYMO Label Framework is not installed\");}a.T=b(a.getPrinters);a.V=b(a.openLabelFile);a.X=b(a.printLabel);a.W=b(a.printLabel2);a.Y=b(a.renderLabel);a.U=b(a.loadImageAsPngBase64);return a}w(\"dymo.label.framework.trace\",!1);var Xd=0;\nfunction O(a){window.dymo.label.framework.trace&&window.console&&window.console.log&&console.log(a)}function gf(a){function b(){throw d;}var d=a||Error(\"DYMO Label Framework Plugin or WebService are not installed\");return{getPrinters:b,openLabelFile:b,printLabel:b,printLabel2:b,renderLabel:b,loadImageAsPngBase64:b,getJobStatus:b,T:b,V:b,X:b,W:b,Y:b,U:b}}\nvar P=function(){function a(g,h){if(d)throw O(\"_createFramework > Error service discovery is in progress. \"),Error(\"DYMO Label Framework service discovery is in progress.\");return b?(O(\"_createFramework > returning existing instance of _framework, has callBack: \"+!!g),g&&g(e),b):this&&this.constructor==a?(d=!0,P.c=function(){e=b=null;Xd=0},hf(function(a){e=a;O(\"onEnvironmentChecked > checkResult isBrowserSupported : \"+a.isBrowserSupported+\", isFrameworkInstalled: \"+a.isFrameworkInstalled+\", isWebServicePresent: \"+\na.isWebServicePresent+\", errorDetails: \"+a.errorDetails);try{b=ff(a),Xd=a.isWebServicePresent?2:1}catch(l){O(\"onEnvironmentChecked > exception e : \"+(l.description||l.message||l));if(!h)throw l;b=gf(l);O(\"onEnvironmentChecked > fall back to createFaultyFramework\")}finally{d=!1}g&&g(e)},h),O(\"_createFramework > return _framework : \"+b+(h?\" (async)\":\" (sync)\")),b):new a(g,h)}var b,d=!1,e=null;return a}();w(\"dymo.label.framework.init\",function(a){P(a,!0)});function jf(a,b,d,e,g){this.printerType=a;this.name=b;this.modelName=d;this.isConnected=e;this.isLocal=g;this.c=this.C=\"\"}function kf(a,b,d,e,g){jf.call(this,\"LabelWriterPrinter\",a,b,d,e);this.isTwinTurbo=g}x(kf,jf);function lf(a,b,d,e,g){jf.call(this,\"TapePrinter\",a,b,d,e);this.isAutoCutSupported=g}x(lf,jf);function mf(a,b,d,e,g){jf.call(this,\"DZPrinter\",a,b,d,e);this.isAutoCutSupported=g}x(mf,jf);function Z(a,b){this.c=a;this.f=b}Z.prototype.h=function(){return this.c.name};Z.prototype.getPrinterName=Z.prototype.h;Z.prototype.i=function(){return this.f};Z.prototype.getJobId=Z.prototype.i;Z.prototype.w=function(a){if(\"\"!=this.c.C)nf(this,a);else{var b;try{b=P().getJobStatus(this.c.name,this.f)}catch(d){b=new Xe(this.h(),this.f,Q.ea,d.message||d)}a(b)}};Z.prototype.getStatus=Z.prototype.w;\nfunction nf(a,b){var d=a.h(),e=a.f,g=a.c.C;(new Pe(Gd(g,\"getPrintJobStatus\"),\"callback\")).send({jobId:e,printerName:a.c.c},function(a){b(new Xe(d,e,a.status,a.statusMessage))},function(){b(new Xe(d,e,Q.ea,'Error processing getPrintJobStatus(): Unable to contact \"'+g+'\"'))})};w(\"dymo.label.framework.VERSION\",\"3.0.0\");\nfunction hf(a,b){function d(){O(\"checkLegacyPlugins\");g.isWebServicePresent=!1;var b=window.navigator.platform;if(-1!=b.indexOf(\"Win\"))if(O(\"checkLegacyPlugins > WIN platform \"),\"ActiveXObject\"in window){O(\"checkLegacyPlugins > ActiveXObject\");g.isBrowserSupported=!0;try{\"object\"!=typeof new ActiveXObject(\"DYMOLabelFrameworkIEPlugin.Plugin\")?g.errorDetails=\"Unable to create DYMO.Label.Framework ActiveX object. Check that DYMO.Label.Framework is installed\":g.isFrameworkInstalled=!0}catch(d){g.errorDetails=\n\"Unable to create DYMO.Label.Framework ActiveX object. Check that DYMO.Label.Framework is installed. Exception details: \"+d}}else O(\"checkLegacyPlugins > non-IE\"),g.isBrowserSupported=!0,Ze(\"application/x-dymolabel\")?(O(\"checkLegacyPlugins > 'application/x-dymolabel'\"),g.isFrameworkInstalled=!0):g.errorDetails=\"DYMO Label Framework Plugin is not installed\";else-1!=b.indexOf(\"Mac\")?(O(\"checkLegacyPlugins > Mac platform\"),g.isBrowserSupported=!0,Ze(\"application/x-dymolabel\")?(O(\"checkLegacyPlugins > safariPluginFound\"),\nb=$e(),\"2.0\"<=b.GetAPIVersion()?g.isFrameworkInstalled=!0:g.errorDetails=\"DYMO Label Safari Plugin is installed but outdated. Install the latest version.\"):Ze(\"application/x-npapi-dymolabel\")?(O(\"checkLegacyPlugins > 'application/x-npapi-dymolabel'\"),(b=df())&&b.getPrinters?g.isFrameworkInstalled=!0:g.errorDetails='DYMO NSAPI plugin is loaded but no callable functions found. If running Safari, then run it in 64-bit mode (MacOS X >= 10.7) or set \"Open using Rosetta\" option'):g.errorDetails=\"DYMO Label Plugin is not installed.\"):\ng.errorDetails=\"The operating system is not supported.\";a&&a(g)}function e(){g.isBrowserSupported=!0;g.isFrameworkInstalled=!0;g.isWebServicePresent=!0;a&&a(g)}var g={isBrowserSupported:!1,isFrameworkInstalled:!1,isWebServicePresent:!1,errorDetails:\"\"};if(Xd)return O(\"checkEnvironment > return existing instance of framework\"),2==Xd?e():(g.isBrowserSupported=!0,g.isFrameworkInstalled=!0,g.isWebServicePresent=!1,a&&a(g)),g;b?Ud(e,d):Wd(e,d);return g}w(\"dymo.label.framework.checkEnvironment\",hf);\nvar of={};function pf(a,b,d){this.c=a;this.f=b;this.h=d}pf.prototype.getPrinters=function(){var a=qf(this.h),b=new N(this.c),d=this.f;\"\"==d&&(d=b.c);for(b=0;b=l.length?a=-1:e=l.substr(d,4E3);(new Pe(k,\"c\")).send({j:h,cid:a,pl:e},function(d){var e=d.status,k=new Hc(\"dymo.label.framework\");k.c=Lc;0==e?-1!=a?g(++a,0):k.log(Lc,\"Finished sending job payload for \"+h,void 0):-5==e?10>b?g(++d.lastAckChunkId,++b):k.log(Kc,'Unable to send print job data for \"'+h+'\": STATUS_INVALID_CHUNK_ID: Max retry count reached',void 0):10>b?g(a,++b):k.log(Kc,'Unable to send print job data for \"'+h+'\": Max retry count reached',\nvoid 0)},function(){var d=new Hc(\"dymo.label.framework\");d.c=Lc;10>b?g(a,++b):d.log(Kc,'Unable to send print job data for \"'+h+'\": error: Max retry count reached',void 0)})}var h=We();b={printerName:a.c,labelXml:d,printParamsXml:b,labelSetXml:e};var k=Gd(a.C,\"pl\"),l=sc(b);g(0,0);return new Z(a,h)}function qe(a,b,d,e,g,h){function k(a){if(g(l,a)){var b=new Ue(function(){l.w(k);Pb(b)},h);Ve(b)}}var l=oe(a,b,d,e);l.w(k);return l}w(\"dymo.label.framework.printLabelAndPollStatus\",qe);\nfunction re(a,b,d,e,g,h){return pe(a,b,d,e).then(function(a){function b(d){if(g(a,d)){var e=new Ue(function(){a.w(b);Pb(e)},h);Ve(e)}}a.w(b);return a})}w(\"dymo.label.framework.printLabelAndPollStatusAsync\",re);function ke(a,b,d){if(\"undefined\"==typeof a)throw Error(\"renderLabel(): labelXml parameter should be specified\");\"string\"!=typeof a&&(a=a.toString());b=b||\"\";d=d||\"\";return P().renderLabel(a,b,d)}w(\"dymo.label.framework.renderLabel\",ke);\nfunction le(a,b,d){if(\"undefined\"==typeof a)throw Error(\"renderLabelAsync(): labelXml parameter should be specified\");\"string\"!=typeof a&&(a=a.toString());b=b||\"\";d=d||\"\";return P().Y(a,b,d)}w(\"dymo.label.framework.renderLabelAsync\",le);w(\"dymo.label.framework.loadImageAsPngBase64\",function(a){return P().loadImageAsPngBase64(a)});w(\"dymo.label.framework.loadImageAsPngBase64Async\",function(a){return P().U(a)});\nw(\"dymo.label.framework.createLabelWriterPrintParamsXml\",function(a){if(!a)return\"\";var b=R(\"\"),d=b.documentElement;a.copies&&S(d,\"Copies\",a.copies.toString());a.jobTitle&&S(d,\"JobTitle\",a.jobTitle);a.flowDirection&&S(d,\"FlowDirection\",a.flowDirection);a.printQuality&&S(d,\"PrintQuality\",a.printQuality);a.twinTurboRoll&&S(d,\"TwinTurboRoll\",a.twinTurboRoll);return ie(b)});\nw(\"dymo.label.framework.createTapePrintParamsXml\",function(a){if(!a)return\"\";var b=R(\"\"),d=b.documentElement;a.copies&&S(d,\"Copies\",a.copies.toString());a.jobTitle&&S(d,\"JobTitle\",a.jobTitle);a.flowDirection&&S(d,\"FlowDirection\",a.flowDirection);a.alignment&&S(d,\"Alignment\",a.alignment);a.cutMode&&S(d,\"CutMode\",a.cutMode);return ie(b)});\nw(\"dymo.label.framework.createDZPrintParamsXml\",function(a){if(!a)return\"\";var b=R(\"\"),d=b.documentElement;a.copies&&S(d,\"Copies\",a.copies.toString());a.jobTitle&&S(d,\"JobTitle\",a.jobTitle);a.flowDirection&&S(d,\"FlowDirection\",a.flowDirection);a.alignment&&S(d,\"Alignment\",a.alignment);a.cutMode&&S(d,\"CutMode\",a.cutMode);return ie(b)});\nw(\"dymo.label.framework.createLabelRenderParamsXml\",function(a){function b(a,b){S(e,a,void 0,{Alpha:b.a||b.alpha||255,Red:b.r||b.red||0,Green:b.g||b.green||0,Blue:b.b||b.blue||0})}if(!a)return\"\";var d=R(\"\"),e=d.documentElement;a.labelColor&&b(\"LabelColor\",a.labelColor);a.shadowColor&&b(\"ShadowColor\",a.shadowColor);\"undefined\"!=typeof a.shadowDepth&&S(e,\"ShadowDepth\",a.shadowDepth.toString());a.flowDirection&&S(e,\"FlowDirection\",a.flowDirection);\"undefined\"!=typeof a.pngUseDisplayResolution&&\nS(e,\"PngUseDisplayResolution\",a.pngUseDisplayResolution?\"True\":\"False\");return ie(d)});})();\n\ndefine(\"dymo\", (function (global) {\n return function () {\n var ret, fn;\n return ret || global.dymo;\n };\n}(this)));\n\n","define('modules/contact/sms-service',[\n 'angular',\n 'underscore',\n '../modal/modal-service',\n './modals/send-text-message-modal-ctrl'\n],\nfunction(angular, _) {\n 'use strict';\n\n return angular.module('bl.contact.services.sms', ['bl.modal'])\n .service('Sms', function($rootScope, $modal, Enums, modalService, SMS, MergeFields, Appointment, Transaction, ItemInterest, Quote) {\n\n function hasMultipleFavorites(contacts) {\n return _(contacts).filter(function(contact) {\n return !!(contact.favoriteItemId && contact.favoriteItemImageUrl);\n }).length > 1;\n }\n\n function includesMergeKey(container, value) {\n var returnValue = false;\n var pos = container.indexOf(value);\n if (pos >= 0) {\n returnValue = true;\n }\n return returnValue;\n }\n\n var service = {\n showSendModal: function(contacts, appointment, transaction, itemInterest, successcb, smsOptions, quote) {\n smsOptions = angular.isObject(smsOptions) ? smsOptions : {};\n\n //make sure at least 1 contact has a valid mobile phone number and an smsOptIn\n var validContacts = [];\n var nbrContactsRequested = 0;\n\n //if we get an array, loop through and make sure all are valid\n if (_.isArray(contacts) && contacts.length) {\n nbrContactsRequested = contacts.length;\n\n _.each(contacts, function(contact) {\n if (contact.mobilePhoneNumber) {\n validContacts.push(contact);\n }\n });\n } else if (contacts) {\n //we are receiving a single contact instance\n if (contacts.mobilePhoneNumber) {\n validContacts.push(contacts);\n nbrContactsRequested = 1;\n }\n }\n\n if (validContacts.length) {\n return $modal.open({\n templateUrl: 'js/modules/contact/modals/send-text-message-modal.tpl.html',\n controller: 'ContactSendTextMessageModalCtrl',\n resolve: {\n templates: function(SMSTemplate) {\n return SMSTemplate.query({ filterObject: { status: Enums.statuses.active.value } });\n },\n settings: function(TwilioSettings) {\n return TwilioSettings.get();\n },\n contacts: function() {\n return validContacts;\n },\n some_excluded: function() {\n return validContacts.length !== nbrContactsRequested;\n },\n awsPolicyAndSignature: function(SMS) {\n return SMS.getS3Policy();\n },\n appointment: function() {\n return appointment;\n },\n transaction: function() {\n return transaction;\n },\n quote: function() {\n return quote;\n },\n itemInterest: function() {\n return itemInterest;\n },\n successcb: function() {\n return successcb;\n },\n customOptions: function() {\n _(smsOptions).defaults({\n showOptions: false,\n includeItemImage: false,\n multipleFavorites: hasMultipleFavorites(validContacts),\n agreements: [],\n imageUrl: ''\n });\n\n return smsOptions;\n }\n }\n });\n } else {\n modalService.showMessage('contact.messages.these-contacts-do-not-have-a-mobile-phone-number-or-they-have-not-been-opted-in-to-receive-text-messages');\n }\n },\n showViewModal: function(sms, modalLayout, successcb) {\n $modal.open({\n templateUrl: 'js/modules/contact/modals/view-received-sms-modal.tpl.html',\n controller: 'ViewReceivedSmsModalCtrl',\n resolve: {\n sms: function() {\n return sms;\n },\n templates: function(SMSTemplate) {\n return SMSTemplate.query({ filterObject: { status: Enums.statuses.active.value } });\n },\n settings: function(TwilioSettings) {\n return TwilioSettings.get();\n },\n awsPolicyAndSignature: function(SMS) {\n return SMS.getS3Policy();\n },\n successcb: function() {\n return successcb;\n },\n smss: function(SMS) {\n if(modalLayout === 'one') {\n return [];\n }\n\n return SMS.query({ filterObject: { contactId: sms.contactId }});\n },\n modalLayout: function() {\n return modalLayout;\n }\n }\n });\n },\n open: function(sms, successcb) {\n var openModal = function() {\n return $modal.open({\n templateUrl: 'js/modules/contact/modals/view-received-sms-modal.tpl.html',\n controller: 'ViewReceivedSmsModalCtrl',\n resolve: {\n sms: function() {\n return sms;\n },\n templates: function(SMSTemplate) {\n return SMSTemplate.query({ filterObject: { status: Enums.statuses.active.value }});\n },\n settings: function(TwilioSettings) {\n return TwilioSettings.get();\n },\n awsPolicyAndSignature: function(SMS) {\n return SMS.getS3Policy();\n },\n successcb: function() {\n return successcb;\n },\n smss: function(SMS) {\n return SMS.query({ filterObject: { contactId: sms.contactId }});\n },\n modalLayout: function() {\n return null;\n }\n }\n });\n };\n\n // open by id\n var smsPromise;\n\n if (typeof sms === 'number' && sms > 0) {\n smsPromise = SMS.getById(sms, function(data) {\n sms = data;\n });\n }\n\n return smsPromise ? smsPromise.then(openModal) : openModal();\n },\n openSelectRequiredEntityModal: function(type, contacts, successcb) {\n var buildResolve = function (type, contactId) {\n return {\n appointments: function () {\n if(type !== 'appointment') {\n return null;\n }\n\n return Appointment.query({ filterObject: { contactId: contactId }});\n },\n transactions: function () {\n if(type !== 'transaction') {\n return null;\n }\n\n return Transaction.query({ filterObject: { contactId: contactId }});\n },\n favorites: function () {\n if(type !== 'favorite') {\n return null;\n }\n\n return ItemInterest.listByContactId(contactId);\n },\n quotes: function () {\n if(type !== 'quote') {\n return null;\n }\n\n return Quote.query({ filterObject: { contactId: contactId }});\n },\n entityType: function () {\n return type;\n }\n };\n };\n\n var contactId = null;\n\n if (_.isArray(contacts) && contacts.length === 1) {\n contactId = contacts[0].id;\n } else if (_.isObject(contacts)) {\n contactId = contacts.id;\n } else if(contacts) {\n contactId = contacts;\n }\n\n if(contactId) {\n $modal.open({\n templateUrl: 'js/modules/contact/modals/select-required-entity-for-message-modal.tpl.html',\n controller: 'SelectRequiredEntityForMessageModalCtrl',\n resolve: buildResolve(type, contactId),\n windowClass: '__large'\n }).result.then(function(result) {\n successcb(result);\n });\n }\n },\n entityTypes: {\n 'favorite':'selectedFavorite',\n 'appointment':'selectedAppointment',\n 'transaction':'selectedTransaction',\n 'quote':'selectedQuote'\n },\n smsMessageCount: 1600,\n uploadImage: function(index, fileObj, awsPolicyAndSignature, successcb, errorcb) {\n if(awsPolicyAndSignature && awsPolicyAndSignature.errorMessage) {\n modalService.showMessage(awsPolicyAndSignature.errorMessage, 'modal-service.error');\n return;\n }\n\n var imageObj = fileObj;\n\n var uploadProgress = function(event, index) {\n $rootScope.$apply(function() {\n if (!imageObj) {\n return;\n }\n\n var picture = imageObj;\n picture._ui.status = 'uploading';\n picture._ui.percentage = Math.round((event.loaded / event.total) * 100);\n });\n };\n\n var uploadAbort = function(event, file) {\n //\n };\n\n var uploadError = function(event, index) {\n $rootScope.$apply(function() {\n imageObj._ui.status = 'error';\n });\n };\n\n var uploadComplete = function(event, index) {\n $rootScope.$apply(function() {\n var picture = imageObj;\n if (picture._ui.status !== 'error') {\n picture._ui.percentage = 100;\n picture._ui.status = 'done';\n }\n });\n };\n\n var picture = imageObj;\n\n var formData = new FormData();\n var key = 'uploads/' + new Date().valueOf() + '-' + picture._ui.file.name;\n\n // Populate the POST parameters.\n formData.append('key', key);\n formData.append('acl', 'private');\n formData.append('Content-Type', picture._ui.file.type);\n formData.append('AWSAccessKeyId', awsPolicyAndSignature.accessKeyId);\n formData.append('policy', awsPolicyAndSignature.policy);\n formData.append('signature', awsPolicyAndSignature.signature);\n formData.append('file', picture._ui.file);\n\n picture._ui.xhr = new XMLHttpRequest();\n\n //register upload progress event listener\n picture._ui.xhr.upload.addEventListener('progress', function(event) {\n uploadProgress(event, index);\n }, false);\n\n picture._ui.xhr.addEventListener('load', function(event) {\n uploadComplete(event, index);\n }, false);\n\n picture._ui.xhr.addEventListener('error', function(event) {\n uploadError(event, index);\n }, false);\n\n picture._ui.xhr.addEventListener('abort', function(event) {\n uploadAbort(event, index);\n }, false);\n\n picture._ui.xhr.onload = function() {\n\n // Special status for S3 uploads. Link is in Location header\n if (this.status === 204) {\n var url = this.getResponseHeader('Location');\n\n $rootScope.$apply(function() {\n var picture = imageObj;\n picture.imageUrl = url;\n picture._ui.status = 'done';\n\n if(successcb) {\n successcb(picture);\n }\n\n });\n } else {\n var errorMessage;\n if (this.responseXML && this.responseXML.getElementsByTagName(\"Message\")\n && this.responseXML.getElementsByTagName(\"Message\").length > 0) {\n errorMessage = this.responseXML.getElementsByTagName(\"Message\")[0].innerHTML;\n }\n\n //some error occurred\n $rootScope.$apply(function() {\n picture = imageObj;\n picture._ui.status = 'error';\n picture._ui.errorMessage = errorMessage;\n });\n\n if(errorcb) {\n errorcb(picture);\n }\n }\n };\n\n // Send file to S3\n picture._ui.xhr.open('POST', 'https://' + awsPolicyAndSignature.bucketName + '.s3.amazonaws.com', true);\n picture._ui.xhr.send(formData);\n },\n uploadImageWithPreSignedURL: function(file, user, Resource, successcb, errorcb) {\n var image = file;\n\n Resource.getS3PreSignedURL({\n objectKey: 'uploads/' + new Date().valueOf() + '-' + image._ui.file.name,\n contentType: image._ui.file.type,\n employeeId: user.id\n }, function(details) {\n var uploadProgress = function(event) {\n $rootScope.$apply(function() {\n if(!image) {\n return;\n }\n\n var picture = image;\n picture._ui.status = 'uploading';\n picture._ui.percentage = Math.round((event.loaded / event.total) * 100);\n });\n };\n\n var uploadError = function() {\n $rootScope.$apply(function() {\n image._ui.status = 'error';\n });\n };\n\n var uploadComplete = function() {\n $rootScope.$apply(function() {\n var picture = image;\n if(picture._ui.status !== 'error') {\n picture._ui.percentage = 100;\n picture._ui.status = 'done';\n }\n });\n };\n\n var picture = image;\n\n var formData = new FormData();\n\n // Populate the POST parameters.\n formData.append('file', picture._ui.file);\n formData.append('acl', 'private');\n formData.append('Content-Type', picture._ui.file.type);\n picture._ui.xhr = new XMLHttpRequest();\n\n //register upload progress event listener\n picture._ui.xhr.upload.addEventListener('progress', function(event) {\n uploadProgress(event);\n }, false);\n\n picture._ui.xhr.addEventListener('load', function(event) {\n uploadComplete(event);\n }, false);\n\n picture._ui.xhr.addEventListener('error', function(event) {\n uploadError(event);\n }, false);\n\n picture._ui.xhr.onload = function() {\n // Special status for S3 uploads. Link is in Location header\n if(this.status === 204) {\n var url = this.getResponseHeader('Location');\n\n $rootScope.$apply(function() {\n var picture = image;\n picture.imageUrl = url;\n picture._ui.status = 'done';\n\n if(successcb) {\n successcb(picture);\n }\n\n });\n } else {\n var errorMessage;\n if(this.responseXML && this.responseXML.getElementsByTagName(\"Message\") && this.responseXML.getElementsByTagName(\"Message\").length > 0) {\n errorMessage = this.responseXML.getElementsByTagName(\"Message\")[0].innerHTML;\n }\n\n //some error occurred\n $rootScope.$apply(function() {\n picture = image;\n picture._ui.status = 'error';\n picture._ui.errorMessage = errorMessage;\n });\n\n if(errorcb) {\n errorcb(picture);\n }\n }\n };\n\n // Send file to S3 with presign url\n picture._ui.xhr.open('POST', details.preSignedURL, true);\n // picture._ui.xhr.setRequestHeader(\"Access-Control-Allow-Origin\", \"*\");\n picture._ui.xhr.send(formData);\n });\n },\n checkMessageForMergeKeys: function(message, selectedAppointment, selectedTransaction, selectedFavorite, selectedQuote) {\n var apptMergeFields = _.where(MergeFields, { appointmentRequired: true });\n var trxMergeFields = _.where(MergeFields, { transactionRequired: true });\n var itemInterestMergeFields = _.where(MergeFields, { itemInterestRequired: true });\n var quoteMergeFields = _.where(MergeFields, { quoteRequired: true });\n var optionalFields = _.where(MergeFields, { optional: true });\n var isAppointmentRequired = false;\n var isTransactionRequired = false;\n var isFavoriteRequired = false;\n var isQuoteRequired = false;\n var isOptional = false;\n\n var includesValue = function(container, value) {\n\n var returnValue = false;\n var pos = container.indexOf(value);\n if (pos >= 0) {\n returnValue = true;\n }\n return returnValue;\n };\n\n if(optionalFields.length) {\n _.each(optionalFields, function(mergeField) {\n if(includesValue(message, mergeField.key)){\n isOptional = true;\n }\n });\n }\n\n if(itemInterestMergeFields.length) {\n var itemInterestMergeFieldsCount = 0;\n _.each(itemInterestMergeFields, function(mergeField) {\n if(includesValue(message, mergeField.key)){\n isFavoriteRequired = selectedFavorite && selectedFavorite.id ? false : true;\n itemInterestMergeFieldsCount++;\n }\n });\n\n if(itemInterestMergeFieldsCount < 1) {\n isFavoriteRequired = false;\n }\n }\n\n if(apptMergeFields.length) {\n var apptMergeFieldsCount = 0;\n _.each(apptMergeFields, function(mergeField) {\n if(includesValue(message, mergeField.key)){\n isAppointmentRequired = selectedAppointment && selectedAppointment.id ? false : true;\n apptMergeFieldsCount++;\n }\n });\n\n if(apptMergeFieldsCount < 1) {\n isAppointmentRequired = false;\n }\n }\n\n if(quoteMergeFields.length) {\n var quoteMergeFieldsCount = 0;\n _.each(quoteMergeFields, function(mergeField) {\n if(includesValue(message, mergeField.key)){\n isQuoteRequired = selectedQuote && selectedQuote.id ? false : true;\n quoteMergeFieldsCount++;\n }\n });\n\n if(quoteMergeFieldsCount < 1) {\n isQuoteRequired = false;\n }\n }\n\n if(trxMergeFields.length) {\n var trxMergeFieldsCount = 0;\n _.each(trxMergeFields, function(mergeField) {\n if(includesValue(message, mergeField.key)){\n isTransactionRequired = selectedTransaction && selectedTransaction.id ? false : true;\n trxMergeFieldsCount++;\n }\n });\n\n if(trxMergeFieldsCount < 1) {\n isTransactionRequired = false;\n }\n\n //Should this be out of the trxMergeFields if stmt??\n return {\n appointment: isAppointmentRequired,\n transaction: isTransactionRequired,\n quote: isQuoteRequired,\n favorite: isFavoriteRequired,\n optional: isOptional\n };\n\n }\n },\n hasSendOnlyKeys: function(message) {\n var sendOnlyKeys = _(MergeFields).where({ sendOnly: true });\n var sendOnly = false;\n if(message && message.length && sendOnlyKeys && sendOnlyKeys.length) {\n for(var i = 0; i < sendOnlyKeys.length; i++) {\n var mergeKey = sendOnlyKeys[i];\n\n if(mergeKey && mergeKey.key && includesMergeKey(message, mergeKey.key)) {\n sendOnly = true;\n break;\n }\n }\n }\n return sendOnly;\n },\n updateMessageCounter: function(messageLength) {\n var MESSAGE_COUNT_TOTAL = service.smsMessageCount;\n return MESSAGE_COUNT_TOTAL - messageLength;\n }\n };\n\n return service;\n });\n });\n\n","define('modules/calendar/fitting-room/fitting-room',['../module', 'underscore', 'jquery'], function (module, _, $) {\n 'use strict';\n\n module.controller('CalendarFittingRoomCtrl', function (\n $scope,\n $stateParams,\n $locale,\n $filter,\n $translate,\n $rootScope,\n $timeout,\n $modal,\n Permissions,\n CALENDAR_EVENTS,\n FittingRoomService,\n AppointmentType,\n FittingRoomAppointmentType,\n AppointmentBlock,\n alerts,\n AppLicense,\n Enums,\n FullcalendarHelper,\n ResourcesHelper,\n AppointmentHelper,\n Appointment,\n fittingRooms,\n settings,\n AppointmentModal,\n ActiveCalendarManager,\n LayoutEventsService,\n calendarUi,\n security\n ) {\n\n var SETTINGS = {\n UNASSIGNED: _(settings).findWhere({ type: 'AC_HIDE_UNASSIGNED_FITTING_ROOM' })\n };\n\n var rooms = _(fittingRooms).map(function(room) {\n return room;\n });\n \n fittingRooms = _.sortBy(fittingRooms, function(room) {\n return room.sequence;\n });\n\n fittingRooms = ResourcesHelper.adaptList('fittingRooms', fittingRooms, SETTINGS.UNASSIGNED);\n\n if(security.hasPermission(Permissions.SETTINGS_AC)) {\n fittingRooms = _(fittingRooms).map(function(room) {\n if(room.id) {\n room.name = '' + room.name + '';\n }\n return room;\n });\n }\n\n var updateHeight, isDateWasChangedExternally, blockCalendarCurrentDateWatcher;\n $scope.events = [];\n $scope.eventSources = [$scope.events];\n $rootScope.dayView = true;\n $rootScope.calendar_view = 'fittingRoom';\n\n function fittingRoomClicked(event) {\n var target = event && event.currentTarget;\n\n if(target && target.dataset) {\n var room = _(rooms).findWhere({ id: +target.dataset.fittingRoomId });\n if(room && room.id) {\n $scope.onSetupClick(room);\n }\n }\n }\n\n $scope.init = function () {\n $scope.uiConfig = {\n calendar: {\n monthNames: $translate.instant('calendar.month-names').split(','),\n monthNamesShort: $translate.instant('calendar.month-names-short').split(','),\n dayNames: $translate.instant('calendar.day-names').split(','),\n dayNamesShort: $translate.instant('calendar.day-names-short').split(','),\n buttonText: {\n today: $translate.instant('calendar.today'),\n month: $translate.instant('calendar.month'),\n week: $translate.instant('calendar.week'),\n day: $translate.instant('calendar.day'),\n prev: '',\n next: ''\n },\n defaultView: 'resourceDay',\n resources: fittingRooms,\n editable: isEditable(security),\n disableResizing: isResizable(security),\n firstHour: 8,\n header: {\n left: 'prev,next today',\n center: 'title',\n right: ''\n },\n titleFormat: {\n month: $locale.DATETIME_FORMATS.calendarMonth,\n week: $locale.DATETIME_FORMATS.calendarWeek,\n day: $locale.DATETIME_FORMATS.calendarDay\n },\n columnFormat: {\n month: $locale.DATETIME_FORMATS.calendarColumnFormat.month,\n week: $locale.DATETIME_FORMATS.calendarColumnFormat.week,\n day: $locale.DATETIME_FORMATS.calendarColumnFormat.day\n },\n timeFormat: { // for event elements\n '': $locale.DATETIME_FORMATS.calendarTimeFormat// default\n },\n axisFormat: $locale.DATETIME_FORMATS.calendarAxisFormat,\n height: 9000, // set big number, it does not expand farther\n year: $scope.calendarCurrentDate.getFullYear(),\n month: $scope.calendarCurrentDate.getMonth(),\n date: $scope.calendarCurrentDate.getDate(),\n dayClick: $scope.onDayClick,\n eventClick: $scope.onEventClick,\n eventDragStart: function (event) {\n ActiveCalendarManager.saveEvent(event);\n FullcalendarHelper.doNotShowPopovers();\n },\n eventResizeStart: function (event) {\n ActiveCalendarManager.saveEvent(event);\n FullcalendarHelper.doNotShowPopovers();\n },\n eventResize: AppointmentHelper.generateEventHandler('resize', 'fitting-room'),\n windowResize: function (view) {\n ActiveCalendarManager.setView(view);\n FullcalendarHelper.adjustAvailableTimeSlotPositions(view);\n FullcalendarHelper.adjustFittingRoomSlotPositions(view);\n },\n eventDrop: AppointmentHelper.generateEventHandler('drop', 'fitting-room'),\n slotEventOverlap: false,\n viewDisplay: function(view) {\n ActiveCalendarManager.setView(view);\n addFittingRoomClickEvent();\n var currentDate = FullcalendarHelper.getDate($scope.myCalendar);\n FullcalendarHelper.setSelectedDate(currentDate);\n\n if(!isDateWasChangedExternally) {\n $scope.setCalendarCurrentDate(currentDate);\n }\n\n isDateWasChangedExternally = false;\n blockCalendarCurrentDateWatcher = true;\n FullcalendarHelper.allowPopovers = false;\n\n // Setup height updater\n if(updateHeight) {\n LayoutEventsService.off('resize', updateHeight);\n }\n\n updateHeight = calendarUi.getHeightUpdater(view);\n LayoutEventsService.on('resize', updateHeight);\n updateHeight();\n\n // Add Current Time - Timeline\n $timeout(function() {\n FullcalendarHelper.setTimeline(view, $scope.myCalendar);\n });\n\n Appointment.listCalendarEvents(\n view.start,\n view.end,\n function (appointments) {\n var events = _(appointments).map(function (item, index) {\n return FullcalendarHelper.generateFullcalendarEventObject(item, index, 'fitting-room');\n });\n\n FullcalendarHelper.updateEvents($scope.myCalendar, events);\n FullcalendarHelper.allowPopovers = true;\n\n ActiveCalendarManager.init($scope.events, 'fitting-room');\n ActiveCalendarManager.loadTodaysNotes(currentDate);\n }\n );\n\n FullcalendarHelper.showBlackOutDates(view);\n },\n viewDestroy: function () {\n LayoutEventsService.off('resize', updateHeight);\n removeFittingRoomClickEvent();\n FullcalendarHelper.removeTimeline();\n },\n eventRender: function (event) {\n if(event.appointment.status !== Enums.statuses.pending.value) {\n event.editable = false;\n }\n },\n eventAfterRender: FullcalendarHelper.addPopover\n }\n };\n\n // Force state re-initialization when url user clicks the same url\n delete $stateParams.date;\n\n $scope.$watch('calendarCurrentDate', function (value, oldValue) {\n if(value && value !== oldValue && !blockCalendarCurrentDateWatcher) {\n isDateWasChangedExternally = true;\n $scope.myCalendar.fullCalendar('gotoDate', value);\n }\n\n blockCalendarCurrentDateWatcher = false;\n });\n };\n\n /**\n * Display Helper Events\n */\n\n $rootScope.$on(CALENDAR_EVENTS.DISPLAY_FITTING_ROOM_BLOCKS, function(event, data) {\n var view = FullcalendarHelper.getView($scope.myCalendar);\n FullcalendarHelper.showFittingRoomBlocks(view, fittingRooms, data);\n });\n\n $rootScope.$on(CALENDAR_EVENTS.DISPLAY_AVAILABLE_TIME_BLOCKS, function(event, data) {\n var view = FullcalendarHelper.getView($scope.myCalendar);\n FullcalendarHelper.showAllAvailableTimeSlots(view, fittingRooms, data);\n });\n\n $rootScope.$on(CALENDAR_EVENTS.DISPLAY_STORE_HOURS, function(event, data) {\n var c = data && data.company;\n var view = FullcalendarHelper.getView($scope.myCalendar);\n FullcalendarHelper.showStoreHourBlocks(view, c, false);\n });\n\n $rootScope.$on(CALENDAR_EVENTS.DISPLAY_NON_STORE_HOURS, function(event, data) {\n var c = data && data.company;\n var view = FullcalendarHelper.getView($scope.myCalendar);\n FullcalendarHelper.showStoreHourBlocks(view, c, true);\n });\n\n $scope.onDayClick = function (date, allDay, js_event, resource) {\n if(security && !security.hasPermission('ADD_APPOINTMENT')) {\n return;\n }\n\n if(resource) {\n AppointmentModal.openAdd(date, allDay, null, {\n resourceId: resource.id\n });\n }\n };\n\n $scope.onSetupClick = function(room) {\n FittingRoomService.openSetupModal(room);\n };\n\n $scope.onEventClick = function (event) {\n if(!security.hasPermission('VIEW_APPOINTMENTS')) {\n return;\n }\n\n var modalPromise = AppointmentModal.openEdit(event, event.appointment);\n modalPromise.result.then(function () {\n if (event.isRemoving) {\n FullcalendarHelper.removeEvents($scope.myCalendar, event._id);\n } else {\n $scope.myCalendar.fullCalendar('updateEvent', event);\n }\n });\n };\n\n $scope.$watch('myCalendar', function (element) {\n if(element) {\n ActiveCalendarManager.calendar = element;\n setCalendarElementClass();\n }\n });\n\n $scope.init();\n\n function addFittingRoomClickEvent() {\n try {\n $('.bl-fitting-room-header').bind('click', fittingRoomClicked).bind('keyup', fittingRoomClicked);\n } catch(e) {\n console.log('Failed to add click event', e);\n }\n }\n\n function removeFittingRoomClickEvent() {\n try {\n $('.bl-fitting-room-header').unbind('click', fittingRoomClicked).unbind('keyup', fittingRoomClicked);\n } catch(e) {\n console.log('Failed to remove click event', e);\n }\n }\n\n function setCalendarElementClass() {\n if (setCalendarElementClass.lengthUsed) {\n $scope.myCalendar.removeClass('__' + setCalendarElementClass.lengthUsed);\n }\n\n setCalendarElementClass.lengthUsed = fittingRooms.length;\n $scope.myCalendar.addClass('__' + fittingRooms.length);\n }\n\n function isEditable(security) {\n if(!security) {\n return true;\n }\n\n return security.hasPermission('EDIT_APPOINTMENT_FITTING_ROOM') && security.hasPermission('EDIT_APPOINTMENT_DATE');\n }\n\n function isResizable(security) {\n if(!security) {\n return false;\n }\n\n return !security.hasPermission('EDIT_APPOINTMENT_DURATION');\n }\n });\n});\n\n","define('modules/common/directives',[\n 'angular',\n 'jquery',\n 'underscore',\n 'moment'\n], function (angular, $, _, moment) {\n return angular.module('bl.directives', [])\n\n /**\n * Focus Me directive based on boolean value\n */\n\n .directive('focusMe', function ($timeout, $parse) {\n return {\n link: function (scope, element, attrs) {\n var model = $parse(attrs.focusMe);\n scope.$watch(model, function (value) {\n if (value === true) {\n $timeout(function () {\n element[0].focus();\n });\n }\n });\n\n // element.bind('blur', function () {\n // scope.$apply(model.assign(scope, false));\n // });\n }\n };\n })\n\n /**\n * Email Validation\n */\n .directive('validateEmail', function(ValidationService) {\n //var EMAIL_REGEXP = /^[_a-z0-9]+(\\.[_a-z0-9]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,})$/;\n return {\n require: 'ngModel',\n link: function($scope, $element, $attrs, ngModel) {\n $element.on('keyup',function() {\n //var isMatchRegex = EMAIL_REGEXP.test($element.val());\n var isMatchRegex = ValidationService.validateEmail($element.val());\n if(isMatchRegex && $element.hasClass('has-error is-focused invalid-email') || $element.val() === '') {\n $element.removeClass('has-error is-focused invalid-email');\n } else if(isMatchRegex === false && !$element.hasClass('has-error is-focused invalid-email')) {\n $element.addClass('has-error is-focused invalid-email');\n }\n });\n }\n };\n })\n\n /**\n * URL Validation\n */\n .directive('validateUrl', function() {\n var URL_REGEXP = /((([A-Za-z]{3,9}:(?:\\/\\/)?)(?:[-;:&=\\+\\$,\\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\\+\\$,\\w]+@)[A-Za-z0-9.-]+)((?:\\/[\\+~%\\/.\\w-_]*)?\\??(?:[-\\+=&;%@.\\w_]*)#?(?:[\\w]*))?)/;\n return {\n require: 'ngModel',\n link: function($scope, $element) {\n $element.on('keyup',function() {\n var isMatchRegex = URL_REGEXP.test($element.val());\n if(isMatchRegex && $element.hasClass('has-error is-focused invalid-url') || $element.val() === '') {\n $element.removeClass('has-error is-focused invalid-url');\n } else if(isMatchRegex === false && !$element.hasClass('has-error is-focused invalid-url')) {\n $element.addClass('has-error is-focused invalid-url');\n }\n });\n }\n };\n })\n\n /**\n * Add 'tabindex' attribute to all input/textarea/select/button\n * inside given element\n *\n * Usefull when there a datepicker in the form and we want to\n * prevent tabbing across all days in it\n */\n .directive('autoTabindex', function () {\n return function (scope, element, attrs) {\n element.find('input, textarea, select, button').each(function (i, el) {\n $(el).attr('tabindex', i + 1);\n });\n };\n })\n\n /**\n * Binds filter value with more intelligent watch which fires only when actual value change happened,\n * in contrast to filters which fire on each digest.\n *\n * @example:\n * \n */\n .directive('filter', function ($filter) {\n return {\n restrict: 'A',\n link: function (scope, elem, attrs) {\n if (!attrs.hasOwnProperty('filter')) {\n return console.error('Filter name expected, got: ' + attrs.filter);\n }\n\n if (!attrs.hasOwnProperty('filterValue')) {\n return console.error('Filter value expected, got: ' + attrs.filterValue);\n }\n\n var filter = $filter(attrs.filter);\n\n attrs.$observe('filterValue', function (newValue) {\n elem.html(filter(newValue, attrs.filterParam) || attrs.filterDefault);\n });\n }\n };\n })\n\n /**\n * Alternative to the autofocus attribute, which doesn't\n * seem to work inside modals.\n */\n .directive('focus', function ($timeout) {\n return function (scope, element, attrs) {\n var isInsideModal = !!element.parents('.modal-body').length;\n var duration = isInsideModal ? 500 : 0;\n var doSelectText = scope.$eval(attrs.focus);\n\n $timeout(function () {\n element.focus();\n\n if (doSelectText) {\n element.get(0).select();\n }\n }, duration, false);\n };\n })\n\n /**\n * Fix validation for type=\"number\"\n * https://groups.google.com/d/msg/angular/pRc5pu3bWQ0/4yxCdCz1JeMJ\n */\n .directive('proxyValidity', function ($timeout) {\n return {\n require: 'ngModel',\n link: function ($scope, $element, $attrs, modelCtrl) {\n if ($element.prop('validity') === undefined) {\n return;\n }\n\n $element.on('input', function () {\n $timeout(function () {\n modelCtrl.$setValidity('$invalid', !$element.prop('validity').badInput);\n });\n });\n }\n };\n })\n\n .directive('uploadOnChange', function() {\n return {\n restrict: 'A',\n link: function (scope, element, attrs) {\n var onChangeFunc = scope.$eval(attrs.uploadOnChange);\n element.bind('change', onChangeFunc);\n }\n };\n })\n\n .directive('eventTypeIcon', function () {\n return {\n restrict: 'AE',\n scope: {},\n link: function (scope, element, attrs) {\n var typeMap = {\n 1: '__ring event-type-icon',\n 2: '__group event-type-icon',\n 3: '__dress event-type-icon',\n 4: '__dress event-type-icon',\n 5: '__dress event-type-icon',\n 6: '__dress event-type-icon',\n 7: '__shirt event-type-icon',\n 8: '__birthday-cake event-type-icon',\n 9: '__circle-question-mark event-type-icon'\n };\n\n var typeClass = typeMap[attrs.eventTypeIcon];\n\n element.addClass('glyphicon');\n element.addClass('glyphic');\n element.addClass(typeClass);\n }\n };\n })\n\n .directive('timelineItemIcon', function () {\n return {\n restrict: 'AE',\n scope: {},\n link: function (scope, element, attrs) {\n var typeMap = {\n A: 'timeline-icon-calendar glyphic __calendar',\n T: 'timeline-icon-register ftic __cashregister',\n M: 'timeline-icon-measurements ftic __measuring-tape',\n MR: 'timeline-icon-measurements ftic __measuring-tape',\n ER: 'timeline-icon-group glyphic __group',\n EU: 'timeline-icon-group glyphic __group',\n CUR: 'timeline-icon-user glyphic __user'\n };\n\n var typeClass = typeMap[attrs.timelineItemIcon];\n\n element.addClass('glyphicon');\n element.addClass(typeClass);\n }\n };\n })\n\n .directive('fadeOnChange', function($timeout) {\n return {\n restrict: 'A',\n link: function (scope, element, attrs) {\n scope.$watch(attrs.fadeOnChange, function(nv, ov) {\n if (nv !== ov) {\n $timeout(function() {\n element.fadeOut(500);\n $timeout(function () {\n element.fadeIn(500);\n }, 1000);\n }, 4500);\n }\n });\n }\n };\n })\n\n .directive('statusIcon', function () {\n return {\n restrict: 'AE',\n scope: {},\n link: function (scope, element, attrs) {\n var statusMap = {\n P: 'glyphicon-time',\n C: 'glyphicon-ok',\n A: 'glyphicon-ok',\n N: 'glyphicon-thumbs-down',\n L: 'glyphicon-remove',\n V: 'glyphicon-remove'\n };\n\n var statusClass = statusMap[attrs.statusIcon];\n\n element.addClass('glyphicon');\n element.addClass(statusClass);\n }\n };\n })\n\n .directive('trxItemStatusIcon', function (Enums) {\n return {\n restrict: 'AE',\n scope: {},\n link: function (scope, element, attrs) {\n if (attrs.trxItemStatusIcon) {\n var status = _.findWhere(Enums.trxItemStatuses, { value: attrs.trxItemStatusIcon });\n if (status) {\n element.addClass('glyphicon');\n element.addClass(status.icon);\n }\n }\n }\n };\n })\n\n .directive('paymentStatusIcon', function () {\n return {\n restrict: 'AE',\n scope: {},\n link: function (scope, element, attrs) {\n var statusMap = {\n P: 'glyphicon-usd',\n C: 'glyphicon-usd',\n V: 'glyphicon-remove'\n };\n\n var statusClass = statusMap[attrs.paymentStatusIcon];\n\n element.addClass('glyphicon');\n element.addClass(statusClass);\n }\n };\n })\n\n .directive('currencyInput', function ($filter, $timeout, $locale) {\n return {\n restrict: 'A',\n require: '?ngModel',\n link: function (scope, element, attrs, ngModel) {\n /**\n * Handlers\n */\n\n element.on('focus', function () {\n\n //if the user clicks into the input and the decimal separator is not a '.',\n //then replace the '.' with the locale's decimal separator\n\n if($locale.NUMBER_FORMATS.DECIMAL_SEP !== '.') {\n ngModel.$viewValue = !ngModel.$modelValue ? '' : ngModel.$modelValue.toString().replace('.', $locale.NUMBER_FORMATS.DECIMAL_SEP);\n } else {\n ngModel.$viewValue = !ngModel.$modelValue ? '' : ngModel.$modelValue;\n }\n\n ngModel.$render(true);\n\n });\n\n element.on('blur', function () {\n var filteredValue = $filter('currency')(ngModel.$modelValue);\n if (filteredValue) {\n ngModel.$viewValue = filteredValue;\n ngModel.$render(true);\n }\n });\n\n element.on('keypress', function (event) {\n var code = event.which || event.keyCode;\n var char = String.fromCharCode(code);\n var allowedKeys = [8, 9, 13, 27, 37, 38, 39, 40, 44, 188];\n\n if (allowedKeys.indexOf(code) === -1 && !event.ctrlKey && !event.metaKey && !/-|\\d|\\./.test(char)) {\n event.preventDefault();\n }\n });\n\n ngModel.$render = function (isInternalChange) {\n element.val(ngModel.$viewValue);\n\n if (!isInternalChange) {\n element.blur();\n }\n };\n\n ngModel.$parsers.unshift(function (value) {\n // Convert value to string if it's a number\n if(_.isNumber(value)) {\n value += '';\n }\n\n // After updating Angular to 1.3 values with applied filter(currency) might appear here(on form submit)\n // so we need parse filtered value first\n var valueToParse = value.replace($locale.NUMBER_FORMATS.CURRENCY_SYM, '')\n .replace($locale.NUMBER_FORMATS.GROUP_SEP, '')\n .replace($locale.NUMBER_FORMATS.DECIMAL_SEP, '.'); //if this locale doesn't use a . for decimal separator\n\n var negativeNumberRegexp = /^\\(([^)]+)\\)$/g;\n var isNegative = negativeNumberRegexp.exec(valueToParse);\n\n if (isNegative && isNegative[1]) {\n valueToParse = '-' + isNegative[1];\n }\n\n if(valueToParse === \"\") {\n valueToParse = \"0\";\n }\n\n value = parseFloat(valueToParse).toFixed(2);\n\n if(ngModel.$name !== 'retail-price') {\n ngModel.$setValidity('$invalid', !!$filter('currency')(value));\n }\n\n return parseFloat(value) || 0;\n });\n\n scope.$on('$localeChangeSuccess', function () {\n element.trigger('blur');\n });\n\n /**\n * Init\n */\n\n $timeout(function () {\n element.trigger('blur');\n });\n }\n };\n })\n\n .directive('integer', function () {\n return {\n restrict: 'A',\n link: function (scope, element, attrs) {\n element.on('keypress', function (event) {\n if (scope.$eval(attrs.integer) === false) {\n return;\n }\n\n var code = event.which || event.keyCode;\n var char = String.fromCharCode(code);\n var allowedKeys = [8, 9, 13, 27, 37, 38, 39, 40];\n\n if (allowedKeys.indexOf(code) === -1 && !event.ctrlKey && !event.metaKey && !/\\d/.test(char)) {\n event.preventDefault();\n }\n });\n }\n };\n })\n\n .directive('measurementsInteger', function () {\n return {\n restrict: 'A',\n require: \"?ngModel\",\n scope: {\n model: '=ngModel'\n },\n link: function (scope, element, attrs) {\n element.on('keypress', function (event) {\n if (scope.$eval(attrs.measurementsInteger) === false) {\n return;\n }\n\n var code = event.which || event.keyCode;\n var char = String.fromCharCode(code);\n var allowedKeys = [8, 9, 13, 27, 37, 38, 39, 40, 46];\n\n if(scope.model && scope.model.length) {\n for(var i = 0; i < scope.model.length; i++) {\n if((char === '.' && '.' === scope.model[i])) {\n event.preventDefault();\n }\n }\n }\n\n if (allowedKeys.indexOf(code) === -1 && !event.ctrlKey && !event.metaKey && !/\\d/.test(char)) {\n event.preventDefault();\n }\n });\n }\n };\n })\n\n .directive('monthYear', function () {\n return {\n restrict: 'A',\n link: function (scope, element, attrs) {\n element.on('keypress', function (event) {\n if (scope.$eval(attrs.monthYear) === false) {\n return;\n }\n\n var code = event.which || event.keyCode;\n var char = String.fromCharCode(code);\n var allowedKeys = [8, 9, 13, 27, 37, 38, 39, 40];\n\n if (allowedKeys.indexOf(code) === -1 && !event.ctrlKey && !event.metaKey && !/\\d/.test(char)) {\n event.preventDefault();\n }\n });\n }\n };\n })\n\n .directive('float', function () {\n return {\n restrict: 'A',\n link: function (scope, element) {\n element.on('keypress', function (event) {\n var code = event.which || event.keyCode;\n var char = String.fromCharCode(code);\n var allowedKeys = [8, 9, 13, 27, 37, 38, 39, 40];\n\n if (allowedKeys.indexOf(code) === -1 && !event.ctrlKey && !event.metaKey && !/\\d|\\./.test(char)) {\n event.preventDefault();\n }\n });\n }\n };\n })\n\n .directive('percentageInput', function ($filter, $timeout, $locale) {\n return {\n restrict: 'A',\n require: '?ngModel',\n link: function (scope, element, attrs, ngModel) {\n /**\n * Handlers\n */\n\n element.on('blur', function () {\n var modelValue = ngModel.$modelValue + '';\n var filteredValue = $filter('number')(ngModel.$modelValue, 2);\n filteredValue = parseFloat(filteredValue);\n\n if(modelValue.indexOf('.') === -1) {\n filteredValue = modelValue;\n }\n\n if(filteredValue || filteredValue === 0) {\n ngModel.$viewValue = filteredValue;\n ngModel.$render(true);\n }\n });\n\n element.on('keypress', function (event) {\n var code = event.which || event.keyCode;\n var char = String.fromCharCode(code);\n var allowedKeys = [8, 9, 13, 27, 37, 38, 39, 40, 44, 188];\n\n if (allowedKeys.indexOf(code) === -1 && !event.ctrlKey && !event.metaKey && !/\\d|\\./.test(char)) {\n event.preventDefault();\n }\n });\n\n ngModel.$render = function(isInternalChange) {\n element.val(ngModel.$viewValue);\n\n if(!isInternalChange) {\n element.blur();\n }\n };\n\n ngModel.$parsers.unshift(function (value) {\n // Validate value\n if(!value || value < 0 || value > 100) {\n value = 0;\n }\n\n // Convert value to string if it's a number\n var valueToParse = '' + value;\n\n if(valueToParse === \"\") {\n valueToParse = \"0\";\n }\n\n if(valueToParse.indexOf('.') === 1) {\n value = parseFloat(valueToParse).toFixed(2);\n }\n\n ngModel.$setValidity('$invalid', !!$filter('number')(value, 2));\n return parseFloat(value) || 0;\n });\n\n /**\n * Init\n */\n\n $timeout(function () {\n element.trigger('blur');\n });\n }\n };\n })\n\n .directive('changeOnEnter', function ($document) {\n return function (scope, element) {\n var triggerChangeOnEnter = function (event) {\n var code = event.which || event.keyCode;\n var $focused = element.find('input:focus').filter(function () {\n // Omit directives\n if (\n this.hasAttribute('data-datepicker-popup') ||\n this.hasAttribute('datepicker-popup') ||\n this.hasAttribute('data-typeahead') ||\n this.hasAttribute('typeahead') ||\n this.hasAttribute('item-search-typeahead-grid-on-select') ||\n this.hasAttribute('change-on-enter-ignore')\n ) {\n return false;\n }\n\n return true;\n });\n\n // On enter detection\n if (code === 13 && $focused.length) {\n $focused.change().blur();\n }\n };\n\n $document.on('keydown', triggerChangeOnEnter);\n\n // Remove handler on scope destroy\n scope.$on('$destroy', function () {\n $document.off('keydown', triggerChangeOnEnter);\n });\n };\n })\n\n .directive(\"toFixedNumber\", function ($timeout) {\n return {\n replace: false,\n restrict: \"A\",\n require: \"?ngModel\",\n scope: {\n model: '=ngModel'\n },\n link: function (scope, element, attrs, ngModel) {\n var digitsAfterDecimalPoint = scope.$eval(attrs.toFixedNumber) || 1;\n\n /**\n * Handlers\n */\n\n element.on('focus', function () {\n ngModel.$viewValue = ngModel.$modelValue === 0 ? '' : ngModel.$modelValue;\n ngModel.$render(true);\n\n });\n\n element.on('blur', function () {\n var filteredValue = ngModel.$modelValue && ngModel.$modelValue.toFixed(digitsAfterDecimalPoint);\n\n // 29.00 => 29\n if (ngModel.$modelValue % 1 === 0) {\n filteredValue = ngModel.$modelValue;\n }\n\n if (filteredValue || filteredValue === 0) {\n ngModel.$viewValue = filteredValue;\n ngModel.$render(true);\n }\n });\n\n ngModel.$render = function (isInternalChange) {\n element.val(ngModel.$viewValue);\n\n if (!isInternalChange) {\n element.blur();\n }\n };\n\n scope.$watch('model', function () {\n if (!element.is(document.activeElement)) {\n element.blur();\n }\n });\n\n /**\n * Init\n */\n\n $timeout(function () {\n element.trigger('blur');\n });\n }\n };\n })\n\n .directive('fotorama', function () {\n return {\n restrict: 'AE',\n link: function (scope, element) {\n scope.$evalAsync(function () {\n element.fotorama();\n });\n }\n };\n })\n\n .directive('errSrc', function () {\n return {\n link: function (scope, element, attrs) {\n element.bind('error', function () {\n element.attr('src', attrs.errSrc);\n });\n }\n };\n })\n\n .directive('timepair', function ($locale) {\n return {\n scope: {\n timepairDuration: '=',\n timepairDurationLength: '='\n },\n link: function (scope, element) {\n var timepairInstance = element.timepair({\n timeFormat: $locale.DATETIME_FORMATS.timepickerFormat.php\n });\n\n timepairInstance.setDurationLength(scope.timepairDurationLength);\n\n scope.$watch('timepairDuration', function (duration) {\n if (duration > 0) {\n timepairInstance.setDuration(duration / 1000);\n }\n });\n }\n };\n })\n\n .directive('timepairValidator', function () {\n return {\n require: 'ngModel',\n link: function (scope, element, attrs, ngModel) {\n var validate = function (value) {\n ngModel.$setValidity('$valid', angular.isString(value) && value.indexOf(':') > 0);\n };\n\n scope.$watch(function () {\n return ngModel.$viewValue;\n }, validate);\n\n validate(ngModel.$viewValue);\n }\n };\n })\n\n .directive('imageonload', function ($parse) {\n return {\n restrict: 'A',\n link: function (scope, element, attrs) {\n element.bind('load', function () {\n $parse(attrs.imageonload)(scope);\n });\n }\n };\n })\n\n .directive('highlight', function () {\n return function (scope, element, attrs) {\n var selectorToHighlight = attrs.highlight;\n\n if (!selectorToHighlight) {\n return;\n }\n\n setTimeout(function () {\n var elementToHighlight = angular.element(selectorToHighlight);\n\n elementToHighlight.addClass('highlight');\n\n element.hover(function () {\n if (scope.$eval(attrs.highlightDisabled)) {\n return;\n }\n\n elementToHighlight\n .removeClass('__highlight-active')\n .addClass('__highlight-active')\n .css('outline-offset', attrs.highlightOffset)\n .removeClass('__highlight-removed');\n }, function () {\n elementToHighlight.addClass('__highlight-removed');\n });\n }, 0);\n };\n })\n\n .directive('modalContent', function () {\n return {\n restrict: 'C',\n link: function (scope, element) {\n if (element.find('.modal-header:not(.__not-draggable)').length) {\n element.find('.modal-header').addClass('__draggable');\n \n element.draggable({\n handle: '.modal-header',\n scroll: false\n });\n }\n }\n };\n })\n\n // Digital clock\n .directive('clock', function ($locale) {\n return {\n restrict: 'E',\n link: function (scope, element) {\n var renderTime = function () {\n element.text(moment().format($locale.DATETIME_FORMATS.mediumTime));\n };\n\n renderTime();\n\n var intervalId = setInterval(renderTime, 1000);\n\n scope.$on('$destroy', function () {\n clearInterval(intervalId);\n });\n }\n };\n })\n\n /**\n * Renders googletag banner in an element directive is called onto.\n * Subscribes to eventsBus 'banner:refresh' event and re-renders banner when it is published.\n *\n * @arg gtag-banner - banner id\n * @arg width - banner width\n * @arg height - banner height\n * @example:\n *
\n */\n // .directive('gtagBanner', function (eventsBus, $timeout) {\n // return {\n // restrict: 'A',\n // scope: {},\n // link: function (scope, element, attrs) {\n // var id = attrs.gtagBanner;\n // var isFirstExecution = true;\n //\n // element\n // .addClass('banner')\n // .attr('id', id)\n // .css({\n // height: attrs.height,\n // width: attrs.width\n // });\n //\n // var render = function () {\n // if (attrs.ignoreSecondRender === 'true') {\n // attrs.ignoreSecondRender = false;\n // return;\n // }\n //\n // if (isFirstExecution) {\n // isFirstExecution = false;\n //\n // window.googletag.cmd.push(function () {\n // window.googletag.display(id);\n // });\n // } else {\n // window.googletag.pubads().refresh();\n // }\n // };\n //\n // render();\n //\n // $timeout(function () {\n // eventsBus.subscribe('banner:refresh', render);\n // });\n //\n // element.on('$destroy', function () {\n // eventsBus.unsubscribe('banner:refresh');\n // });\n // }\n // };\n // })\n \n .directive('table', function () {\n return {\n restrict: 'C',\n link: function (scope, element) {\n if (element[0].tagName === 'TABLE') {\n element.wrap('
');\n }\n }\n };\n })\n\n .directive('backToTop', function() {\n return {\n restrict: 'E',\n replace: true,\n template: '
',\n link: function($scope, element, attrs) {\n\n $(window).scroll(function(){\n if ($(window).scrollTop() >= 1000) {\n element.addClass('back-to-top-show');\n } else {\n element.removeClass('back-to-top-show');\n }\n });\n\n element.on('click', function(){\n $('html, body').animate({ scrollTop: 0 }, 'fast');\n });\n\n }\n };\n })\n\n .directive('dropdownToggle', function ($rootScope) {\n function dropDownFixPosition(button, dropdown) {\n var dropDownTop = button.offset().top - $(window).scrollTop() + button.outerHeight();\n\n dropdown.css('top', dropDownTop + \"px\");\n dropdown.css('left', button.offset().left + \"px\" );\n }\n\n return {\n restrict: 'C',\n link: function (scope, element) {\n if($rootScope.isTablet || !$rootScope.isMobile || $(element).closest('.table-responsive').length === 0) {\n return;\n }\n\n element.click(function () {\n dropDownFixPosition(element, element.next('.dropdown-menu'));\n });\n }\n };\n })\n\n .directive('dropdownSubmenu', function ($rootScope) {\n return {\n restrict: 'C',\n link: function (scope, element) {\n if(!$rootScope.isAndroid) {\n return;\n }\n\n element.click(function(event) {\n element.siblings().children('.dropdown-menu').hide();\n element.children('.dropdown-menu').toggle();\n event.stopPropagation();\n });\n }\n };\n })\n\n .directive('iframeOnload', function(){\n return {\n restrict: 'A',\n link: function(scope, element, attrs){\n var onload = scope.$eval(attrs.iframeOnload);\n\n element.on('load', function() {\n return onload(element, attrs);\n });\n }\n };\n })\n\n .directive('smsMediaSrc', ['$http', function ($http) {\n var IMAGE_PLACEHOLDERS = {\n TWILIO: '/assets/img/twilio-auth-click-grey-logo.png'\n };\n\n var includesValue = function(container, value) {\n var returnValue = false;\n var pos = container.indexOf(value);\n if (pos >= 0) {\n returnValue = true;\n }\n return returnValue;\n };\n\n return {\n // do not share scope with sibling img tags and parent\n // (prevent show same images on img tag)\n scope: {\n smsMediaSrc: '@'\n },\n link: function ($scope, elem, attrs) {\n function revokeObjectURL() {\n if($scope.objectURL) {\n URL.revokeObjectURL($scope.objectURL);\n }\n }\n\n $scope.$watch('objectURL', function(objectURL) {\n elem.attr('src', objectURL);\n });\n\n $scope.$on('$destroy', function() {\n revokeObjectURL();\n });\n\n attrs.$observe('smsMediaSrc', function(url) {\n revokeObjectURL();\n\n if(url && url.indexOf('data:') === 0) {\n $scope.objectURL = url;\n } else if (includesValue(url, 'api.twilio.com')) {\n $scope.objectURL = IMAGE_PLACEHOLDERS.TWILIO;\n } else {\n $scope.objectURL = url;\n }\n });\n }\n };\n }])\n\n .directive('webcam', function () {\n (function() {\n // GetUserMedia is not yet supported by all browsers\n // Until then, we need to handle the vendor prefixes\n navigator.getMedia = ( navigator.getUserMedia ||\n navigator.webkitGetUserMedia ||\n navigator.mozGetUserMedia ||\n navigator.msGetUserMedia);\n\n // Latest specs modified how to access it\n window.hasModernUserMedia = 'mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices;\n if (window.hasModernUserMedia) {\n navigator.getMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);\n }\n\n // Checks if feature support is available on the client browser\n window.hasUserMedia = function hasUserMedia() {\n return navigator.getMedia ? true : false;\n };\n })();\n\n return {\n template: '
',\n restrict: 'E',\n replace: true,\n transclude: true,\n scope:\n {\n onError: '&',\n onStream: '&',\n onStreaming: '&',\n placeholder: '=',\n config: '=channel'\n },\n link: function postLink($scope, element) {\n var videoElem = null,\n videoStream = null,\n placeholder = null;\n\n $scope.config = $scope.config || {};\n\n var _removeDOMElement = function _removeDOMElement(DOMel) {\n if (DOMel) {\n angular.element(DOMel).remove();\n }\n };\n\n var onDestroy = function onDestroy() {\n if (!!videoStream ) {\n var checker = typeof videoStream.getVideoTracks === 'function';\n if(videoStream.getVideoTracks && checker) {\n // get video track to call stop in it\n // videoStream.stop() is deprecated and may be removed in the\n // near future\n // ENSURE THIS IS CHECKED FIRST BEFORE THE FALLBACK\n // videoStream.stop()\n var tracks = videoStream.getVideoTracks();\n if (tracks && tracks[0] && tracks[0].stop) {\n tracks[0].stop();\n }\n } else if (videoStream.stop) {\n // deprecated, may be removed in the near future\n videoStream.stop();\n }\n }\n\n if (!!videoElem) {\n delete videoElem.src;\n delete videoElem.srcObject;\n videoElem.removeAttribute('src');\n videoElem.removeAttribute('srcObject');\n }\n };\n\n // called when camera stream is loaded\n var onSuccess = function onSuccess(stream) {\n videoStream = stream;\n\n if (window.hasModernUserMedia) {\n videoElem.srcObject = stream;\n } else if (navigator.mozGetUserMedia) {\n // Firefox supports a src object\n videoElem.mozSrcObject = stream;\n } else {\n var vendorURL = window.URL || window.webkitURL;\n videoElem.src = vendorURL.createObjectURL(stream);\n }\n\n /* Start playing the video to show the stream from the webcam */\n videoElem.play();\n $scope.config.video = videoElem;\n\n /* Call custom callback */\n if ($scope.onStream) {\n $scope.onStream({stream: stream});\n }\n };\n\n // called when any error happens\n var onFailure = function onFailure(err) {\n _removeDOMElement(placeholder);\n if (console && console.debug) {\n console.debug('The following error occured: ', err);\n }\n\n /* Call custom callback */\n if ($scope.onError) {\n $scope.onError({err:err});\n }\n\n return;\n };\n\n var startWebcam = function startWebcam() {\n videoElem = document.createElement('video');\n videoElem.setAttribute('class', 'webcam-live');\n videoElem.setAttribute('autoplay', '');\n element.append(videoElem);\n\n if ($scope.placeholder) {\n placeholder = document.createElement('img');\n placeholder.setAttribute('class', 'webcam-loader');\n placeholder.src = $scope.placeholder;\n element.append(placeholder);\n }\n\n // Default variables\n var isStreaming = false,\n width = element.width = $scope.config.videoWidth || 320,\n height = element.height = 0;\n\n // Check the availability of getUserMedia across supported browsers\n if (!window.hasUserMedia()) {\n onFailure({ code: -1, msg: 'Browser does not support getUserMedia.' });\n return;\n }\n\n var mediaConstraint = { video: true, audio: false };\n\n if (window.hasModernUserMedia) {\n // The spec has changed towards a Promise based interface\n navigator.getMedia(mediaConstraint)\n .then(onSuccess)\n .catch(onFailure);\n } else {\n navigator.getMedia(mediaConstraint, onSuccess, onFailure);\n }\n\n /* Start streaming the webcam data when the video element can play\n * It will do it only once\n */\n videoElem.addEventListener('canplay', function() {\n if (!isStreaming) {\n var scale = width / videoElem.videoWidth;\n height = (videoElem.videoHeight * scale) ||\n $scope.config.videoHeight;\n videoElem.setAttribute('width', width);\n videoElem.setAttribute('height', height);\n isStreaming = true;\n\n $scope.config.video = videoElem;\n\n _removeDOMElement(placeholder);\n\n /* Call custom callback */\n if ($scope.onStreaming) {\n $scope.onStreaming();\n }\n }\n }, false);\n };\n\n var stopWebcam = function stopWebcam() {\n onDestroy();\n videoElem.remove();\n };\n\n $scope.$on('$destroy', onDestroy);\n $scope.$on('START_WEBCAM', startWebcam);\n $scope.$on('STOP_WEBCAM', stopWebcam);\n\n startWebcam();\n }\n };\n });\n});\n\n","define('modules/common/avery-label-helper-service',['angular', 'jquery', 'underscore', 'printJS', 'text!./avery.5167.tpl.html', 'text!./avery.5160.tpl.html'], function(angular, $, _, printJS, avery5167, avery5160) {\n 'use strict';\n\n angular.module('bl.avery-label.helper', [])\n .run(function(security, eventsBus) {\n eventsBus.subscribe('user:set', function () {\n var URL = '/vendor/not-bower/js-barcode/JsBarcode.code128.min.js';\n $.getScript(URL, function() {});\n });\n })\n .service('AveryLabelHelper', function($window, $compile, $rootScope, $timeout, $translate, $modal, $filter, $locale, Enums, AppLicense, modalService, localStorageService) {\n var $labelScope;\n\n var AVERY_5160 = {\n labelTemplate: 'averyItem5160',\n file: avery5160,\n labelsPerRow: 3,\n charLimit: {\n itemName: '14',\n itemNameFullRow: '32',\n vendorItemName: '18',\n description: '34',\n color: '23',\n vendorCode: '10',\n departmentCode: '10',\n price: '20',\n size: '8'\n },\n barcodeOptions: {\n barCodeFormat: 'CODE128',\n height: 35,\n width: 1,\n margin: 5,\n displayValue: false\n }\n };\n\n var AVERY_5167 = {\n labelTemplate: 'averyItem5167',\n file: avery5167,\n labelsPerRow: 4,\n charLimit: {\n itemName: '14',\n itemNameFullRow: '30',\n vendorItemName: '14',\n color: '13',\n vendorCode: '6',\n price: '15',\n size: '6'\n },\n barcodeOptions: {\n barCodeFormat: 'CODE128',\n height: 10,\n width: 1,\n margin: 5,\n displayValue: false\n }\n };\n\n function setTemplate(printSettings) {\n return printSettings.labelTemplate === \"averyItem5167\" ? AVERY_5167 : AVERY_5160;\n }\n\n function buildLabels(label, items, printSettings) {\n var addBarCodes = false;\n\n if($window.JsBarcode && printSettings.printBarcodes) {\n addBarCodes = true;\n }\n\n // Map items and build labels\n _.each(items, function (item) {\n var barcode = '';\n\n if(addBarCodes && item.itemNumber) {\n var div = document.createElement('div');\n var img = document.createElement('img');\n new $window.JsBarcode(img, item.itemNumber, label.template.barcodeOptions);\n div.appendChild(img);\n barcode = div.innerHTML;\n }\n\n var printPrivateLabel = printSettings.printVendorStyleNumber && item.vendorItemName && String(item.vendorItemName).valueOf() !== String(item.name).valueOf();\n\n\n var labelInfo = {\n name: formatStringForLabel(item.name, printPrivateLabel ? label.template.charLimit.itemName : label.template.charLimit.itemNameFullRow),\n description: formatStringForLabel(item.description, label.template.charLimit.description),\n departmentCode: formatStringForLabel(item.departmentCode, label.template.charLimit.departmentCode),\n vendorItemName: formatStringForLabel(item.vendorItemName, label.template.charLimit.vendorItemName),\n vendorCode: formatStringForLabel(item.vendorCode, label.template.charLimit.vendorCode),\n price: formatCurrencyForLabel(item.regularPrice, printSettings),\n salePrice: formatCurrencyForLabel(item.salePrice, printSettings),\n color: formatStringForLabel(item.color, label.template.charLimit.color),\n size: formatStringForLabel(item.size, label.template.charLimit.size),\n barcode: barcode,\n blankLabel: false,\n showSalePrice: item.salePrice && item.salePrice > 0 && printSettings.printPrices && !printSettings.hideSalePrice,\n printPrivateLabel: printPrivateLabel\n };\n\n var printCount = printSettings.nbrLabelsPerItem || 1;\n\n if(printSettings.nbrLabelsCustom && (printSettings.nbrLabelsType === 'S' || printSettings.nbrLabelsType === 'SWZ')) {\n if(printSettings.rvMode) {\n printCount = item && item.quantityOnHand > 0 ? item.quantityOnHand : 1;\n } else {\n printCount = item && item.quantityInStock > 0 ? item.quantityInStock : 1;\n }\n }\n\n while(printCount > 0) {\n label.labels.push(angular.copy(labelInfo));\n printCount--;\n }\n });\n\n return label;\n }\n\n function addBlankLabels(label) {\n //if template = 5167 add 4 X (startingRow - 1) + startingColumn - 1 empty labels\n //if template = 5160 add 3 X (startingRow - 1) + startingColumn - 1 empty labels\n var blankLabels = label.template.labelsPerRow * (label.settings.startingRow - 1) + label.settings.startingColumn - 1;\n\n if(blankLabels > 0) {\n var blankLabel = {\n blankLabel: true\n };\n\n while (blankLabels > 0) {\n label.labels.push(angular.copy(blankLabel));\n blankLabels--;\n }\n }\n\n return label;\n }\n\n function formatStringForLabel(string, charLimit) {\n if(!string || typeof string != \"string\") {\n return \"\";\n }\n if(string.length > charLimit) {\n return string.substring(0, charLimit);\n }\n return string;\n }\n\n function formatCurrencyForLabel(amount, printSettings) {\n if(amount == null) {\n amount = 0.00;\n }\n\n var formattedAmount = \"\";\n if(printSettings && printSettings.removeCentsFromPrice) {\n formattedAmount = $filter('currency')(amount, $locale.NUMBER_FORMATS.CURRENCY_SYM, 0);\n } else {\n formattedAmount = $filter('currency')(amount);\n }\n\n if(printSettings && printSettings.removeCommasFromPrice) {\n if($locale.NUMBER_FORMATS.DECIMAL_SEP === \".\") {\n formattedAmount = formattedAmount ? formattedAmount.replace(/,/g, '') : formattedAmount;\n } else {\n formattedAmount = formattedAmount ? formattedAmount.replace(/\\./g, '') : formattedAmount;\n }\n }\n\n return formattedAmount;\n }\n\n function generateCSS(settings) {\n var font = settings.lang === 'en' ?\n {\n type: 'Helvetica',\n src: '../../assets/fonts/Helvetica.ttf'\n }\n :\n {\n type: 'FreeSerif',\n src: '../../assets/fonts/FreeSerif.ttf'\n };\n\n return'@font-face {font-family: \\'' + font.type + '\\';src: url(\\'' + font.src + '\\');}.avery-label-content{position:relative;}.avery-column-left-content{margin-right:8px;}.avery-label-5160,.avery-label-5167{overflow:hidden;border-radius:5px;}@page{margin:0}.avery-border{border: 1px solid #000;}.avery-wrapper{width:8.5in;font-family: ' + font.type + '; color: black;}.avery-label-5160{font-size:11px;width:2.375in;height:.86in;padding: .0625in .125in .0625in .125in;display:inline-block}.avery-label-5160 .avery-row{height: .175in;display:flex;padding-bottom:0.016in}.avery-label-5160 .avery-column{width: 30%}.avery-label-5160 .avery-column-2{width: 60%}.avery-label-5160 .avery-column-3{width: 100%}.avery-label-5167 .avery-column{width: 50%}.avery-column{display:inline-flex}.avery-column span.margin-right{margin-right:8px}.avery-label-barcode{z-index:-1;}.avery-label-5167-barcode{position: absolute; right: 6px; bottom: 12px;}.avery-label-5160-barcode{position: absolute; right: 2px; bottom: 0px;}.avery-label-5167{font-size:8px;width:1.625in;height:.415in;padding:.0625in .0625in 0;display:inline-block}.avery-label-5167 .avery-row{height:.115in;display:flex;padding-bottom:0.0227in}.avery-label-5160:nth-child(30n+1),.avery-label-5160:nth-child(30n+2),.avery-label-5160:nth-child(30n+3),.avery-label-5167:nth-child(80n+1),.avery-label-5167:nth-child(80n+2),.avery-label-5167:nth-child(80n+3),.avery-label-5167:nth-child(80n+4){margin-top:' + settings.topMargin + '}.avery-label-5160:nth-child(30n),.avery-label-5167:nth-child(80n) {page-break-after: always;}';\n }\n\n var service = {\n printLabels: function(items, printSettings, callback) {\n service.setTopMargin(printSettings.labelTemplate, printSettings.topMargin);\n service.setLeftMargin(printSettings.labelTemplate, printSettings.leftMargin);\n service.setLabelSpacing(printSettings.labelTemplate, printSettings.labelSpacing);\n\n var license = AppLicense.get();\n var label = {\n template: setTemplate(printSettings),\n html: '',\n labels: [],\n settings: {\n startingRow: printSettings.startingRow,\n startingColumn: printSettings.startingColumn,\n topMargin: printSettings.topMargin + 'in',\n leftMargin: printSettings.leftMargin + 'in',\n labelSpacing: printSettings.labelSpacing +'in',\n printPrice: printSettings.printPrices,\n printVendorCode: printSettings.printColorOrVendorCode === \"VC\" || printSettings.printColorOrVendorCode === \"B\",\n printColor: printSettings.printColorOrVendorCode === \"C\" || printSettings.printColorOrVendorCode === \"B\",\n printVendorItemName: printSettings.printVendorStyleNumber,\n printBarcodes: printSettings.printBarcodes,\n hideSalePrice: printSettings.hideSalePrice,\n lang: license && license.company && license.company.language || 'en',\n showBorder: printSettings.showBorder\n }\n };\n\n label = addBlankLabels(label);\n label = buildLabels(label, items, printSettings);\n\n // Destroy/Init scope\n if($labelScope) {\n $labelScope.$destroy();\n }\n\n $labelScope = $rootScope.$new();\n\n $labelScope.labels = label.labels;\n $labelScope.settings = label.settings;\n var compile = $compile(label.template.file)($labelScope);\n\n // Do $timeout so the $compile content renders.\n $timeout(function() {\n var html = compile[0].outerHTML;\n var css = generateCSS(label.settings);\n service.printHTMLIframe(html, css, callback);\n }, 1000);\n },\n printHTMLIframe: function(html, css, callback) {\n var hiddenFrame = $('').appendTo('body')[0];\n hiddenFrame.onload = function() {\n var isIE = !!navigator.userAgent.match(/Trident/g) || !!navigator.userAgent.match(/MSIE/g);\n if(isIE) {\n modalService.showMessage('alerts.printing.message.enhanced-printing-legacy-browser-error');\n } else {\n printAndRemove();\n }\n };\n\n var printAndRemove = function() {\n hiddenFrame.contentWindow.focus();\n hiddenFrame.contentWindow.print();\n\n $timeout(function() {\n $(hiddenFrame).remove();\n if(callback) {\n callback({ label: label });\n }\n });\n };\n\n var htmlDocument = \"\" +\n \"\" +\n \"\" +\n \"\" +\n \"\" +\n \"\" + // Print only after document is loaded\n html +\n \"\" +\n \"\";\n\n var doc = hiddenFrame.contentWindow.document.open(\"text/html\", \"replace\");\n doc.write(htmlDocument);\n doc.close();\n },\n printHTMLPrintJSRawHTML: function(html, style, callback) {\n // 816px === 8.5 inches\n printJS({ printable: html, type: 'raw-html', maxWidth: '820', css: '../../assets/print/label.print.css', onLoadingEnd: function() {\n if(callback && typeof callback === \"function\") {\n callback({ html: html, style: style, css: '../../assets/print/label.print.css' });\n }\n }});\n },\n printHTMLCreateElement: function(html, css) {\n var PRINT_ELEMENT_ID = 'avery-label-print-area';\n var STYLE_ELEMENT_ID = 'avery-label-print-area-css';\n\n var style = document.createElement('style');\n style.id = STYLE_ELEMENT_ID;\n style.type = 'text/css';\n style.innerHTML = css;\n\n document.head.appendChild(style);\n var print = document.createElement('div');\n print.id = PRINT_ELEMENT_ID;\n print.innerHTML = html;\n document.body.appendChild(print);\n window.print();\n setTimeout(function() {\n // need to remove print elements on the next tick otherwise print preview doesn't always display styles\n style.remove();\n print.remove();\n }, 500);\n },\n CONSTANTS: {\n TOP_MARGIN: \"_TOP_MARGIN\",\n LEFT_MARGIN: \"_LEFT_MARGIN\",\n LABEL_SPACING: \"_LABEL_SPACING\",\n },\n getTopMargin: function (template) {\n return localStorageService.get(template + this.CONSTANTS.TOP_MARGIN);\n },\n setTopMargin: function (template, margin) {\n localStorageService.set(template + this.CONSTANTS.TOP_MARGIN, margin);\n },\n getLeftMargin: function (template) {\n return localStorageService.get(template + this.CONSTANTS.LEFT_MARGIN);\n },\n setLeftMargin: function (template, margin) {\n localStorageService.set(template + this.CONSTANTS.LEFT_MARGIN, margin);\n },\n getLabelSpacing: function (template) {\n return localStorageService.get(template + this.CONSTANTS.LABEL_SPACING);\n },\n setLabelSpacing: function (template, spacing) {\n localStorageService.set(template + this.CONSTANTS.LABEL_SPACING, spacing);\n }\n };\n\n return service;\n });\n});\n\n","// Customized for BridalLive version of TinyMCE.\n// Customized:\n// * theme script is included in the tinymce.min.js\n// * plugins included: code, link, textcolor, fullpage\n// * base url is hardcoded into customizedBaseUrl variable - built-in autodetection srewes\n// 4.1.10 (2015-05-05)\n!function(e,t){\"use strict\";\n var customizedBaseUrl = '/vendor/not-bower/tinymce';\n\nfunction n(e,t){for(var n,r=[],i=0;ir;r++)if(o=n[r],o&&o.func.call(o.scope,e)===!1&&e.preventDefault(),e.isImmediatePropagationStopped())return}var a=this,s={},l,c,u,d,f;c=o+(+new Date).toString(32),d=\"onmouseenter\"in document.documentElement,u=\"onfocusin\"in document.documentElement,f={mouseenter:\"mouseover\",mouseleave:\"mouseout\"},l=1,a.domLoaded=!1,a.events=s,a.bind=function(t,o,p,h){function m(e){i(n(e||_.event),g)}var g,v,y,b,C,x,w,_=window;if(t&&3!==t.nodeType&&8!==t.nodeType){for(t[c]?g=t[c]:(g=l++,t[c]=g,s[g]={}),h=h||t,o=o.split(\" \"),y=o.length;y--;)b=o[y],x=m,C=w=!1,\"DOMContentLoaded\"===b&&(b=\"ready\"),a.domLoaded&&\"ready\"===b&&\"complete\"==t.readyState?p.call(h,n({type:b})):(d||(C=f[b],C&&(x=function(e){var t,r;if(t=e.currentTarget,r=e.relatedTarget,r&&t.contains)r=t.contains(r);else for(;r&&r!==t;)r=r.parentNode;r||(e=n(e||_.event),e.type=\"mouseout\"===e.type?\"mouseleave\":\"mouseenter\",e.target=t,i(e,g))})),u||\"focusin\"!==b&&\"focusout\"!==b||(w=!0,C=\"focusin\"===b?\"focus\":\"blur\",x=function(e){e=n(e||_.event),e.type=\"focus\"===e.type?\"focusin\":\"focusout\",i(e,g)}),v=s[g][b],v?\"ready\"===b&&a.domLoaded?p({type:b}):v.push({func:p,scope:h}):(s[g][b]=v=[{func:p,scope:h}],v.fakeName=C,v.capture=w,v.nativeHandler=x,\"ready\"===b?r(t,x,a):e(t,C||b,x,w)));return t=v=0,p}},a.unbind=function(e,n,r){var i,o,l,u,d,f;if(!e||3===e.nodeType||8===e.nodeType)return a;if(i=e[c]){if(f=s[i],n){for(n=n.split(\" \"),l=n.length;l--;)if(d=n[l],o=f[d]){if(r)for(u=o.length;u--;)if(o[u].func===r){var p=o.nativeHandler,h=o.fakeName,m=o.capture;o=o.slice(0,u).concat(o.slice(u+1)),o.nativeHandler=p,o.fakeName=h,o.capture=m,f[d]=o}r&&0!==o.length||(delete f[d],t(e,o.fakeName||d,o.nativeHandler,o.capture))}}else{for(d in f)o=f[d],t(e,o.fakeName||d,o.nativeHandler,o.capture);f={}}for(d in f)return a;delete s[i];try{delete e[c]}catch(g){e[c]=null}}return a},a.fire=function(e,t,r){var o;if(!e||3===e.nodeType||8===e.nodeType)return a;r=n(null,r),r.type=t,r.target=e;do o=e[c],o&&i(r,o),e=e.parentNode||e.ownerDocument||e.defaultView||e.parentWindow;while(e&&!r.isPropagationStopped());return a},a.clean=function(e){var t,n,r=a.unbind;if(!e||3===e.nodeType||8===e.nodeType)return a;if(e[c]&&r(e),e.getElementsByTagName||(e=e.document),e&&e.getElementsByTagName)for(r(e),n=e.getElementsByTagName(\"*\"),t=n.length;t--;)e=n[t],e[c]&&r(e);return a},a.destroy=function(){s={}},a.cancel=function(e){return e&&(e.preventDefault(),e.stopImmediatePropagation()),!1}}var o=\"mce-data-\",a=/^(?:mouse|contextmenu)|click/,s={keyLocation:1,layerX:1,layerY:1,returnValue:1};return i.Event=new i,i.Event.bind(window,\"ready\",function(){}),i}),r(c,[],function(){if(!window.jQuery)throw new Error(\"Load jQuery first\");return jQuery.find}),r(u,[],function(){var e=navigator,t=e.userAgent,n,r,i,o,a,s,l,c,u;n=window.opera&&window.opera.buildNumber,u=/Android/.test(t),r=/WebKit/.test(t),i=!r&&!n&&/MSIE/gi.test(t)&&/Explorer/gi.test(e.appName),i=i&&/MSIE (\\w+)\\./.exec(t)[1],o=-1==t.indexOf(\"Trident/\")||-1==t.indexOf(\"rv:\")&&-1==e.appName.indexOf(\"Netscape\")?!1:11,a=!document.msElementsFromPoint||i||o?!1:12,i=i||o||a,s=!r&&!o&&/Gecko/.test(t),l=-1!=t.indexOf(\"Mac\"),c=/(iPad|iPhone)/.test(t),a&&(r=!1);var d=!c||t.match(/AppleWebKit\\/(\\d*)/)[1]>=534;return{opera:n,webkit:r,ie:i,gecko:s,mac:l,iOS:c,android:u,contentEditable:d,transparentSrc:\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\",caretAfter:8!=i,range:window.getSelection&&\"Range\"in window,documentMode:i&&!a?document.documentMode||7:10}}),r(d,[u],function(e){function n(e){return null===e||e===t?\"\":(\"\"+e).replace(v,\"\")}function r(e,n){return n?\"array\"==n&&y(e)?!0:typeof e==n:e!==t}function i(e){var t=e,n,r;if(!y(e))for(t=[],n=0,r=e.length;r>n;n++)t[n]=e[n];return t}function o(e,t,n){var r;for(e=e||[],t=t||\",\",\"string\"==typeof e&&(e=e.split(t)),n=n||{},r=e.length;r--;)n[e[r]]={};return n}function a(e,n,r){var i,o;if(!e)return 0;if(r=r||e,e.length!==t){for(i=0,o=e.length;o>i;i++)if(n.call(r,e[i],i,e)===!1)return 0}else for(i in e)if(e.hasOwnProperty(i)&&n.call(r,e[i],i,e)===!1)return 0;return 1}function s(e,t){var n=[];return a(e,function(e){n.push(t(e))}),n}function l(e,t){var n=[];return a(e,function(e){(!t||t(e))&&n.push(e)}),n}function c(e,t,n){var r=this,i,o,a,s,l,c=0;if(e=/^((static) )?([\\w.]+)(:([\\w.]+))?/.exec(e),a=e[3].match(/(^|\\.)(\\w+)$/i)[2],o=r.createNS(e[3].replace(/\\.\\w+$/,\"\"),n),!o[a]){if(\"static\"==e[2])return o[a]=t,void(this.onCreate&&this.onCreate(e[2],e[3],o[a]));t[a]||(t[a]=function(){},c=1),o[a]=t[a],r.extend(o[a].prototype,t),e[5]&&(i=r.resolve(e[5]).prototype,s=e[5].match(/\\.(\\w+)$/i)[1],l=o[a],c?o[a]=function(){return i[s].apply(this,arguments)}:o[a]=function(){return this.parent=i[s],l.apply(this,arguments)},o[a].prototype[a]=o[a],r.each(i,function(e,t){o[a].prototype[t]=i[t]}),r.each(t,function(e,t){i[t]?o[a].prototype[t]=function(){return this.parent=i[t],e.apply(this,arguments)}:t!=a&&(o[a].prototype[t]=e)})),r.each(t[\"static\"],function(e,t){o[a][t]=e})}}function u(e,t){var n,r;if(e)for(n=0,r=e.length;r>n;n++)if(e[n]===t)return n;return-1}function d(e,n){var r,i,o,a=arguments,s;for(r=1,i=a.length;i>r;r++){n=a[r];for(o in n)n.hasOwnProperty(o)&&(s=n[o],s!==t&&(e[o]=s))}return e}function f(e,t,n,r){r=r||this,e&&(n&&(e=e[n]),a(e,function(e,i){return t.call(r,e,i,n)===!1?!1:void f(e,t,n,r)}))}function p(e,t){var n,r;for(t=t||window,e=e.split(\".\"),n=0;nn&&(t=t[e[n]],t);n++);return t}function m(e,t){return!e||r(e,\"array\")?e:s(e.split(t||\",\"),n)}function g(t){var n=e.cacheSuffix;return n&&(t+=(-1===t.indexOf(\"?\")?\"?\":\"&\")+n),t}var v=/^\\s*|\\s*$/g,y=Array.isArray||function(e){return\"[object Array]\"===Object.prototype.toString.call(e)};return{trim:n,isArray:y,is:r,toArray:i,makeMap:o,each:a,map:s,grep:l,inArray:u,extend:d,create:c,walk:f,createNS:p,resolve:h,explode:m,_addCacheSuffix:g}}),r(f,[l,c,d,u],function(e,n,r,i){function o(e){return\"undefined\"!=typeof e}function a(e){return\"string\"==typeof e}function s(e){return e&&e==e.window}function l(e,t){var n,r,i;for(t=t||w,i=t.createElement(\"div\"),n=t.createDocumentFragment(),i.innerHTML=e;r=i.firstChild;)n.appendChild(r);return n}function c(e,t,n,r){var i;if(a(t))t=l(t,v(e[0]));else if(t.length&&!t.nodeType){if(t=f.makeArray(t),r)for(i=t.length-1;i>=0;i--)c(e,t[i],n,r);else for(i=0;ii&&(a=e[i],t.call(a,i,a)!==!1);i++);return e}function g(e,t){var n=[];return m(e,function(e,r){t(r,e)&&n.push(r)}),n}function v(e){return e?9==e.nodeType?e:e.ownerDocument:w}function y(e,n,r){var i=[],o=e[n];for(\"string\"!=typeof r&&r instanceof f&&(r=r[0]);o&&9!==o.nodeType;){if(r!==t){if(o===r)break;if(\"string\"==typeof r&&f(o).is(r))break}1===o.nodeType&&i.push(o),o=o[n]}return i}function b(e,n,r,i){var o=[];for(i instanceof f&&(i=i[0]);e;e=e[n])if(!r||e.nodeType===r){if(i!==t){if(e===i)break;if(\"string\"==typeof i&&f(e).is(i))break}o.push(e)}return o}function C(e,t,n){for(e=e[t];e;e=e[t])if(e.nodeType==n)return e;return null}function x(e,t,n){m(n,function(n,r){e[n]=e[n]||{},e[n][t]=r})}var w=document,_=Array.prototype.push,E=Array.prototype.slice,N=/^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,k=e.Event,S,T=r.makeMap(\"fillOpacity fontWeight lineHeight opacity orphans widows zIndex zoom\",\" \"),R=r.makeMap(\"checked compact declare defer disabled ismap multiple nohref noshade nowrap readonly selected\",\" \"),A={\"for\":\"htmlFor\",\"class\":\"className\",readonly:\"readOnly\"},B={\"float\":\"cssFloat\"},D={},M={},H=/^\\s*|\\s*$/g;return f.fn=f.prototype={constructor:f,selector:\"\",context:null,length:0,init:function(e,t){var n=this,r,i;if(!e)return n;if(e.nodeType)return n.context=n[0]=e,n.length=1,n;if(t&&t.nodeType)n.context=t;else{if(t)return f(e).attr(t);n.context=t=document}if(a(e)){if(n.selector=e,r=\"<\"===e.charAt(0)&&\">\"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!r)return f(t).find(e);if(r[1])for(i=l(e,v(t)).firstChild;i;)_.call(n,i),i=i.nextSibling;else{if(i=v(t).getElementById(r[2]),!i)return n;if(i.id!==r[2])return n.find(e);n.length=1,n[0]=i}}else this.add(e,!1);return n},toArray:function(){return r.toArray(this)},add:function(e,t){var n=this,r,i;if(a(e))return n.add(f(e));if(t!==!1)for(r=f.unique(n.toArray().concat(f.makeArray(e))),n.length=r.length,i=0;it;t++)f.find(e,this[t],r);return f(r)},filter:function(e){return f(\"function\"==typeof e?g(this.toArray(),function(t,n){return e(n,t)}):f.filter(e,this.toArray()))},closest:function(e){var t=[];return e instanceof f&&(e=e[0]),this.each(function(n,r){for(;r;){if(\"string\"==typeof e&&f(r).is(e)){t.push(r);break}if(r==e){t.push(r);break}r=r.parentNode}}),f(t)},offset:function(e){var t,n,r,i=0,o=0,a;return e?this.css(e):(t=this[0],t&&(n=t.ownerDocument,r=n.documentElement,t.getBoundingClientRect&&(a=t.getBoundingClientRect(),i=a.left+(r.scrollLeft||n.body.scrollLeft)-r.clientLeft,o=a.top+(r.scrollTop||n.body.scrollTop)-r.clientTop)),{left:i,top:o})},push:_,sort:[].sort,splice:[].splice},r.extend(f,{extend:r.extend,makeArray:function(e){return s(e)||e.nodeType?[e]:r.toArray(e)},inArray:p,isArray:r.isArray,each:m,trim:h,grep:g,find:n,expr:n.selectors,unique:n.uniqueSort,text:n.getText,contains:n.contains,filter:function(e,t,n){var r=t.length;for(n&&(e=\":not(\"+e+\")\");r--;)1!=t[r].nodeType&&t.splice(r,1);return t=1===t.length?f.find.matchesSelector(t[0],e)?[t[0]]:[]:f.find.matches(e,t)}}),m({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return y(e,\"parentNode\")},next:function(e){return C(e,\"nextSibling\",1)},prev:function(e){return C(e,\"previousSibling\",1)},children:function(e){return b(e.firstChild,\"nextSibling\",1)},contents:function(e){return r.toArray((\"iframe\"===e.nodeName?e.contentDocument||e.contentWindow.document:e).childNodes)}},function(e,t){f.fn[e]=function(n){var r=this,i=[];return r.each(function(){var e=t.call(i,this,n,i);e&&(f.isArray(e)?i.push.apply(i,e):i.push(e))}),this.length>1&&(i=f.unique(i),0===e.indexOf(\"parents\")&&(i=i.reverse())),i=f(i),n?i.filter(n):i}}),m({parentsUntil:function(e,t){return y(e,\"parentNode\",t)},nextUntil:function(e,t){return b(e,\"nextSibling\",1,t).slice(1)},prevUntil:function(e,t){return b(e,\"previousSibling\",1,t).slice(1)}},function(e,t){f.fn[e]=function(n,r){var i=this,o=[];return i.each(function(){var e=t.call(o,this,n,o);e&&(f.isArray(e)?o.push.apply(o,e):o.push(e))}),this.length>1&&(o=f.unique(o),(0===e.indexOf(\"parents\")||\"prevUntil\"===e)&&(o=o.reverse())),o=f(o),r?o.filter(r):o}}),f.fn.is=function(e){return!!e&&this.filter(e).length>0},f.fn.init.prototype=f.fn,f.overrideDefaults=function(e){function t(r,i){return n=n||e(),0===arguments.length&&(r=n.element),i||(i=n.context),new t.fn.init(r,i)}var n;return f.extend(t,this),t},i.ie&&i.ie<8&&(x(D,\"get\",{maxlength:function(e){var t=e.maxLength;return 2147483647===t?S:t},size:function(e){var t=e.size;return 20===t?S:t},\"class\":function(e){return e.className},style:function(e){var t=e.style.cssText;return 0===t.length?S:t}}),x(D,\"set\",{\"class\":function(e,t){e.className=t},style:function(e,t){e.style.cssText=t}})),i.ie&&i.ie<9&&(B[\"float\"]=\"styleFloat\",x(M,\"set\",{opacity:function(e,t){var n=e.style;null===t||\"\"===t?n.removeAttribute(\"filter\"):(n.zoom=1,n.filter=\"alpha(opacity=\"+100*t+\")\")}})),f.attrHooks=D,f.cssHooks=M,f}),r(p,[],function(){return function(e,t){function n(e,t,n,r){function i(e){return e=parseInt(e,10).toString(16),e.length>1?e:\"0\"+e}return\"#\"+i(t)+i(n)+i(r)}var r=/rgb\\s*\\(\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*\\)/gi,i=/(?:url(?:(?:\\(\\s*\\\"([^\\\"]+)\\\"\\s*\\))|(?:\\(\\s*\\'([^\\']+)\\'\\s*\\))|(?:\\(\\s*([^)\\s]+)\\s*\\))))|(?:\\'([^\\']+)\\')|(?:\\\"([^\\\"]+)\\\")/gi,o=/\\s*([^:]+):\\s*([^;]+);?/g,a=/\\s+$/,s,l,c={},u,d,f,p=\"\\ufeff\";for(e=e||{},t&&(d=t.getValidStyles(),f=t.getInvalidStyles()),u=(\"\\\\\\\" \\\\' \\\\; \\\\: ; : \"+p).split(\" \"),l=0;l-1&&n||(m[e+t]=-1==l?s[0]:s.join(\" \"),delete m[e+\"-top\"+t],delete m[e+\"-right\"+t],delete m[e+\"-bottom\"+t],delete m[e+\"-left\"+t])}}function u(e){var t=m[e],n;if(t){for(t=t.split(\" \"),n=t.length;n--;)if(t[n]!==t[0])return!1;return m[e]=t[0],!0}}function d(e,t,n,r){u(t)&&u(n)&&u(r)&&(m[e]=m[t]+\" \"+m[n]+\" \"+m[r],delete m[t],delete m[n],delete m[r])}function f(e){return b=!0,c[e]}function p(e,t){return b&&(e=e.replace(/\\uFEFF[0-9]/g,function(e){return c[e]})),t||(e=e.replace(/\\\\([\\'\\\";:])/g,\"$1\")),e}function h(t,n,r,i,o,a){if(o=o||a)return o=p(o),\"'\"+o.replace(/\\'/g,\"\\\\'\")+\"'\";if(n=p(n||r||i),!e.allow_script_urls){var s=n.replace(/[\\s\\r\\n]+/,\"\");if(/(java|vb)script:/i.test(s))return\"\";if(!e.allow_svg_data_urls&&/^data:image\\/svg/i.test(s))return\"\"}return C&&(n=C.call(x,n,\"style\")),\"url('\"+n.replace(/\\'/g,\"\\\\'\")+\"')\"}var m={},g,v,y,b,C=e.url_converter,x=e.url_converter_scope||this;if(t){for(t=t.replace(/[\\u0000-\\u001F]/g,\"\"),t=t.replace(/\\\\[\\\"\\';:\\uFEFF]/g,f).replace(/\\\"[^\\\"]+\\\"|\\'[^\\']+\\'/g,function(e){return e.replace(/[;:]/g,f)});g=o.exec(t);){if(v=g[1].replace(a,\"\").toLowerCase(),y=g[2].replace(a,\"\"),y=y.replace(/\\\\[0-9a-f]+/g,function(e){return String.fromCharCode(parseInt(e.substr(1),16))}),v&&y.length>0){if(!e.allow_script_urls&&(\"behavior\"==v||/expression\\s*\\(|\\/\\*|\\*\\//.test(y)))continue;\"font-weight\"===v&&\"700\"===y?y=\"bold\":(\"color\"===v||\"background-color\"===v)&&(y=y.toLowerCase()),y=y.replace(r,n),y=y.replace(i,h),m[v]=b?p(y,!0):y}o.lastIndex=g.index+g[0].length}s(\"border\",\"\",!0),s(\"border\",\"-width\"),s(\"border\",\"-color\"),s(\"border\",\"-style\"),s(\"padding\",\"\"),s(\"margin\",\"\"),d(\"border\",\"border-width\",\"border-style\",\"border-color\"),\"medium none\"===m.border&&delete m.border,\"none\"===m[\"border-image\"]&&delete m[\"border-image\"]}return m},serialize:function(e,t){function n(t){var n,r,o,a;if(n=d[t])for(r=0,o=n.length;o>r;r++)t=n[r],a=e[t],a!==s&&a.length>0&&(i+=(i.length>0?\" \":\"\")+t+\": \"+a+\";\")}function r(e,t){var n;return n=f[\"*\"],n&&n[e]?!1:(n=f[t],n&&n[e]?!1:!0)}var i=\"\",o,a;if(t&&d)n(\"*\"),n(t);else for(o in e)a=e[o],a!==s&&a.length>0&&(!f||r(o,t))&&(i+=(i.length>0?\" \":\"\")+o+\": \"+a+\";\");return i}}}}),r(h,[],function(){return function(e,t){function n(e,n,r,i){var o,a;if(e){if(!i&&e[n])return e[n];if(e!=t){if(o=e[r])return o;for(a=e.parentNode;a&&a!=t;a=a.parentNode)if(o=a[r])return o}}}var r=e;this.current=function(){return r},this.next=function(e){return r=n(r,\"firstChild\",\"nextSibling\",e)},this.prev=function(e){return r=n(r,\"lastChild\",\"previousSibling\",e)}}}),r(m,[d],function(e){function t(n){function r(){return L.createDocumentFragment()}function i(e,t){_(F,e,t)}function o(e,t){_(z,e,t)}function a(e){i(e.parentNode,j(e))}function s(e){i(e.parentNode,j(e)+1)}function l(e){o(e.parentNode,j(e))}function c(e){o(e.parentNode,j(e)+1)}function u(e){e?(H[U]=H[V],H[$]=H[W]):(H[V]=H[U],H[W]=H[$]),H.collapsed=F}function d(e){a(e),c(e)}function f(e){i(e,0),o(e,1===e.nodeType?e.childNodes.length:e.nodeValue.length)}function p(e,t){var n=H[V],r=H[W],i=H[U],o=H[$],a=t.startContainer,s=t.startOffset,l=t.endContainer,c=t.endOffset;return 0===e?w(n,r,a,s):1===e?w(i,o,a,s):2===e?w(i,o,l,c):3===e?w(n,r,l,c):void 0}function h(){E(I)}function m(){return E(P)}function g(){return E(O)}function v(e){var t=this[V],r=this[W],i,o;3!==t.nodeType&&4!==t.nodeType||!t.nodeValue?(t.childNodes.length>0&&(o=t.childNodes[r]),o?t.insertBefore(e,o):3==t.nodeType?n.insertAfter(e,t):t.appendChild(e)):r?r>=t.nodeValue.length?n.insertAfter(e,t):(i=t.splitText(r),t.parentNode.insertBefore(e,i)):t.parentNode.insertBefore(e,t)}function y(e){var t=H.extractContents();H.insertNode(e),e.appendChild(t),H.selectNode(e)}function b(){return q(new t(n),{startContainer:H[V],startOffset:H[W],endContainer:H[U],endOffset:H[$],collapsed:H.collapsed,commonAncestorContainer:H.commonAncestorContainer})}function C(e,t){var n;if(3==e.nodeType)return e;if(0>t)return e;for(n=e.firstChild;n&&t>0;)--t,n=n.nextSibling;return n?n:e}function x(){return H[V]==H[U]&&H[W]==H[$]}function w(e,t,r,i){var o,a,s,l,c,u;if(e==r)return t==i?0:i>t?-1:1;for(o=r;o&&o.parentNode!=e;)o=o.parentNode;if(o){for(a=0,s=e.firstChild;s!=o&&t>a;)a++,s=s.nextSibling;return a>=t?-1:1}for(o=e;o&&o.parentNode!=r;)o=o.parentNode;if(o){for(a=0,s=r.firstChild;s!=o&&i>a;)a++,s=s.nextSibling;return i>a?-1:1}for(l=n.findCommonAncestor(e,r),c=e;c&&c.parentNode!=l;)c=c.parentNode;for(c||(c=l),u=r;u&&u.parentNode!=l;)u=u.parentNode;if(u||(u=l),c==u)return 0;for(s=l.firstChild;s;){if(s==c)return-1;if(s==u)return 1;s=s.nextSibling}}function _(e,t,r){var i,o;for(e?(H[V]=t,H[W]=r):(H[U]=t,H[$]=r),i=H[U];i.parentNode;)i=i.parentNode;for(o=H[V];o.parentNode;)o=o.parentNode;o==i?w(H[V],H[W],H[U],H[$])>0&&H.collapse(e):H.collapse(e),H.collapsed=x(),H.commonAncestorContainer=n.findCommonAncestor(H[V],H[U])}function E(e){var t,n=0,r=0,i,o,a,s,l,c;if(H[V]==H[U])return N(e);for(t=H[U],i=t.parentNode;i;t=i,i=i.parentNode){if(i==H[V])return k(t,e);++n}for(t=H[V],i=t.parentNode;i;t=i,i=i.parentNode){if(i==H[U])return S(t,e);++r}for(o=r-n,a=H[V];o>0;)a=a.parentNode,o--;for(s=H[U];0>o;)s=s.parentNode,o++;for(l=a.parentNode,c=s.parentNode;l!=c;l=l.parentNode,c=c.parentNode)a=l,s=c;return T(a,s,e)}function N(e){var t,n,i,o,a,s,l,c,u;if(e!=I&&(t=r()),H[W]==H[$])return t;if(3==H[V].nodeType){if(n=H[V].nodeValue,i=n.substring(H[W],H[$]),e!=O&&(o=H[V],c=H[W],u=H[$]-H[W],0===c&&u>=o.nodeValue.length-1?o.parentNode.removeChild(o):o.deleteData(c,u),H.collapse(F)),e==I)return;return i.length>0&&t.appendChild(L.createTextNode(i)),t}for(o=C(H[V],H[W]),a=H[$]-H[W];o&&a>0;)s=o.nextSibling,l=D(o,e),t&&t.appendChild(l),--a,o=s;return e!=O&&H.collapse(F),t}function k(e,t){var n,i,o,a,s,l;if(t!=I&&(n=r()),i=R(e,t),n&&n.appendChild(i),o=j(e),a=o-H[W],0>=a)return t!=O&&(H.setEndBefore(e),H.collapse(z)),n;for(i=e.previousSibling;a>0;)s=i.previousSibling,l=D(i,t),n&&n.insertBefore(l,n.firstChild),--a,i=s;return t!=O&&(H.setEndBefore(e),H.collapse(z)),n}function S(e,t){var n,i,o,a,s,l;for(t!=I&&(n=r()),o=A(e,t),n&&n.appendChild(o),i=j(e),++i,a=H[$]-i,o=e.nextSibling;o&&a>0;)s=o.nextSibling,l=D(o,t),n&&n.appendChild(l),--a,o=s;return t!=O&&(H.setStartAfter(e),H.collapse(F)),n}function T(e,t,n){var i,o,a,s,l,c,u;for(n!=I&&(o=r()),i=A(e,n),o&&o.appendChild(i),a=j(e),s=j(t),++a,l=s-a,c=e.nextSibling;l>0;)u=c.nextSibling,i=D(c,n),o&&o.appendChild(i),c=u,--l;return i=R(t,n),o&&o.appendChild(i),n!=O&&(H.setStartAfter(e),H.collapse(F)),o}function R(e,t){var n=C(H[U],H[$]-1),r,i,o,a,s,l=n!=H[U];if(n==e)return B(n,l,z,t);for(r=n.parentNode,i=B(r,z,z,t);r;){for(;n;)o=n.previousSibling,a=B(n,l,z,t),t!=I&&i.insertBefore(a,i.firstChild),l=F,n=o;if(r==e)return i;n=r.previousSibling,r=r.parentNode,s=B(r,z,z,t),t!=I&&s.appendChild(i),i=s}}function A(e,t){var n=C(H[V],H[W]),r=n!=H[V],i,o,a,s,l;if(n==e)return B(n,r,F,t);for(i=n.parentNode,o=B(i,z,F,t);i;){for(;n;)a=n.nextSibling,s=B(n,r,F,t),t!=I&&o.appendChild(s),r=F,n=a;if(i==e)return o;n=i.nextSibling,i=i.parentNode,l=B(i,z,F,t),t!=I&&l.appendChild(o),o=l}}function B(e,t,r,i){var o,a,s,l,c;if(t)return D(e,i);if(3==e.nodeType){if(o=e.nodeValue,r?(l=H[W],a=o.substring(l),s=o.substring(0,l)):(l=H[$],a=o.substring(0,l),s=o.substring(l)),i!=O&&(e.nodeValue=s),i==I)return;return c=n.clone(e,z),c.nodeValue=a,c}if(i!=I)return n.clone(e,z)}function D(e,t){return t!=I?t==O?n.clone(e,F):e:void e.parentNode.removeChild(e)}function M(){return n.create(\"body\",null,g()).outerText}var H=this,L=n.doc,P=0,O=1,I=2,F=!0,z=!1,W=\"startOffset\",V=\"startContainer\",U=\"endContainer\",$=\"endOffset\",q=e.extend,j=n.nodeIndex;return q(H,{startContainer:L,startOffset:0,endContainer:L,endOffset:0,collapsed:F,commonAncestorContainer:L,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:i,setEnd:o,setStartBefore:a,setStartAfter:s,setEndBefore:l,setEndAfter:c,collapse:u,selectNode:d,selectNodeContents:f,compareBoundaryPoints:p,deleteContents:h,extractContents:m,cloneContents:g,insertNode:v,surroundContents:y,cloneRange:b,toStringIE:M}),H}return t.prototype.toString=function(){return this.toStringIE()},t}),r(g,[d],function(e){function t(e){var t;return t=document.createElement(\"div\"),t.innerHTML=e,t.textContent||t.innerText||e}function n(e,t){var n,r,i,a={};if(e){for(e=e.split(\",\"),t=t||10,n=0;n\\\"\\u0060\\u007E-\\uD7FF\\uE000-\\uFFEF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/g,l=/[<>&\\u007E-\\uD7FF\\uE000-\\uFFEF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/g,c=/[<>&\\\"\\']/g,u=/&#([a-z0-9]+);?|&([a-z0-9]+);/gi,d={128:\"\\u20ac\",130:\"\\u201a\",131:\"\\u0192\",132:\"\\u201e\",133:\"\\u2026\",134:\"\\u2020\",135:\"\\u2021\",136:\"\\u02c6\",137:\"\\u2030\",138:\"\\u0160\",139:\"\\u2039\",140:\"\\u0152\",142:\"\\u017d\",145:\"\\u2018\",146:\"\\u2019\",147:\"\\u201c\",148:\"\\u201d\",149:\"\\u2022\",150:\"\\u2013\",151:\"\\u2014\",152:\"\\u02dc\",153:\"\\u2122\",154:\"\\u0161\",155:\"\\u203a\",156:\"\\u0153\",158:\"\\u017e\",159:\"\\u0178\"};o={'\"':\""\",\"'\":\"'\",\"<\":\"<\",\">\":\">\",\"&\":\"&\",\"`\":\"`\"},a={\"<\":\"<\",\">\":\">\",\"&\":\"&\",\""\":'\"',\"'\":\"'\"},i=n(\"50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,t9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro\",32);\n\nvar f={encodeRaw:function(e,t){return e.replace(t?s:l,function(e){return o[e]||e})},encodeAllRaw:function(e){return(\"\"+e).replace(c,function(e){return o[e]||e})},encodeNumeric:function(e,t){return e.replace(t?s:l,function(e){return e.length>1?\"&#\"+(1024*(e.charCodeAt(0)-55296)+(e.charCodeAt(1)-56320)+65536)+\";\":o[e]||\"&#\"+e.charCodeAt(0)+\";\"})},encodeNamed:function(e,t,n){return n=n||i,e.replace(t?s:l,function(e){return o[e]||n[e]||e})},getEncodeFunc:function(e,t){function a(e,n){return e.replace(n?s:l,function(e){return o[e]||t[e]||\"&#\"+e.charCodeAt(0)+\";\"||e})}function c(e,n){return f.encodeNamed(e,n,t)}return t=n(t)||i,e=r(e.replace(/\\+/g,\",\")),e.named&&e.numeric?a:e.named?t?c:f.encodeNamed:e.numeric?f.encodeNumeric:f.encodeRaw},decode:function(e){return e.replace(u,function(e,n){return n?(n=\"x\"===n.charAt(0).toLowerCase()?parseInt(n.substr(1),16):parseInt(n,10),n>65535?(n-=65536,String.fromCharCode(55296+(n>>10),56320+(1023&n))):d[n]||String.fromCharCode(n)):a[e]||i[e]||t(e)})}};return f}),r(v,[d],function(e){return function(t,n){function r(e){t.getElementsByTagName(\"head\")[0].appendChild(e)}function i(n,i,l){function c(){for(var e=y.passed,t=e.length;t--;)e[t]();y.status=2,y.passed=[],y.failed=[]}function u(){for(var e=y.failed,t=e.length;t--;)e[t]();y.status=3,y.passed=[],y.failed=[]}function d(){var e=navigator.userAgent.match(/WebKit\\/(\\d*)/);return!!(e&&e[1]<536)}function f(e,t){e()||((new Date).getTime()-v0)return g=t.createElement(\"style\"),g.textContent='@import \"'+n+'\"',h(),void r(g);p()}r(m),m.href=n}}var o=0,a={},s;n=n||{},s=n.maxLoadTime||5e3,this.load=i}}),r(y,[c,f,p,l,h,m,g,u,d,v],function(e,n,r,i,o,a,s,l,c,u){function d(e,t){var n={},r=t.keep_values,i;return i={set:function(n,r,i){t.url_converter&&(r=t.url_converter.call(t.url_converter_scope||e,r,i,n[0])),n.attr(\"data-mce-\"+i,r).attr(i,r)},get:function(e,t){return e.attr(\"data-mce-\"+t)||e.attr(t)}},n={style:{set:function(e,t){return null!==t&&\"object\"==typeof t?void e.css(t):(r&&e.attr(\"data-mce-style\",t),void e.attr(\"style\",t))},get:function(t){var n=t.attr(\"data-mce-style\")||t.attr(\"style\");return n=e.serializeStyle(e.parseStyle(n),t[0].nodeName)}}},r&&(n.href=n.src=i),n}function f(e,t){var o=this,a;o.doc=e,o.win=window,o.files={},o.counter=0,o.stdMode=!v||e.documentMode>=8,o.boxModel=!v||\"CSS1Compat\"==e.compatMode||o.stdMode,o.styleSheetLoader=new u(e),o.boundEvents=[],o.settings=t=t||{},o.schema=t.schema,o.styles=new r({url_converter:t.url_converter,url_converter_scope:t.url_converter_scope},t.schema),o.fixDoc(e),o.events=t.ownEvents?new i(t.proxy):i.Event,o.attrHooks=d(o,t),a=t.schema?t.schema.getBlockElements():{},o.$=n.overrideDefaults(function(){return{context:e,element:o.getRoot()}}),o.isBlock=function(e){if(!e)return!1;var t=e.nodeType;return t?!(1!==t||!a[e.nodeName]):!!a[e]}}var p=c.each,h=c.is,m=c.grep,g=c.trim,v=l.ie,y=/^([a-z0-9],?)+$/i,b=/^[ \\t\\r\\n]*$/;return f.prototype={$$:function(e){return\"string\"==typeof e&&(e=this.get(e)),this.$(e)},root:null,fixDoc:function(e){var t=this.settings,n;if(v&&t.schema){\"abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video\".replace(/\\w+/g,function(t){e.createElement(t)});for(n in t.schema.getCustomElements())e.createElement(n)}},clone:function(e,t){var n=this,r,i;return!v||1!==e.nodeType||t?e.cloneNode(t):(i=n.doc,t?r.firstChild:(r=i.createElement(e.nodeName),p(n.getAttribs(e),function(t){n.setAttrib(r,t.nodeName,n.getAttrib(e,t.nodeName))}),r))},getRoot:function(){var e=this;return e.settings.root_element||e.doc.body},getViewPort:function(e){var t,n;return e=e?e:this.win,t=e.document,n=this.boxModel?t.documentElement:t.body,{x:e.pageXOffset||n.scrollLeft,y:e.pageYOffset||n.scrollTop,w:e.innerWidth||n.clientWidth,h:e.innerHeight||n.clientHeight}},getRect:function(e){var t=this,n,r;return e=t.get(e),n=t.getPos(e),r=t.getSize(e),{x:n.x,y:n.y,w:r.w,h:r.h}},getSize:function(e){var t=this,n,r;return e=t.get(e),n=t.getStyle(e,\"width\"),r=t.getStyle(e,\"height\"),-1===n.indexOf(\"px\")&&(n=0),-1===r.indexOf(\"px\")&&(r=0),{w:parseInt(n,10)||e.offsetWidth||e.clientWidth,h:parseInt(r,10)||e.offsetHeight||e.clientHeight}},getParent:function(e,t,n){return this.getParents(e,t,n,!1)},getParents:function(e,n,r,i){var o=this,a,s=[];for(e=o.get(e),i=i===t,r=r||(\"BODY\"!=o.getRoot().nodeName?o.getRoot().parentNode:null),h(n,\"string\")&&(a=n,n=\"*\"===n?function(e){return 1==e.nodeType}:function(e){return o.is(e,a)});e&&e!=r&&e.nodeType&&9!==e.nodeType;){if(!n||n(e)){if(!i)return e;s.push(e)}e=e.parentNode}return i?s:null},get:function(e){var t;return e&&this.doc&&\"string\"==typeof e&&(t=e,e=this.doc.getElementById(e),e&&e.id!==t)?this.doc.getElementsByName(t)[1]:e},getNext:function(e,t){return this._findSib(e,t,\"nextSibling\")},getPrev:function(e,t){return this._findSib(e,t,\"previousSibling\")},select:function(t,n){var r=this;return e(t,r.get(n)||r.settings.root_element||r.doc,[])},is:function(n,r){var i;if(n.length===t){if(\"*\"===r)return 1==n.nodeType;if(y.test(r)){for(r=r.toLowerCase().split(/,/),n=n.nodeName.toLowerCase(),i=r.length-1;i>=0;i--)if(r[i]==n)return!0;return!1}}if(n.nodeType&&1!=n.nodeType)return!1;var o=n.nodeType?[n]:n;return e(r,o[0].ownerDocument||o[0],null,o).length>0},add:function(e,t,n,r,i){var o=this;return this.run(e,function(e){var a;return a=h(t,\"string\")?o.doc.createElement(t):t,o.setAttribs(a,n),r&&(r.nodeType?a.appendChild(r):o.setHTML(a,r)),i?a:e.appendChild(a)})},create:function(e,t,n){return this.add(this.doc.createElement(e),e,t,n,1)},createHTML:function(e,t,n){var r=\"\",i;r+=\"<\"+e;for(i in t)t.hasOwnProperty(i)&&null!==t[i]&&\"undefined\"!=typeof t[i]&&(r+=\" \"+i+'=\"'+this.encode(t[i])+'\"');return\"undefined\"!=typeof n?r+\">\"+n+\"\":r+\" />\"},createFragment:function(e){var t,n,r=this.doc,i;for(i=r.createElement(\"div\"),t=r.createDocumentFragment(),e&&(i.innerHTML=e);n=i.firstChild;)t.appendChild(n);return t},remove:function(e,t){return e=this.$$(e),t?e.each(function(){for(var e;e=this.firstChild;)3==e.nodeType&&0===e.data.length?this.removeChild(e):this.parentNode.insertBefore(e,this)}).remove():e.remove(),e.length>1?e.toArray():e[0]},setStyle:function(e,t,n){e=this.$$(e).css(t,n),this.settings.update_styles&&e.attr(\"data-mce-style\",null)},getStyle:function(e,n,r){return e=this.$$(e),r?e.css(n):(n=n.replace(/-(\\D)/g,function(e,t){return t.toUpperCase()}),\"float\"==n&&(n=v?\"styleFloat\":\"cssFloat\"),e[0]&&e[0].style?e[0].style[n]:t)},setStyles:function(e,t){e=this.$$(e).css(t),this.settings.update_styles&&e.attr(\"data-mce-style\",null)},removeAllAttribs:function(e){return this.run(e,function(e){var t,n=e.attributes;for(t=n.length-1;t>=0;t--)e.removeAttributeNode(n.item(t))})},setAttrib:function(e,t,n){var r=this,i,o,a=r.settings;\"\"===n&&(n=null),e=r.$$(e),i=e.attr(t),e.length&&(o=r.attrHooks[t],o&&o.set?o.set(e,n,t):e.attr(t,n),i!=n&&a.onSetAttrib&&a.onSetAttrib({attrElm:e,attrName:t,attrValue:n}))},setAttribs:function(e,t){var n=this;n.$$(e).each(function(e,r){p(t,function(e,t){n.setAttrib(r,t,e)})})},getAttrib:function(e,t,n){var r=this,i,o;return e=r.$$(e),e.length&&(i=r.attrHooks[t],o=i&&i.get?i.get(e,t):e.attr(t)),\"undefined\"==typeof o&&(o=n||\"\"),o},getPos:function(e,t){var r=this,i=0,o=0,a,s=r.doc,l=s.body,c;if(e=r.get(e),t=t||l,e){if(t===l&&e.getBoundingClientRect&&\"static\"===n(l).css(\"position\"))return c=e.getBoundingClientRect(),t=r.boxModel?s.documentElement:l,i=c.left+(s.documentElement.scrollLeft||l.scrollLeft)-t.clientLeft,o=c.top+(s.documentElement.scrollTop||l.scrollTop)-t.clientTop,{x:i,y:o};for(a=e;a&&a!=t&&a.nodeType;)i+=a.offsetLeft||0,o+=a.offsetTop||0,a=a.offsetParent;for(a=e.parentNode;a&&a!=t&&a.nodeType;)i-=a.scrollLeft||0,o-=a.scrollTop||0,a=a.parentNode}return{x:i,y:o}},parseStyle:function(e){return this.styles.parse(e)},serializeStyle:function(e,t){return this.styles.serialize(e,t)},addStyle:function(e){var t=this,n=t.doc,r,i;if(t!==f.DOM&&n===document){var o=f.DOM.addedStyles;if(o=o||[],o[e])return;o[e]=!0,f.DOM.addedStyles=o}i=n.getElementById(\"mceDefaultStyles\"),i||(i=n.createElement(\"style\"),i.id=\"mceDefaultStyles\",i.type=\"text/css\",r=n.getElementsByTagName(\"head\")[0],r.firstChild?r.insertBefore(i,r.firstChild):r.appendChild(i)),i.styleSheet?i.styleSheet.cssText+=e:i.appendChild(n.createTextNode(e))},loadCSS:function(e){var t=this,n=t.doc,r;return t!==f.DOM&&n===document?void f.DOM.loadCSS(e):(e||(e=\"\"),r=n.getElementsByTagName(\"head\")[0],void p(e.split(\",\"),function(e){var i;e=c._addCacheSuffix(e),t.files[e]||(t.files[e]=!0,i=t.create(\"link\",{rel:\"stylesheet\",href:e}),v&&n.documentMode&&n.recalc&&(i.onload=function(){n.recalc&&n.recalc(),i.onload=null}),r.appendChild(i))}))},addClass:function(e,t){this.$$(e).addClass(t)},removeClass:function(e,t){this.toggleClass(e,t,!1)},hasClass:function(e,t){return this.$$(e).hasClass(t)},toggleClass:function(e,t,r){this.$$(e).toggleClass(t,r).each(function(){\"\"===this.className&&n(this).attr(\"class\",null)})},show:function(e){this.$$(e).show()},hide:function(e){this.$$(e).hide()},isHidden:function(e){return\"none\"==this.$$(e).css(\"display\")},uniqueId:function(e){return(e?e:\"mce_\")+this.counter++},setHTML:function(e,t){e=this.$$(e),v?e.each(function(e,r){if(r.canHaveHTML!==!1){for(;r.firstChild;)r.removeChild(r.firstChild);try{r.innerHTML=\"
\"+t,r.removeChild(r.firstChild)}catch(i){n(\"
\").html(\"
\"+t).contents().slice(1).appendTo(r)}return t}}):e.html(t)},getOuterHTML:function(e){return e=this.get(e),1==e.nodeType&&\"outerHTML\"in e?e.outerHTML:n(\"
\").append(n(e).clone()).html()},setOuterHTML:function(e,t){var r=this;r.$$(e).each(function(){try{if(\"outerHTML\"in this)return void(this.outerHTML=t)}catch(e){}r.remove(n(this).html(t),!0)})},decode:s.decode,encode:s.encodeAllRaw,insertAfter:function(e,t){return t=this.get(t),this.run(e,function(e){var n,r;return n=t.parentNode,r=t.nextSibling,r?n.insertBefore(e,r):n.appendChild(e),e})},replace:function(e,t,n){var r=this;return r.run(t,function(t){return h(t,\"array\")&&(e=e.cloneNode(!0)),n&&p(m(t.childNodes),function(t){e.appendChild(t)}),t.parentNode.replaceChild(e,t)})},rename:function(e,t){var n=this,r;return e.nodeName!=t.toUpperCase()&&(r=n.create(t),p(n.getAttribs(e),function(t){n.setAttrib(r,t.nodeName,n.getAttrib(e,t.nodeName))}),n.replace(r,e,1)),r||e},findCommonAncestor:function(e,t){for(var n=e,r;n;){for(r=t;r&&n!=r;)r=r.parentNode;if(n==r)break;n=n.parentNode}return!n&&e.ownerDocument?e.ownerDocument.documentElement:n},toHex:function(e){return this.styles.toHex(c.trim(e))},run:function(e,t,n){var r=this,i;return\"string\"==typeof e&&(e=r.get(e)),e?(n=n||this,e.nodeType||!e.length&&0!==e.length?t.call(n,e):(i=[],p(e,function(e,o){e&&(\"string\"==typeof e&&(e=r.get(e)),i.push(t.call(n,e,o)))}),i)):!1},getAttribs:function(e){var t;if(e=this.get(e),!e)return[];if(v){if(t=[],\"OBJECT\"==e.nodeName)return e.attributes;\"OPTION\"===e.nodeName&&this.getAttrib(e,\"selected\")&&t.push({specified:1,nodeName:\"selected\"});var n=/<\\/?[\\w:\\-]+ ?|=[\\\"][^\\\"]+\\\"|=\\'[^\\']+\\'|=[\\w\\-]+|>/gi;return e.cloneNode(!1).outerHTML.replace(n,\"\").replace(/[\\w:\\-]+/gi,function(e){t.push({specified:1,nodeName:e})}),t}return e.attributes},isEmpty:function(e,t){var n=this,r,i,a,s,l,c=0;if(e=e.firstChild){s=new o(e,e.parentNode),t=t||(n.schema?n.schema.getNonEmptyElements():null);do{if(a=e.nodeType,1===a){if(e.getAttribute(\"data-mce-bogus\"))continue;if(l=e.nodeName.toLowerCase(),t&&t[l]){if(\"br\"===l){c++;continue}return!1}for(i=n.getAttribs(e),r=i.length;r--;)if(l=i[r].nodeName,\"name\"===l||\"data-mce-bookmark\"===l)return!1}if(8==a)return!1;if(3===a&&!b.test(e.nodeValue))return!1}while(e=s.next())}return 1>=c},createRng:function(){var e=this.doc;return e.createRange?e.createRange():new a(this)},nodeIndex:function(e,t){var n=0,r,i;if(e)for(r=e.nodeType,e=e.previousSibling;e;e=e.previousSibling)i=e.nodeType,(!t||3!=i||i!=r&&e.nodeValue.length)&&(n++,r=i);return n},split:function(e,t,n){function r(e){function t(e){var t=e.previousSibling&&\"SPAN\"==e.previousSibling.nodeName,n=e.nextSibling&&\"SPAN\"==e.nextSibling.nodeName;return t&&n}var n,o=e.childNodes,a=e.nodeType;if(1!=a||\"bookmark\"!=e.getAttribute(\"data-mce-type\")){for(n=o.length-1;n>=0;n--)r(o[n]);if(9!=a){if(3==a&&e.nodeValue.length>0){var s=g(e.nodeValue).length;if(!i.isBlock(e.parentNode)||s>0||0===s&&t(e))return}else if(1==a&&(o=e.childNodes,1==o.length&&o[0]&&1==o[0].nodeType&&\"bookmark\"==o[0].getAttribute(\"data-mce-type\")&&e.parentNode.insertBefore(o[0],e),o.length||/^(br|hr|input|img)$/i.test(e.nodeName)))return;i.remove(e)}return e}}var i=this,o=i.createRng(),a,s,l;return e&&t?(o.setStart(e.parentNode,i.nodeIndex(e)),o.setEnd(t.parentNode,i.nodeIndex(t)),a=o.extractContents(),o=i.createRng(),o.setStart(t.parentNode,i.nodeIndex(t)+1),o.setEnd(e.parentNode,i.nodeIndex(e)+1),s=o.extractContents(),l=e.parentNode,l.insertBefore(r(a),e),n?l.replaceChild(n,t):l.insertBefore(t,e),l.insertBefore(r(s),e),i.remove(e),n||t):void 0},bind:function(e,t,n,r){var i=this;if(c.isArray(e)){for(var o=e.length;o--;)e[o]=i.bind(e[o],t,n,r);return e}return!i.settings.collect||e!==i.doc&&e!==i.win||i.boundEvents.push([e,t,n,r]),i.events.bind(e,t,n,r||i)},unbind:function(e,t,n){var r=this,i;if(c.isArray(e)){for(i=e.length;i--;)e[i]=r.unbind(e[i],t,n);return e}if(r.boundEvents&&(e===r.doc||e===r.win))for(i=r.boundEvents.length;i--;){var o=r.boundEvents[i];e!=o[0]||t&&t!=o[1]||n&&n!=o[2]||this.events.unbind(o[0],o[1],o[2])}return this.events.unbind(e,t,n)},fire:function(e,t,n){return this.events.fire(e,t,n)},getContentEditable:function(e){var t;return e&&1==e.nodeType?(t=e.getAttribute(\"data-mce-contenteditable\"),t&&\"inherit\"!==t?t:\"inherit\"!==e.contentEditable?e.contentEditable:null):null},getContentEditableParent:function(e){for(var t=this.getRoot(),n=null;e&&e!==t&&(n=this.getContentEditable(e),null===n);e=e.parentNode);return n},destroy:function(){var t=this;if(t.boundEvents){for(var n=t.boundEvents.length;n--;){var r=t.boundEvents[n];this.events.unbind(r[0],r[1],r[2])}t.boundEvents=null}e.setDocument&&e.setDocument(),t.win=t.doc=t.root=t.events=t.frag=null},isChildOf:function(e,t){for(;e;){if(t===e)return!0;e=e.parentNode}return!1},dumpRng:function(e){return\"startContainer: \"+e.startContainer.nodeName+\", startOffset: \"+e.startOffset+\", endContainer: \"+e.endContainer.nodeName+\", endOffset: \"+e.endOffset},_findSib:function(e,t,n){var r=this,i=t;if(e)for(\"string\"==typeof i&&(i=function(e){return r.is(e,t)}),e=e[n];e;e=e[n])if(i(e))return e;return null}},f.DOM=new f(document),f}),r(b,[y,d],function(e,t){function n(){function e(e,n){function i(){a.remove(l),s&&(s.onreadystatechange=s.onload=s=null),n()}function o(){\"undefined\"!=typeof console&&console.log&&console.log(\"Failed to load: \"+e)}var a=r,s,l;l=a.uniqueId(),s=document.createElement(\"script\"),s.id=l,s.type=\"text/javascript\",s.src=t._addCacheSuffix(e),\"onreadystatechange\"in s?s.onreadystatechange=function(){/loaded|complete/.test(s.readyState)&&i()}:s.onload=i,s.onerror=o,(document.getElementsByTagName(\"head\")[0]||document.body).appendChild(s)}var n=0,a=1,s=2,l={},c=[],u={},d=[],f=0,p;this.isDone=function(e){return l[e]==s},this.markDone=function(e){l[e]=s},this.add=this.load=function(e,t,r){var i=l[e];i==p&&(c.push(e),l[e]=n),t&&(u[e]||(u[e]=[]),u[e].push({func:t,scope:r||this}))},this.loadQueue=function(e,t){this.loadScripts(c,e,t)},this.loadScripts=function(t,n,r){function c(e){i(u[e],function(e){e.func.call(e.scope)}),u[e]=p}var h;d.push({func:n,scope:r||this}),(h=function(){var n=o(t);t.length=0,i(n,function(t){return l[t]==s?void c(t):void(l[t]!=a&&(l[t]=a,f++,e(t,function(){l[t]=s,f--,c(t),h()})))}),f||(i(d,function(e){e.func.call(e.scope)}),d.length=0)})()}}var r=e.DOM,i=t.each,o=t.grep;return n.ScriptLoader=new n,n}),r(C,[b,d],function(e,n){function r(){var e=this;e.items=[],e.urls={},e.lookup={}}var i=n.each;return r.prototype={get:function(e){return this.lookup[e]?this.lookup[e].instance:t},dependencies:function(e){var t;return this.lookup[e]&&(t=this.lookup[e].dependencies),t||[]},requireLangPack:function(t,n){var i=r.language;if(i&&r.languageLoad!==!1){if(n)if(n=\",\"+n+\",\",-1!=n.indexOf(\",\"+i.substr(0,2)+\",\"))i=i.substr(0,2);else if(-1==n.indexOf(\",\"+i+\",\"))return;e.ScriptLoader.add(this.urls[t]+\"/langs/\"+i+\".js\")}},add:function(e,t,n){return this.items.push(t),this.lookup[e]={instance:t,dependencies:n},t},createUrl:function(e,t){return\"object\"==typeof t?t:{prefix:e.prefix,resource:t,suffix:e.suffix}},addComponents:function(t,n){var r=this.urls[t];i(n,function(t){e.ScriptLoader.add(r+\"/\"+t)})},load:function(n,o,a,s){function l(){var r=c.dependencies(n);i(r,function(e){var n=c.createUrl(o,e);c.load(n.resource,n,t,t)}),a&&a.call(s?s:e)}var c=this,u=o;c.urls[n]||(\"object\"==typeof o&&(u=o.prefix+o.resource+o.suffix),0!==u.indexOf(\"/\")&&-1==u.indexOf(\"://\")&&(u=r.baseURL+\"/\"+u),c.urls[n]=u.substring(0,u.lastIndexOf(\"/\")),c.lookup[n]?l():e.ScriptLoader.add(u,l,s))}},r.PluginManager=new r,r.ThemeManager=new r,r}),r(x,[d,h],function(e,t){function n(e,t){var n=e.childNodes;return t--,t>n.length-1?t=n.length-1:0>t&&(t=0),n[t]||e}function r(e){this.walk=function(t,r){function o(e){var t;return t=e[0],3===t.nodeType&&t===c&&u>=t.nodeValue.length&&e.splice(0,1),t=e[e.length-1],0===f&&e.length>0&&t===d&&3===t.nodeType&&e.splice(e.length-1,1),e}function a(e,t,n){for(var r=[];e&&e!=n;e=e[t])r.push(e);return r}function s(e,t){do{if(e.parentNode==t)return e;e=e.parentNode}while(e)}function l(e,t,n){var i=n?\"nextSibling\":\"previousSibling\";for(g=e,v=g.parentNode;g&&g!=t;g=v)v=g.parentNode,y=a(g==e?g:g[i],i),y.length&&(n||y.reverse(),r(o(y)))}var c=t.startContainer,u=t.startOffset,d=t.endContainer,f=t.endOffset,p,h,m,g,v,y,b;if(b=e.select(\"td.mce-item-selected,th.mce-item-selected\"),b.length>0)return void i(b,function(e){r([e])});if(1==c.nodeType&&c.hasChildNodes()&&(c=c.childNodes[u]),1==d.nodeType&&d.hasChildNodes()&&(d=n(d,f)),c==d)return r(o([c]));for(p=e.findCommonAncestor(c,d),g=c;g;g=g.parentNode){if(g===d)return l(c,p,!0);if(g===p)break}for(g=d;g;g=g.parentNode){if(g===c)return l(d,p);if(g===p)break}h=s(c,p)||c,m=s(d,p)||d,l(c,h,!0),y=a(h==c?h:h.nextSibling,\"nextSibling\",m==d?m.nextSibling:m),y.length&&r(o(y)),l(d,m)},this.split=function(e){function t(e,t){return e.splitText(t)}var n=e.startContainer,r=e.startOffset,i=e.endContainer,o=e.endOffset;return n==i&&3==n.nodeType?r>0&&rr?(o-=r,n=i=t(i,o).previousSibling,o=i.nodeValue.length,r=0):o=0):(3==n.nodeType&&r>0&&r0&&o0)return c=p,u=n?p.nodeValue.length:0,void(i=!0);if(e.isBlock(p)||h[p.nodeName.toLowerCase()])return;s=p}o&&s&&(c=s,i=!0,u=0)}var c,u,d,f=e.getRoot(),p,h,m,g;if(c=n[(r?\"start\":\"end\")+\"Container\"],u=n[(r?\"start\":\"end\")+\"Offset\"],g=1==c.nodeType&&u===c.childNodes.length,h=e.schema.getNonEmptyElements(),m=r,1==c.nodeType&&u>c.childNodes.length-1&&(m=!1),9===c.nodeType&&(c=e.getRoot(),u=0),c===f){if(m&&(p=c.childNodes[u>0?u-1:0],p&&(h[p.nodeName]||\"TABLE\"==p.nodeName)))return;if(c.hasChildNodes()&&(u=Math.min(!m&&u>0?u-1:u,c.childNodes.length-1),c=c.childNodes[u],u=0,c.hasChildNodes()&&!/TABLE/.test(c.nodeName))){p=c,d=new t(c,f);do{if(3===p.nodeType&&p.nodeValue.length>0){u=m?0:p.nodeValue.length,c=p,i=!0;break}if(h[p.nodeName.toLowerCase()]){u=e.nodeIndex(p),c=p.parentNode,\"IMG\"!=p.nodeName||m||u++,i=!0;break}}while(p=m?d.next():d.prev())}}o&&(3===c.nodeType&&0===u&&l(!0),1===c.nodeType&&(p=c.childNodes[u],p||(p=c.childNodes[u-1]),!p||\"BR\"!==p.nodeName||s(p,\"A\")||a(p)||a(p,!0)||l(!0,p))),m&&!o&&3===c.nodeType&&u===c.nodeValue.length&&l(!1),i&&n[\"set\"+(r?\"Start\":\"End\")](c,u)}var i,o;return o=n.collapsed,r(!0),o||r(),i&&o&&n.collapse(!0),i}}var i=e.each;return r.compareRanges=function(e,t){if(e&&t){if(!e.item&&!e.duplicate)return e.startContainer==t.startContainer&&e.startOffset==t.startOffset;if(e.item&&t.item&&e.item(0)===t.item(0))return!0;if(e.isEqual&&t.isEqual&&t.isEqual(e))return!0}return!1},r.getCaretRangeFromPoint=function(e,t,n){var r,i;if(n.caretPositionFromPoint)i=n.caretPositionFromPoint(e,t),r=n.createRange(),r.setStart(i.offsetNode,i.offset),r.collapse(!0);else if(n.caretRangeFromPoint)r=n.caretRangeFromPoint(e,t);else if(n.body.createTextRange){r=n.body.createTextRange();try{r.moveToPoint(e,t),r.collapse(!0)}catch(o){r.collapse(t=e.childNodes.length&&(t=e.childNodes.length-1),e=e.childNodes[t]),e},r}),r(w,[x,u],function(e,t){return function(n){function r(e){var t,r;if(r=n.$(e).parentsUntil(n.getBody()).add(e),r.length===o.length){for(t=r.length;t>=0&&r[t]===o[t];t--);if(-1===t)return o=r,!0}return o=r,!1}var i,o=[];\"onselectionchange\"in n.getDoc()||n.on(\"NodeChange Click MouseUp KeyUp Focus\",function(t){var r,o;r=n.selection.getRng(),o={startContainer:r.startContainer,startOffset:r.startOffset,endContainer:r.endContainer,endOffset:r.endOffset},\"nodechange\"!=t.type&&e.compareRanges(o,i)||n.fire(\"SelectionChange\"),i=o}),n.on(\"contextmenu\",function(){n.fire(\"SelectionChange\")}),n.on(\"SelectionChange\",function(){var e=n.selection.getStart(!0);(t.range||!n.selection.isCollapsed())&&!r(e)&&n.dom.isChildOf(e,n.getBody())&&n.nodeChanged({selectionChange:!0})}),n.on(\"MouseUp\",function(e){e.isDefaultPrevented()||(\"IMG\"==n.selection.getNode().nodeName?setTimeout(function(){n.nodeChanged()},0):n.nodeChanged())}),this.nodeChanged=function(e){var t=n.selection,r,i,o;n.initialized&&t&&!n.settings.disable_nodechange&&!n.settings.readonly&&(o=n.getBody(),r=t.getStart()||o,r=r.ownerDocument!=n.getDoc()?n.getBody():r,\"IMG\"==r.nodeName&&t.isCollapsed()&&(r=r.parentNode),i=[],n.dom.getParent(r,function(e){return e===o?!0:void i.push(e)}),e=e||{},e.element=r,e.parents=i,n.fire(\"NodeChange\",e))}}}),r(_,[],function(){function e(e,t,n){var r,i,o=n?\"lastChild\":\"firstChild\",a=n?\"prev\":\"next\";if(e[o])return e[o];if(e!==t){if(r=e[a])return r;for(i=e.parent;i&&i!==t;i=i.parent)if(r=i[a])return r}}function t(e,t){this.name=e,this.type=t,1===t&&(this.attributes=[],this.attributes.map={})}var n=/^[ \\t\\r\\n]*$/,r={\"#text\":3,\"#comment\":8,\"#cdata\":4,\"#pi\":7,\"#doctype\":10,\"#document-fragment\":11};return t.prototype={replace:function(e){var t=this;return e.parent&&e.remove(),t.insert(e,t),t.remove(),t},attr:function(e,t){var n=this,r,i,o;if(\"string\"!=typeof e){for(i in e)n.attr(i,e[i]);return n}if(r=n.attributes){if(t!==o){if(null===t){if(e in r.map)for(delete r.map[e],i=r.length;i--;)if(r[i].name===e)return r=r.splice(i,1),n;return n}if(e in r.map){for(i=r.length;i--;)if(r[i].name===e){r[i].value=t;break}}else r.push({name:e,value:t});return r.map[e]=t,n}return r.map[e]}},clone:function(){var e=this,n=new t(e.name,e.type),r,i,o,a,s;if(o=e.attributes){for(s=[],s.map={},r=0,i=o.length;i>r;r++)a=o[r],\"id\"!==a.name&&(s[s.length]={name:a.name,value:a.value},s.map[a.name]=a.value);n.attributes=s}return n.value=e.value,n.shortEnded=e.shortEnded,n},wrap:function(e){var t=this;return t.parent.insert(e,t),e.append(t),t},unwrap:function(){var e=this,t,n;for(t=e.firstChild;t;)n=t.next,e.insert(t,e,!0),t=n;e.remove()},remove:function(){var e=this,t=e.parent,n=e.next,r=e.prev;return t&&(t.firstChild===e?(t.firstChild=n,n&&(n.prev=null)):r.next=n,t.lastChild===e?(t.lastChild=r,r&&(r.next=null)):n.prev=r,e.parent=e.next=e.prev=null),e},append:function(e){var t=this,n;return e.parent&&e.remove(),n=t.lastChild,n?(n.next=e,e.prev=n,t.lastChild=e):t.lastChild=t.firstChild=e,e.parent=t,e},insert:function(e,t,n){var r;return e.parent&&e.remove(),r=t.parent||this,n?(t===r.firstChild?r.firstChild=e:t.prev.next=e,e.prev=t.prev,e.next=t,t.prev=e):(t===r.lastChild?r.lastChild=e:t.next.prev=e,e.next=t.next,e.prev=t,t.next=e),e.parent=r,e},getAll:function(t){var n=this,r,i=[];for(r=n.firstChild;r;r=e(r,n))r.name===t&&i.push(r);return i},empty:function(){var t=this,n,r,i;if(t.firstChild){for(n=[],i=t.firstChild;i;i=e(i,t))n.push(i);for(r=n.length;r--;)i=n[r],i.parent=i.firstChild=i.lastChild=i.next=i.prev=null}return t.firstChild=t.lastChild=null,t},isEmpty:function(t){var r=this,i=r.firstChild,o,a;if(i)do{if(1===i.type){if(i.attributes.map[\"data-mce-bogus\"])continue;if(t[i.name])return!1;for(o=i.attributes.length;o--;)if(a=i.attributes[o].name,\"name\"===a||0===a.indexOf(\"data-mce-bookmark\"))return!1}if(8===i.type)return!1;if(3===i.type&&!n.test(i.value))return!1}while(i=e(i,r));return!0},walk:function(t){return e(this,null,t)}},t.create=function(e,n){var i,o;if(i=new t(e,r[e]||1),n)for(o in n)i.attr(o,n[o]);return i},t}),r(E,[d],function(e){function t(e,t){return e?e.split(t||\" \"):[]}function n(e){function n(e,n,r){function i(e,t){var n={},r,i;for(r=0,i=e.length;i>r;r++)n[e[r]]=t||{};return n}var s,c,u,d=arguments;for(r=r||[],n=n||\"\",\"string\"==typeof r&&(r=t(r)),c=3;co;o++)i.attributes[n[o]]={},i.attributesOrder.push(n[o])}var a={},l,c,u,d,f,p;return i[e]?i[e]:(l=t(\"id accesskey class dir lang style tabindex title\"),c=t(\"address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul\"),u=t(\"a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd label map noscript object q s samp script select small span strong sub sup textarea u var #text #comment\"),\"html4\"!=e&&(l.push.apply(l,t(\"contenteditable contextmenu draggable dropzone hidden spellcheck translate\")),c.push.apply(c,t(\"article aside details dialog figure header footer hgroup section nav\")),u.push.apply(u,t(\"audio canvas command datalist mark meter output progress time wbr video ruby bdi keygen\"))),\"html5-strict\"!=e&&(l.push(\"xml:lang\"),p=t(\"acronym applet basefont big font strike tt\"),u.push.apply(u,p),s(p,function(e){n(e,\"\",u)}),f=t(\"center dir isindex noframes\"),c.push.apply(c,f),d=[].concat(c,u),s(f,function(e){n(e,\"\",d)})),d=d||[].concat(c,u),n(\"html\",\"manifest\",\"head body\"),n(\"head\",\"\",\"base command link meta noscript script style title\"),n(\"title hr noscript br\"),n(\"base\",\"href target\"),n(\"link\",\"href rel media hreflang type sizes hreflang\"),n(\"meta\",\"name http-equiv content charset\"),n(\"style\",\"media type scoped\"),n(\"script\",\"src async defer type charset\"),n(\"body\",\"onafterprint onbeforeprint onbeforeunload onblur onerror onfocus onhashchange onload onmessage onoffline ononline onpagehide onpageshow onpopstate onresize onscroll onstorage onunload\",d),n(\"address dt dd div caption\",\"\",d),n(\"h1 h2 h3 h4 h5 h6 pre p abbr code var samp kbd sub sup i b u bdo span legend em strong small s cite dfn\",\"\",u),n(\"blockquote\",\"cite\",d),n(\"ol\",\"reversed start type\",\"li\"),n(\"ul\",\"\",\"li\"),n(\"li\",\"value\",d),n(\"dl\",\"\",\"dt dd\"),n(\"a\",\"href target rel media hreflang type\",u),n(\"q\",\"cite\",u),n(\"ins del\",\"cite datetime\",d),n(\"img\",\"src sizes srcset alt usemap ismap width height\"),n(\"iframe\",\"src name width height\",d),n(\"embed\",\"src type width height\"),n(\"object\",\"data type typemustmatch name usemap form width height\",d,\"param\"),n(\"param\",\"name value\"),n(\"map\",\"name\",d,\"area\"),n(\"area\",\"alt coords shape href target rel media hreflang type\"),n(\"table\",\"border\",\"caption colgroup thead tfoot tbody tr\"+(\"html4\"==e?\" col\":\"\")),n(\"colgroup\",\"span\",\"col\"),n(\"col\",\"span\"),n(\"tbody thead tfoot\",\"\",\"tr\"),n(\"tr\",\"\",\"td th\"),n(\"td\",\"colspan rowspan headers\",d),n(\"th\",\"colspan rowspan headers scope abbr\",d),n(\"form\",\"accept-charset action autocomplete enctype method name novalidate target\",d),n(\"fieldset\",\"disabled form name\",d,\"legend\"),n(\"label\",\"form for\",u),n(\"input\",\"accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate formtarget height list max maxlength min multiple name pattern readonly required size src step type value width\"),n(\"button\",\"disabled form formaction formenctype formmethod formnovalidate formtarget name type value\",\"html4\"==e?d:u),n(\"select\",\"disabled form multiple name required size\",\"option optgroup\"),n(\"optgroup\",\"disabled label\",\"option\"),n(\"option\",\"disabled label selected value\"),n(\"textarea\",\"cols dirname disabled form maxlength name readonly required rows wrap\"),n(\"menu\",\"type label\",d,\"li\"),n(\"noscript\",\"\",d),\"html4\"!=e&&(n(\"wbr\"),n(\"ruby\",\"\",u,\"rt rp\"),n(\"figcaption\",\"\",d),n(\"mark rt rp summary bdi\",\"\",u),n(\"canvas\",\"width height\",d),n(\"video\",\"src crossorigin poster preload autoplay mediagroup loop muted controls width height buffered\",d,\"track source\"),n(\"audio\",\"src crossorigin preload autoplay mediagroup loop muted controls buffered volume\",d,\"track source\"),n(\"picture\",\"\",\"img source\"),n(\"source\",\"src srcset type media sizes\"),n(\"track\",\"kind src srclang label default\"),n(\"datalist\",\"\",u,\"option\"),n(\"article section nav aside header footer\",\"\",d),n(\"hgroup\",\"\",\"h1 h2 h3 h4 h5 h6\"),n(\"figure\",\"\",d,\"figcaption\"),n(\"time\",\"datetime\",u),n(\"dialog\",\"open\",d),n(\"command\",\"type label icon disabled checked radiogroup command\"),n(\"output\",\"for form name\",u),n(\"progress\",\"value max\",u),n(\"meter\",\"value min max low high optimum\",u),n(\"details\",\"open\",d,\"summary\"),n(\"keygen\",\"autofocus challenge disabled form keytype name\")),\"html5-strict\"!=e&&(r(\"script\",\"language xml:space\"),r(\"style\",\"xml:space\"),r(\"object\",\"declare classid code codebase codetype archive standby align border hspace vspace\"),r(\"embed\",\"align name hspace vspace\"),r(\"param\",\"valuetype type\"),r(\"a\",\"charset name rev shape coords\"),r(\"br\",\"clear\"),r(\"applet\",\"codebase archive code object alt name width height align hspace vspace\"),r(\"img\",\"name longdesc align border hspace vspace\"),r(\"iframe\",\"longdesc frameborder marginwidth marginheight scrolling align\"),r(\"font basefont\",\"size color face\"),r(\"input\",\"usemap align\"),r(\"select\",\"onchange\"),r(\"textarea\"),r(\"h1 h2 h3 h4 h5 h6 div p legend caption\",\"align\"),r(\"ul\",\"type compact\"),r(\"li\",\"type\"),r(\"ol dl menu dir\",\"compact\"),r(\"pre\",\"width xml:space\"),r(\"hr\",\"align noshade size width\"),r(\"isindex\",\"prompt\"),r(\"table\",\"summary width frame rules cellspacing cellpadding align bgcolor\"),r(\"col\",\"width align char charoff valign\"),r(\"colgroup\",\"width align char charoff valign\"),r(\"thead\",\"align char charoff valign\"),r(\"tr\",\"align char charoff valign bgcolor\"),r(\"th\",\"axis align char charoff valign nowrap bgcolor width height\"),r(\"form\",\"accept\"),r(\"td\",\"abbr axis scope align char charoff valign nowrap bgcolor width height\"),r(\"tfoot\",\"align char charoff valign\"),r(\"tbody\",\"align char charoff valign\"),r(\"area\",\"nohref\"),r(\"body\",\"background bgcolor text link vlink alink\")),\"html4\"!=e&&(r(\"input button select textarea\",\"autofocus\"),r(\"input textarea\",\"placeholder\"),\nr(\"a\",\"download\"),r(\"link script img\",\"crossorigin\"),r(\"iframe\",\"sandbox seamless allowfullscreen\")),s(t(\"a form meter progress dfn\"),function(e){a[e]&&delete a[e].children[e]}),delete a.caption.children.table,i[e]=a,a)}function r(e,t){var n;return e&&(n={},\"string\"==typeof e&&(e={\"*\":e}),s(e,function(e,r){n[r]=n[r.toUpperCase()]=\"map\"==t?a(e,/[, ]/):c(e,/[, ]/)})),n}var i={},o={},a=e.makeMap,s=e.each,l=e.extend,c=e.explode,u=e.inArray;return function(e){function o(t,n,r){var o=e[t];return o?o=a(o,/[, ]/,a(o.toUpperCase(),/[, ]/)):(o=i[t],o||(o=a(n,\" \",a(n.toUpperCase(),\" \")),o=l(o,r),i[t]=o)),o}function d(e){return new RegExp(\"^\"+e.replace(/([?+*])/g,\".$1\")+\"$\")}function f(e){var n,r,i,o,s,l,c,f,p,h,m,g,v,b,x,w,_,E,N,k=/^([#+\\-])?([^\\[!\\/]+)(?:\\/([^\\[!]+))?(?:(!?)\\[([^\\]]+)\\])?$/,S=/^([!\\-])?(\\w+::\\w+|[^=:<]+)?(?:([=:<])(.*))?$/,T=/[*?+]/;if(e)for(e=t(e,\",\"),y[\"@\"]&&(w=y[\"@\"].attributes,_=y[\"@\"].attributesOrder),n=0,r=e.length;r>n;n++)if(s=k.exec(e[n])){if(b=s[1],p=s[2],x=s[3],f=s[5],g={},v=[],l={attributes:g,attributesOrder:v},\"#\"===b&&(l.paddEmpty=!0),\"-\"===b&&(l.removeEmpty=!0),\"!\"===s[4]&&(l.removeEmptyAttrs=!0),w){for(E in w)g[E]=w[E];v.push.apply(v,_)}if(f)for(f=t(f,\"|\"),i=0,o=f.length;o>i;i++)if(s=S.exec(f[i])){if(c={},m=s[1],h=s[2].replace(/::/g,\":\"),b=s[3],N=s[4],\"!\"===m&&(l.attributesRequired=l.attributesRequired||[],l.attributesRequired.push(h),c.required=!0),\"-\"===m){delete g[h],v.splice(u(v,h),1);continue}b&&(\"=\"===b&&(l.attributesDefault=l.attributesDefault||[],l.attributesDefault.push({name:h,value:N}),c.defaultValue=N),\":\"===b&&(l.attributesForced=l.attributesForced||[],l.attributesForced.push({name:h,value:N}),c.forcedValue=N),\"<\"===b&&(c.validValues=a(N,\"?\"))),T.test(h)?(l.attributePatterns=l.attributePatterns||[],c.pattern=d(h),l.attributePatterns.push(c)):(g[h]||v.push(h),g[h]=c)}w||\"@\"!=p||(w=g,_=v),x&&(l.outputName=p,y[x]=l),T.test(p)?(l.pattern=d(p),C.push(l)):y[p]=l}}function p(e){y={},C=[],f(e),s(_,function(e,t){b[t]=e.children})}function h(e){var n=/^(~)?(.+)$/;e&&(i.text_block_elements=i.block_elements=null,s(t(e,\",\"),function(e){var t=n.exec(e),r=\"~\"===t[1],i=r?\"span\":\"div\",o=t[2];if(b[o]=b[i],H[o]=i,r||(R[o.toUpperCase()]={},R[o]={}),!y[o]){var a=y[i];a=l({},a),delete a.removeEmptyAttrs,delete a.removeEmpty,y[o]=a}s(b,function(e,t){e[i]&&(b[t]=e=l({},b[t]),e[o]=e[i])})}))}function m(e){var n=/^([+\\-]?)(\\w+)\\[([^\\]]+)\\]$/;e&&s(t(e,\",\"),function(e){var r=n.exec(e),i,o;r&&(o=r[1],i=o?b[r[2]]:b[r[2]]={\"#comment\":{}},i=b[r[2]],s(t(r[3],\"|\"),function(e){\"-\"===o?(b[r[2]]=i=l({},b[r[2]]),delete i[e]):i[e]={}}))})}function g(e){var t=y[e],n;if(t)return t;for(n=C.length;n--;)if(t=C[n],t.pattern.test(e))return t}var v=this,y={},b={},C=[],x,w,_,E,N,k,S,T,R,A,B,D,M,H={},L={};e=e||{},_=n(e.schema),e.verify_html===!1&&(e.valid_elements=\"*[*]\"),x=r(e.valid_styles),w=r(e.invalid_styles,\"map\"),T=r(e.valid_classes,\"map\"),E=o(\"whitespace_elements\",\"pre script noscript style textarea video audio iframe object\"),N=o(\"self_closing_elements\",\"colgroup dd dt li option p td tfoot th thead tr\"),k=o(\"short_ended_elements\",\"area base basefont br col frame hr img input isindex link meta param embed source wbr track\"),S=o(\"boolean_attributes\",\"checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls\"),A=o(\"non_empty_elements\",\"td th iframe video audio object script\",k),B=o(\"move_caret_before_on_enter_elements\",\"table\",A),D=o(\"text_block_elements\",\"h1 h2 h3 h4 h5 h6 p div address pre form blockquote center dir fieldset header footer article section hgroup aside nav figure\"),R=o(\"block_elements\",\"hr table tbody thead tfoot th tr td li ol ul caption dl dt dd noscript menu isindex option datalist select optgroup\",D),M=o(\"text_inline_elements\",\"span strong b em i font strike u var cite dfn code mark q sup sub samp\"),s((e.special||\"script noscript style textarea\").split(\" \"),function(e){L[e]=new RegExp(\"]*>\",\"gi\")}),e.valid_elements?p(e.valid_elements):(s(_,function(e,t){y[t]={attributes:e.attributes,attributesOrder:e.attributesOrder},b[t]=e.children}),\"html5\"!=e.schema&&s(t(\"strong/b em/i\"),function(e){e=t(e,\"/\"),y[e[1]].outputName=e[0]}),y.img.attributesDefault=[{name:\"alt\",value:\"\"}],s(t(\"ol ul sub sup blockquote span font a table tbody tr strong em b i\"),function(e){y[e]&&(y[e].removeEmpty=!0)}),s(t(\"p h1 h2 h3 h4 h5 h6 th td pre div address caption\"),function(e){y[e].paddEmpty=!0}),s(t(\"span\"),function(e){y[e].removeEmptyAttrs=!0})),h(e.custom_elements),m(e.valid_children),f(e.extended_valid_elements),m(\"+ol[ul|ol],+ul[ul|ol]\"),e.invalid_elements&&s(c(e.invalid_elements),function(e){y[e]&&delete y[e]}),g(\"span\")||f(\"span[!data-mce-type|*]\"),v.children=b,v.getValidStyles=function(){return x},v.getInvalidStyles=function(){return w},v.getValidClasses=function(){return T},v.getBoolAttrs=function(){return S},v.getBlockElements=function(){return R},v.getTextBlockElements=function(){return D},v.getTextInlineElements=function(){return M},v.getShortEndedElements=function(){return k},v.getSelfClosingElements=function(){return N},v.getNonEmptyElements=function(){return A},v.getMoveCaretBeforeOnEnterElements=function(){return B},v.getWhiteSpaceElements=function(){return E},v.getSpecialElements=function(){return L},v.isValidChild=function(e,t){var n=b[e];return!(!n||!n[t])},v.isValid=function(e,t){var n,r,i=g(e);if(i){if(!t)return!0;if(i.attributes[t])return!0;if(n=i.attributePatterns)for(r=n.length;r--;)if(n[r].pattern.test(e))return!0}return!1},v.getElementRule=g,v.getCustomElements=function(){return H},v.addValidElements=f,v.setValidElements=p,v.addCustomElements=h,v.addValidChildren=m,v.elements=y}}),r(N,[E,g,d],function(e,t,n){function r(e,t,n){var r=1,i,o,a,s;for(s=e.getShortEndedElements(),a=/<([!?\\/])?([A-Za-z0-9\\-_\\:\\.]+)((?:\\s+[^\"\\'>]+(?:(?:\"[^\"]*\")|(?:\\'[^\\']*\\')|[^>]*))*|\\/|\\s+)>/g,a.lastIndex=i=n;o=a.exec(t);){if(i=a.lastIndex,\"/\"===o[1])r--;else if(!o[1]){if(o[2]in s)continue;r++}if(0===r)break}return i}function i(i,a){function s(){}var l=this;i=i||{},l.schema=a=a||new e,i.fix_self_closing!==!1&&(i.fix_self_closing=!0),o(\"comment cdata text start end pi doctype\".split(\" \"),function(e){e&&(l[e]=i[e]||s)}),l.parse=function(e){function o(e){var t,n;for(t=p.length;t--&&p[t].name!==e;);if(t>=0){for(n=p.length-1;n>=t;n--)e=p[n],e.valid&&l.end(e.name);p.length=t}}function s(e,t,n,r,o){var a,s,l=/[\\s\\u0000-\\u001F]+/g;if(t=t.toLowerCase(),n=t in x?t:z(n||r||o||\"\"),_&&!y&&0!==t.indexOf(\"data-\")){if(a=T[t],!a&&R){for(s=R.length;s--&&(a=R[s],!a.pattern.test(t)););-1===s&&(a=null)}if(!a)return;if(a.validValues&&!(n in a.validValues))return}if(V[t]&&!i.allow_script_urls){var c=n.replace(l,\"\");try{c=decodeURIComponent(c)}catch(u){c=unescape(c)}if(U.test(c))return;if(!i.allow_html_data_urls&&$.test(c)&&!/^data:image\\//i.test(c))return}h.map[t]=n,h.push({name:t,value:n})}var l=this,c,u=0,d,f,p=[],h,m,g,v,y,b,C,x,w,_,E,N,k,S,T,R,A,B,D,M,H,L,P,O,I,F=0,z=t.decode,W,V=n.makeMap(\"src,href,data,background,formaction,poster\"),U=/((java|vb)script|mhtml):/i,$=/^data:/i;for(L=new RegExp(\"<(?:(?:!--([\\\\w\\\\W]*?)-->)|(?:!\\\\[CDATA\\\\[([\\\\w\\\\W]*?)\\\\]\\\\]>)|(?:!DOCTYPE([\\\\w\\\\W]*?)>)|(?:\\\\?([^\\\\s\\\\/<>]+) ?([\\\\w\\\\W]*?)[?/]>)|(?:\\\\/([^>]+)>)|(?:([A-Za-z0-9\\\\-_\\\\:\\\\.]+)((?:\\\\s+[^\\\"'>]+(?:(?:\\\"[^\\\"]*\\\")|(?:'[^']*')|[^>]*))*|\\\\/|\\\\s+)>))\",\"g\"),P=/([\\w:\\-]+)(?:\\s*=\\s*(?:(?:\\\"((?:[^\\\"])*)\\\")|(?:\\'((?:[^\\'])*)\\')|([^>\\s]+)))?/g,C=a.getShortEndedElements(),H=i.self_closing_elements||a.getSelfClosingElements(),x=a.getBoolAttrs(),_=i.validate,b=i.remove_internals,W=i.fix_self_closing,O=a.getSpecialElements();c=L.exec(e);){if(u0&&p[p.length-1].name===d&&o(d),!_||(E=a.getElementRule(d))){if(N=!0,_&&(T=E.attributes,R=E.attributePatterns),(S=c[8])?(y=-1!==S.indexOf(\"data-mce-type\"),y&&b&&(N=!1),h=[],h.map={},S.replace(P,s)):(h=[],h.map={}),_&&!y){if(A=E.attributesRequired,B=E.attributesDefault,D=E.attributesForced,M=E.removeEmptyAttrs,M&&!h.length&&(N=!1),D)for(m=D.length;m--;)k=D[m],v=k.name,I=k.value,\"{$uid}\"===I&&(I=\"mce_\"+F++),h.map[v]=I,h.push({name:v,value:I});if(B)for(m=B.length;m--;)k=B[m],v=k.name,v in h.map||(I=k.value,\"{$uid}\"===I&&(I=\"mce_\"+F++),h.map[v]=I,h.push({name:v,value:I}));if(A){for(m=A.length;m--&&!(A[m]in h.map););-1===m&&(N=!1)}if(k=h.map[\"data-mce-bogus\"]){if(\"all\"===k){u=r(a,e,L.lastIndex),L.lastIndex=u;continue}N=!1}}N&&l.start(d,h,w)}else N=!1;if(f=O[d]){f.lastIndex=u=c.index+c[0].length,(c=f.exec(e))?(N&&(g=e.substr(u,c.index-u)),u=c.index+c[0].length):(g=e.substr(u),u=e.length),N&&(g.length>0&&l.text(g,!0),l.end(d)),L.lastIndex=u;continue}w||(S&&S.indexOf(\"/\")==S.length-1?N&&l.end(d):p.push({name:d,valid:N}))}else(d=c[1])?(\">\"===d.charAt(0)&&(d=\" \"+d),i.allow_conditional_comments||\"[if\"!==d.substr(0,3)||(d=\" \"+d),l.comment(d)):(d=c[2])?l.cdata(d):(d=c[3])?l.doctype(d):(d=c[4])&&l.pi(d,c[5]);u=c.index+c[0].length}for(u=0;m--)d=p[m],d.valid&&l.end(d.name)}}var o=n.each;return i.findEndTag=r,i}),r(k,[_,E,N,d],function(e,t,n,r){var i=r.makeMap,o=r.each,a=r.explode,s=r.extend;return function(r,l){function c(t){var n,r,o,a,s,c,d,f,p,h,m,g,v,y;for(m=i(\"tr,td,th,tbody,thead,tfoot,table\"),h=l.getNonEmptyElements(),g=l.getTextBlockElements(),n=0;n1){for(a.reverse(),s=c=u.filterNode(a[0].clone()),p=0;p0?(t.value=n,t=t.prev):(r=t.prev,t.remove(),t=r)}function g(e){var t,n={};for(t in e)\"li\"!==t&&\"p\"!=t&&(n[t]=e[t]);return n}var v,y,b,C,x,w,_,E,N,k,S,T,R,A=[],B,D,M,H,L,P,O,I;if(o=o||{},p={},h={},T=s(i(\"script,style,head,html,body,title,meta,param\"),l.getBlockElements()),O=l.getNonEmptyElements(),P=l.children,S=r.validate,I=\"forced_root_block\"in o?o.forced_root_block:r.forced_root_block,L=l.getWhiteSpaceElements(),R=/^[ \\t\\r\\n]+/,D=/[ \\t\\r\\n]+$/,M=/[ \\t\\r\\n]+/g,H=/^[ \\t\\r\\n]+$/,v=new n({validate:S,allow_script_urls:r.allow_script_urls,allow_conditional_comments:r.allow_conditional_comments,self_closing_elements:g(l.getSelfClosingElements()),cdata:function(e){b.append(u(\"#cdata\",4)).value=e},text:function(e,t){var n;B||(e=e.replace(M,\" \"),b.lastChild&&T[b.lastChild.name]&&(e=e.replace(R,\"\"))),0!==e.length&&(n=u(\"#text\",3),n.raw=!!t,b.append(n).value=e)},comment:function(e){b.append(u(\"#comment\",8)).value=e},pi:function(e,t){b.append(u(e,7)).value=t,m(b)},doctype:function(e){var t;t=b.append(u(\"#doctype\",10)),t.value=e,m(b)},start:function(e,t,n){var r,i,o,a,s;if(o=S?l.getElementRule(e):{}){for(r=u(o.outputName||e,1),r.attributes=t,r.shortEnded=n,b.append(r),s=P[b.name],s&&P[r.name]&&!s[r.name]&&A.push(r),i=f.length;i--;)a=f[i].name,a in t.map&&(N=h[a],N?N.push(r):h[a]=[r]);T[e]&&m(r),n||(b=r),!B&&L[e]&&(B=!0)}},end:function(t){var n,r,i,o,a;if(r=S?l.getElementRule(t):{}){if(T[t]&&!B){if(n=b.firstChild,n&&3===n.type)if(i=n.value.replace(R,\"\"),i.length>0)n.value=i,n=n.next;else for(o=n.next,n.remove(),n=o;n&&3===n.type;)i=n.value,o=n.next,(0===i.length||H.test(i))&&(n.remove(),n=o),n=o;if(n=b.lastChild,n&&3===n.type)if(i=n.value.replace(D,\"\"),i.length>0)n.value=i,n=n.prev;else for(o=n.prev,n.remove(),n=o;n&&3===n.type;)i=n.value,o=n.prev,(0===i.length||H.test(i))&&(n.remove(),n=o),n=o}if(B&&L[t]&&(B=!1),(r.removeEmpty||r.paddEmpty)&&b.isEmpty(O))if(r.paddEmpty)b.empty().append(new e(\"#text\",\"3\")).value=\"\\xa0\";else if(!b.attributes.map.name&&!b.attributes.map.id)return a=b.parent,T[b.name]?b.empty().remove():b.unwrap(),void(b=a);b=b.parent}}},l),y=b=new e(o.context||r.root_name,11),v.parse(t),S&&A.length&&(o.context?o.invalid=!0:c(A)),I&&(\"body\"==y.name||o.isRootContent)&&a(),!o.invalid){for(k in p){for(N=d[k],C=p[k],_=C.length;_--;)C[_].parent||C.splice(_,1);for(x=0,w=N.length;w>x;x++)N[x](C,k,o)}for(x=0,w=f.length;w>x;x++)if(N=f[x],N.name in h){for(C=h[N.name],_=C.length;_--;)C[_].parent||C.splice(_,1);for(_=0,E=N.callbacks.length;E>_;_++)N.callbacks[_](C,N.name,o)}}return y},r.remove_trailing_brs&&u.addNodeFilter(\"br\",function(t){var n,r=t.length,i,o=s({},l.getBlockElements()),a=l.getNonEmptyElements(),c,u,d,f,p,h;for(o.body=1,n=0;r>n;n++)if(i=t[n],c=i.parent,o[i.parent.name]&&i===c.lastChild){for(d=i.prev;d;){if(f=d.name,\"span\"!==f||\"bookmark\"!==d.attr(\"data-mce-type\")){if(\"br\"!==f)break;if(\"br\"===f){i=null;break}}d=d.prev}i&&(i.remove(),c.isEmpty(a)&&(p=l.getElementRule(c.name),p&&(p.removeEmpty?c.remove():p.paddEmpty&&(c.empty().append(new e(\"#text\",3)).value=\"\\xa0\"))))}else{for(u=i;c&&c.firstChild===u&&c.lastChild===u&&(u=c,!o[c.name]);)c=c.parent;u===c&&(h=new e(\"#text\",3),h.value=\"\\xa0\",i.replace(h))}}),r.allow_html_in_named_anchor||u.addAttributeFilter(\"id,name\",function(e){for(var t=e.length,n,r,i,o;t--;)if(o=e[t],\"a\"===o.name&&o.firstChild&&!o.attr(\"href\")){i=o.parent,n=o.lastChild;do r=n.prev,i.insert(n,o),n=r;while(n)}}),r.validate&&l.getValidClasses()&&u.addAttributeFilter(\"class\",function(e){for(var t=e.length,n,r,i,o,a,s=l.getValidClasses(),c,u;t--;){for(n=e[t],r=n.attr(\"class\").split(\" \"),a=\"\",i=0;i0&&(f=r[r.length-1],f.length>0&&\"\\n\"!==f&&r.push(\"\\n\")),r.push(\"<\",e),t)for(c=0,u=t.length;u>c;c++)d=t[c],r.push(\" \",d.name,'=\"',s(d.value,!0),'\"');!n||l?r[r.length]=\">\":r[r.length]=\" />\",n&&i&&a[e]&&r.length>0&&(f=r[r.length-1],f.length>0&&\"\\n\"!==f&&r.push(\"\\n\"))},end:function(e){var t;r.push(\"\"),i&&a[e]&&r.length>0&&(t=r[r.length-1],t.length>0&&\"\\n\"!==t&&r.push(\"\\n\"))},text:function(e,t){e.length>0&&(r[r.length]=t?e:s(e))},cdata:function(e){r.push(\"\")},comment:function(e){r.push(\"\")},pi:function(e,t){t?r.push(\"\"):r.push(\"\"),i&&r.push(\"\\n\")},doctype:function(e){r.push(\"\",i?\"\\n\":\"\")},reset:function(){r.length=0},getContent:function(){return r.join(\"\").replace(/\\n$/,\"\")}}}}),r(T,[S,E],function(e,t){return function(n,r){var i=this,o=new e(n);n=n||{},n.validate=\"validate\"in n?n.validate:!0,i.schema=r=r||new t,i.writer=o,i.serialize=function(e){function t(e){var n=i[e.type],s,l,c,u,d,f,p,h,m;if(n)n(e);else{if(s=e.name,l=e.shortEnded,c=e.attributes,a&&c&&c.length>1){for(f=[],f.map={},m=r.getElementRule(e.name),p=0,h=m.attributesOrder.length;h>p;p++)u=m.attributesOrder[p],u in c.map&&(d=c.map[u],f.map[u]=d,f.push({name:u,value:d}));for(p=0,h=c.length;h>p;p++)u=c[p].name,u in f.map||(d=c.map[u],f.map[u]=d,f.push({name:u,value:d}));c=f}if(o.start(e.name,c,l),!l){if(e=e.firstChild)do t(e);while(e=e.next);o.end(s)}}}var i,a;return a=n.validate,i={3:function(e){o.text(e.value,e.raw)},8:function(e){o.comment(e.value)},7:function(e){o.pi(e.name,e.value)},10:function(e){o.doctype(e.value)},4:function(e){o.cdata(e.value)},11:function(e){if(e=e.firstChild)do t(e);while(e=e.next)}},o.reset(),1!=e.type||n.inner?i[11](e):t(e),o.getContent()}}}),r(R,[y,k,g,T,_,E,u,d],function(e,t,n,r,i,o,a,s){var l=s.each,c=s.trim,u=e.DOM;return function(e,i){var s,d,f;return i&&(s=i.dom,d=i.schema),s=s||u,d=d||new o(e),e.entity_encoding=e.entity_encoding||\"named\",e.remove_trailing_brs=\"remove_trailing_brs\"in e?e.remove_trailing_brs:!0,f=new t(e,d),f.addAttributeFilter(\"data-mce-tabindex\",function(e,t){for(var n=e.length,r;n--;)r=e[n],r.attr(\"tabindex\",r.attributes.map[\"data-mce-tabindex\"]),r.attr(t,null)}),f.addAttributeFilter(\"src,href,style\",function(t,n){for(var r=t.length,i,o,a=\"data-mce-\"+n,l=e.url_converter,c=e.url_converter_scope,u;r--;)i=t[r],o=i.attributes.map[a],o!==u?(i.attr(n,o.length>0?o:null),i.attr(a,null)):(o=i.attributes.map[n],\"style\"===n?o=s.serializeStyle(s.parseStyle(o),i.name):l&&(o=l.call(c,o,n,i.name)),i.attr(n,o.length>0?o:null))}),f.addAttributeFilter(\"class\",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.attr(\"class\"),r&&(r=n.attr(\"class\").replace(/(?:^|\\s)mce-item-\\w+(?!\\S)/g,\"\"),n.attr(\"class\",r.length>0?r:null))}),f.addAttributeFilter(\"data-mce-type\",function(e,t,n){for(var r=e.length,i;r--;)i=e[r],\"bookmark\"!==i.attributes.map[\"data-mce-type\"]||n.cleanup||i.remove()}),f.addNodeFilter(\"noscript\",function(e){for(var t=e.length,r;t--;)r=e[t].firstChild,r&&(r.value=n.decode(r.value))}),f.addNodeFilter(\"script,style\",function(e,t){function n(e){return e.replace(/()/g,\"\\n\").replace(/^[\\r\\n]*|[\\r\\n]*$/g,\"\").replace(/^\\s*(()?|\\s*\\/\\/\\s*\\]\\]>(-->)?|\\/\\/\\s*(-->)?|\\]\\]>|\\/\\*\\s*-->\\s*\\*\\/|\\s*-->\\s*)\\s*$/g,\"\")}for(var r=e.length,i,o,a;r--;)i=e[r],o=i.firstChild?i.firstChild.value:\"\",\"script\"===t?(a=i.attr(\"type\"),a&&i.attr(\"type\",\"mce-no/type\"==a?null:a.replace(/^mce\\-/,\"\")),o.length>0&&(i.firstChild.value=\"// \")):o.length>0&&(i.firstChild.value=\"\")}),f.addNodeFilter(\"#comment\",function(e){for(var t=e.length,n;t--;)n=e[t],0===n.value.indexOf(\"[CDATA[\")?(n.name=\"#cdata\",n.type=4,n.value=n.value.replace(/^\\[CDATA\\[|\\]\\]$/g,\"\")):0===n.value.indexOf(\"mce:protected \")&&(n.name=\"#text\",n.type=3,n.raw=!0,n.value=unescape(n.value).substr(14))}),f.addNodeFilter(\"xml:namespace,input\",function(e,t){for(var n=e.length,r;n--;)r=e[n],7===r.type?r.remove():1===r.type&&(\"input\"!==t||\"type\"in r.attributes.map||r.attr(\"type\",\"text\"))}),e.fix_list_elements&&f.addNodeFilter(\"ul,ol\",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.parent,(\"ul\"===r.name||\"ol\"===r.name)&&n.prev&&\"li\"===n.prev.name&&n.prev.append(n)}),f.addAttributeFilter(\"data-mce-src,data-mce-href,data-mce-style,data-mce-selected,data-mce-expando,data-mce-type,data-mce-resize\",function(e,t){for(var n=e.length;n--;)e[n].attr(t,null)}),{schema:d,addNodeFilter:f.addNodeFilter,addAttributeFilter:f.addAttributeFilter,serialize:function(t,n){var i=this,o,u,p,h,m;return a.ie&&s.select(\"script,style,select,map\").length>0?(m=t.innerHTML,t=t.cloneNode(!1),s.setHTML(t,m)):t=t.cloneNode(!0),o=t.ownerDocument.implementation,o.createHTMLDocument&&(u=o.createHTMLDocument(\"\"),l(\"BODY\"==t.nodeName?t.childNodes:[t],function(e){u.body.appendChild(u.importNode(e,!0))}),t=\"BODY\"!=t.nodeName?u.body.firstChild:u.body,p=s.doc,s.doc=u),n=n||{},n.format=n.format||\"html\",n.selection&&(n.forced_root_block=\"\"),n.no_events||(n.node=t,i.onPreProcess(n)),h=new r(e,d),n.content=h.serialize(f.parse(c(n.getInner?t.innerHTML:s.getOuterHTML(t)),n)),n.cleanup||(n.content=n.content.replace(/\\uFEFF/g,\"\")),n.no_events||i.onPostProcess(n),p&&(s.doc=p),n.node=null,n.content},addRules:function(e){d.addValidElements(e)},setRules:function(e){d.setValidElements(e)},onPreProcess:function(e){i&&i.fire(\"PreProcess\",e)},onPostProcess:function(e){i&&i.fire(\"PostProcess\",e)}}}}),r(A,[],function(){function e(e){function t(t,n){var r,i=0,o,a,s,l,c,u,d=-1,f;if(r=t.duplicate(),r.collapse(n),f=r.parentElement(),f.ownerDocument===e.dom.doc){for(;\"false\"===f.contentEditable;)f=f.parentNode;if(!f.hasChildNodes())return{node:f,inside:1};for(s=f.children,o=s.length-1;o>=i;)if(u=Math.floor((i+o)/2),l=s[u],r.moveToElementText(l),d=r.compareEndPoints(n?\"StartToStart\":\"EndToEnd\",t),d>0)o=u-1;else{if(!(0>d))return{node:l};i=u+1}if(0>d)for(l?r.collapse(!1):(r.moveToElementText(f),r.collapse(!0),l=f,a=!0),c=0;0!==r.compareEndPoints(n?\"StartToStart\":\"StartToEnd\",t)&&0!==r.move(\"character\",1)&&f==r.parentElement();)c++;else for(r.collapse(!0),c=0;0!==r.compareEndPoints(n?\"StartToStart\":\"StartToEnd\",t)&&0!==r.move(\"character\",-1)&&f==r.parentElement();)c++;return{node:l,position:d,offset:c,inside:a}}}function n(){function n(e){var n=t(o,e),r,i,s=0,l,c,u;if(r=n.node,i=n.offset,n.inside&&!r.hasChildNodes())return void a[e?\"setStart\":\"setEnd\"](r,0);if(i===c)return void a[e?\"setStartBefore\":\"setEndAfter\"](r);if(n.position<0){if(l=n.inside?r.firstChild:r.nextSibling,!l)return void a[e?\"setStartAfter\":\"setEndAfter\"](r);if(!i)return void(3==l.nodeType?a[e?\"setStart\":\"setEnd\"](l,0):a[e?\"setStartBefore\":\"setEndBefore\"](l));for(;l;){if(3==l.nodeType&&(u=l.nodeValue,s+=u.length,s>=i)){r=l,s-=i,s=u.length-s;break}l=l.nextSibling}}else{if(l=r.previousSibling,!l)return a[e?\"setStartBefore\":\"setEndBefore\"](r);if(!i)return void(3==r.nodeType?a[e?\"setStart\":\"setEnd\"](l,r.nodeValue.length):a[e?\"setStartAfter\":\"setEndAfter\"](l));for(;l;){if(3==l.nodeType&&(s+=l.nodeValue.length,s>=i)){r=l,s-=i;break}l=l.previousSibling}}a[e?\"setStart\":\"setEnd\"](r,s)}var o=e.getRng(),a=i.createRng(),s,l,c,u,d;if(s=o.item?o.item(0):o.parentElement(),s.ownerDocument!=i.doc)return a;if(l=e.isCollapsed(),o.item)return a.setStart(s.parentNode,i.nodeIndex(s)),a.setEnd(a.startContainer,a.startOffset+1),a;try{n(!0),l||n()}catch(f){if(-2147024809!=f.number)throw f;d=r.getBookmark(2),c=o.duplicate(),c.collapse(!0),s=c.parentElement(),l||(c=o.duplicate(),c.collapse(!1),u=c.parentElement(),u.innerHTML=u.innerHTML),s.innerHTML=s.innerHTML,r.moveToBookmark(d),o=e.getRng(),n(!0),l||n()}return a}var r=this,i=e.dom,o=!1;this.getBookmark=function(n){function r(e){var t,n,r,o,a=[];for(t=e.parentNode,n=i.getRoot().parentNode;t!=n&&9!==t.nodeType;){for(r=t.children,o=r.length;o--;)if(e===r[o]){a.push(o);break}e=t,t=t.parentNode}return a}function o(e){var n;return n=t(a,e),n?{position:n.position,offset:n.offset,indexes:r(n.node),inside:n.inside}:void 0}var a=e.getRng(),s={};return 2===n&&(a.item?s.start={ctrl:!0,indexes:r(a.item(0))}:(s.start=o(!0),e.isCollapsed()||(s.end=o()))),s},this.moveToBookmark=function(e){function t(e){var t,n,r,o;for(t=i.getRoot(),n=e.length-1;n>=0;n--)o=t.children,r=e[n],r<=o.length-1&&(t=o[r]);return t}function n(n){var i=e[n?\"start\":\"end\"],a,s,l,c;i&&(a=i.position>0,s=o.createTextRange(),s.moveToElementText(t(i.indexes)),c=i.offset,c!==l?(s.collapse(i.inside||a),s.moveStart(\"character\",a?-c:c)):s.collapse(n),r.setEndPoint(n?\"StartToStart\":\"EndToStart\",s),n&&r.collapse(!0))}var r,o=i.doc.body;e.start&&(e.start.ctrl?(r=o.createControlRange(),r.addElement(t(e.start.indexes)),r.select()):(r=o.createTextRange(),n(!0),n(),r.select()))},this.addRange=function(t){function n(e){var t,n,a,d,h;a=i.create(\"a\"),t=e?s:c,n=e?l:u,d=r.duplicate(),(t==f||t==f.documentElement)&&(t=p,n=0),3==t.nodeType?(t.parentNode.insertBefore(a,t),d.moveToElementText(a),d.moveStart(\"character\",n),i.remove(a),r.setEndPoint(e?\"StartToStart\":\"EndToEnd\",d)):(h=t.childNodes,h.length?(n>=h.length?i.insertAfter(a,h[h.length-1]):t.insertBefore(a,h[n]),d.moveToElementText(a)):t.canHaveHTML&&(t.innerHTML=\"\",a=t.firstChild,d.moveToElementText(a),d.collapse(o)),r.setEndPoint(e?\"StartToStart\":\"EndToEnd\",d),i.remove(a))}var r,a,s,l,c,u,d,f=e.dom.doc,p=f.body,h,m;if(s=t.startContainer,l=t.startOffset,c=t.endContainer,u=t.endOffset,r=p.createTextRange(),s==c&&1==s.nodeType){if(l==u&&!s.hasChildNodes()){if(s.canHaveHTML)return d=s.previousSibling,d&&!d.hasChildNodes()&&i.isBlock(d)?d.innerHTML=\"\":d=null,s.innerHTML=\"\",r.moveToElementText(s.lastChild),r.select(),i.doc.selection.clear(),s.innerHTML=\"\",void(d&&(d.innerHTML=\"\"));l=i.nodeIndex(s),s=s.parentNode}if(l==u-1)try{if(m=s.childNodes[l],a=p.createControlRange(),a.addElement(m),a.select(),h=e.getRng(),h.item&&m===h.item(0))return}catch(g){}}n(!0),n(),r.select()},this.getRangeAt=n}return e}),r(B,[u],function(e){return{BACKSPACE:8,DELETE:46,DOWN:40,ENTER:13,LEFT:37,RIGHT:39,SPACEBAR:32,TAB:9,UP:38,modifierPressed:function(e){return e.shiftKey||e.ctrlKey||e.altKey||this.metaKeyPressed(e)},metaKeyPressed:function(t){return e.mac?t.metaKey:t.ctrlKey&&!t.altKey}}}),r(D,[B,d,u],function(e,t,n){return function(r,i){function o(e){var t=i.settings.object_resizing;return t===!1||n.iOS?!1:(\"string\"!=typeof t&&(t=\"table,img,div\"),\"false\"===e.getAttribute(\"data-mce-resize\")?!1:i.dom.is(e,t))}function a(t){var n,r,o,a,s;n=t.screenX-T,r=t.screenY-R,P=n*k[2]+D,O=r*k[3]+M,P=5>P?5:P,O=5>O?5:O,o=\"IMG\"==w.nodeName&&i.settings.resize_img_proportional!==!1?!e.modifierPressed(t):e.modifierPressed(t)||\"IMG\"==w.nodeName&&k[2]*k[3]!==0,o&&(W(n)>W(r)?(O=V(P*H),P=V(O/H)):(P=V(O/H),O=V(P*H))),C.setStyles(_,{width:P,height:O}),a=k.startPos.x+n,s=k.startPos.y+r,a=a>0?a:0,s=s>0?s:0,C.setStyles(E,{left:a,top:s,display:\"block\"}),E.innerHTML=P+\" × \"+O,k[2]<0&&_.clientWidth<=P&&C.setStyle(_,\"left\",A+(D-P)),k[3]<0&&_.clientHeight<=O&&C.setStyle(_,\"top\",B+(M-O)),n=U.scrollWidth-$,r=U.scrollHeight-q,n+r!==0&&C.setStyles(E,{left:a-n,top:s-r}),L||(i.fire(\"ObjectResizeStart\",{target:w,width:D,height:M}),L=!0)}function s(){function e(e,t){t&&(w.style[e]||!i.schema.isValid(w.nodeName.toLowerCase(),e)?C.setStyle(w,e,t):C.setAttrib(w,e,t))}L=!1,e(\"width\",P),e(\"height\",O),C.unbind(I,\"mousemove\",a),C.unbind(I,\"mouseup\",s),F!=I&&(C.unbind(F,\"mousemove\",a),C.unbind(F,\"mouseup\",s)),C.remove(_),C.remove(E),z&&\"TABLE\"!=w.nodeName||l(w),i.fire(\"ObjectResized\",{target:w,width:P,height:O}),C.setAttrib(w,\"style\",C.getAttrib(w,\"style\")),i.nodeChanged()}function l(e,t,r){var l,u,d,f,p;g(),l=C.getPos(e,U),A=l.x,B=l.y,p=e.getBoundingClientRect(),u=p.width||p.right-p.left,d=p.height||p.bottom-p.top,w!=e&&(m(),w=e,P=O=0),f=i.fire(\"ObjectSelected\",{target:e}),o(e)&&!f.isDefaultPrevented()?x(N,function(e,i){function o(t){T=t.screenX,R=t.screenY,D=w.clientWidth,M=w.clientHeight,H=M/D,k=e,e.startPos={x:u*e[0]+A,y:d*e[1]+B},$=U.scrollWidth,q=U.scrollHeight,_=w.cloneNode(!0),C.addClass(_,\"mce-clonedresizable\"),C.setAttrib(_,\"data-mce-bogus\",\"all\"),_.contentEditable=!1,_.unSelectabe=!0,C.setStyles(_,{left:A,top:B,margin:0}),_.removeAttribute(\"data-mce-selected\"),U.appendChild(_),C.bind(I,\"mousemove\",a),C.bind(I,\"mouseup\",s),F!=I&&(C.bind(F,\"mousemove\",a),C.bind(F,\"mouseup\",s)),E=C.add(U,\"div\",{\"class\":\"mce-resize-helper\",\"data-mce-bogus\":\"all\"},D+\" × \"+M)}var l,c;return t?void(i==t&&o(r)):(l=C.get(\"mceResizeHandle\"+i),l?C.show(l):(c=U,l=C.add(c,\"div\",{id:\"mceResizeHandle\"+i,\"data-mce-bogus\":\"all\",\"class\":\"mce-resizehandle\",unselectable:!0,style:\"cursor:\"+i+\"-resize; margin:0; padding:0\"}),n.ie&&(l.contentEditable=!1)),e.elm||(C.bind(l,\"mousedown\",function(e){e.stopImmediatePropagation(),e.preventDefault(),o(e)}),e.elm=l),void C.setStyles(l,{left:u*e[0]+A-l.offsetWidth/2,top:d*e[1]+B-l.offsetHeight/2}))}):c(),w.setAttribute(\"data-mce-selected\",\"1\")}function c(){var e,t;g(),w&&w.removeAttribute(\"data-mce-selected\");for(e in N)t=C.get(\"mceResizeHandle\"+e),t&&(C.unbind(t),C.remove(t))}function u(e){function t(e,t){if(e)do if(e===t)return!0;while(e=e.parentNode)}var n,i;if(!L)return x(C.select(\"img[data-mce-selected],hr[data-mce-selected]\"),function(e){e.removeAttribute(\"data-mce-selected\")}),i=\"mousedown\"==e.type?e.target:r.getNode(),i=C.$(i).closest(z?\"table\":\"table,img,hr\")[0],t(i,U)&&(v(),n=r.getStart(!0),t(n,i)&&t(r.getEnd(!0),i)&&(!z||i!=n&&\"IMG\"!==n.nodeName))?void l(i):void c()}function d(e,t,n){e&&e.attachEvent&&e.attachEvent(\"on\"+t,n)}function f(e,t,n){e&&e.detachEvent&&e.detachEvent(\"on\"+t,n)}function p(e){var t=e.srcElement,n,r,o,a,s,c,u;n=t.getBoundingClientRect(),c=S.clientX-n.left,u=S.clientY-n.top;for(r in N)if(o=N[r],a=t.offsetWidth*o[0],s=t.offsetHeight*o[1],W(a-c)<8&&W(s-u)<8){k=o;break}L=!0,i.fire(\"ObjectResizeStart\",{target:w,width:w.clientWidth,height:w.clientHeight}),i.getDoc().selection.empty(),l(t,r,S)}function h(e){var t=e.srcElement;if(t!=w){if(i.fire(\"ObjectSelected\",{target:t}),m(),0===t.id.indexOf(\"mceResizeHandle\"))return void(e.returnValue=!1);(\"IMG\"==t.nodeName||\"TABLE\"==t.nodeName)&&(c(),w=t,d(t,\"resizestart\",p))}}function m(){f(w,\"resizestart\",p)}function g(){for(var e in N){var t=N[e];t.elm&&(C.unbind(t.elm),delete t.elm)}}function v(){try{i.getDoc().execCommand(\"enableObjectResizing\",!1,!1)}catch(e){}}function y(e){var t;if(z){t=I.body.createControlRange();try{return t.addElement(e),t.select(),!0}catch(n){}}}function b(){w=_=null,z&&(m(),f(U,\"controlselect\",h))}var C=i.dom,x=t.each,w,_,E,N,k,S,T,R,A,B,D,M,H,L,P,O,I=i.getDoc(),F=document,z=n.ie&&n.ie<11,W=Math.abs,V=Math.round,U=i.getBody(),$,q;N={n:[.5,0,0,-1],e:[1,.5,1,0],s:[.5,1,0,1],w:[0,.5,-1,0],nw:[0,0,-1,-1],ne:[1,0,1,-1],se:[1,1,1,1],sw:[0,1,-1,1]};var j=\".mce-content-body\";return i.contentStyles.push(j+\" div.mce-resizehandle {position: absolute;border: 1px solid black;background: #FFF;width: 5px;height: 5px;z-index: 10000}\"+j+\" .mce-resizehandle:hover {background: #000}\"+j+\" img[data-mce-selected], hr[data-mce-selected] {outline: 1px solid black;resize: none}\"+j+\" .mce-clonedresizable {position: absolute;\"+(n.gecko?\"\":\"outline: 1px dashed black;\")+\"opacity: .5;filter: alpha(opacity=50);z-index: 10000}\"+j+\" .mce-resize-helper {background: #555;background: rgba(0,0,0,0.75);border-radius: 3px;border: 1px;color: white;display: none;font-family: sans-serif;font-size: 12px;white-space: nowrap;line-height: 14px;margin: 5px 10px;padding: 5px;position: absolute;z-index: 10001}\"),i.on(\"init\",function(){z?(i.on(\"ObjectResized\",function(e){\"TABLE\"!=e.target.nodeName&&(c(),y(e.target))}),d(U,\"controlselect\",h),i.on(\"mousedown\",function(e){S=e})):(v(),n.ie>=11&&(i.on(\"mouseup\",function(e){var t=e.target.nodeName;!L&&/^(TABLE|IMG|HR)$/.test(t)&&(i.selection.select(e.target,\"TABLE\"==t),i.nodeChanged())}),i.dom.bind(U,\"mscontrolselect\",function(e){/^(TABLE|IMG|HR)$/.test(e.target.nodeName)&&(e.preventDefault(),\"IMG\"==e.target.tagName&&window.setTimeout(function(){i.selection.select(e.target)},0))}))),i.on(\"nodechange ResizeEditor\",u),i.on(\"keydown keyup\",function(e){w&&\"TABLE\"==w.nodeName&&u(e)}),i.on(\"hide\",c)}),i.on(\"remove\",g),{isResizable:o,showResizeRect:l,hideResizeRect:c,updateResizeRect:u,\ncontrolSelect:y,destroy:b}}}),r(M,[u,d],function(e,t){function n(n){var r=n.dom;this.getBookmark=function(e,i){function o(e,n){var i=0;return t.each(r.select(e),function(e,t){e==n&&(i=t)}),i}function a(e){function t(t){var n,r,i,o=t?\"start\":\"end\";n=e[o+\"Container\"],r=e[o+\"Offset\"],1==n.nodeType&&\"TR\"==n.nodeName&&(i=n.childNodes,n=i[Math.min(t?r:r-1,i.length-1)],n&&(r=t?0:n.childNodes.length,e[\"set\"+(t?\"Start\":\"End\")](n,r)))}return t(!0),t(),e}function s(){function e(e,t){var n=e[t?\"startContainer\":\"endContainer\"],a=e[t?\"startOffset\":\"endOffset\"],s=[],l,c,u=0;if(3==n.nodeType){if(i)for(l=n.previousSibling;l&&3==l.nodeType;l=l.previousSibling)a+=l.nodeValue.length;s.push(a)}else c=n.childNodes,a>=c.length&&c.length&&(u=1,a=Math.max(0,c.length-1)),s.push(r.nodeIndex(c[a],i)+u);for(;n&&n!=o;n=n.parentNode)s.push(r.nodeIndex(n,i));return s}var t=n.getRng(!0),o=r.getRoot(),a={};return a.start=e(t,!0),n.isCollapsed()||(a.end=e(t)),a}var l,c,u,d,f,p,h=\"\",m;if(2==e)return p=n.getNode(),f=p?p.nodeName:null,\"IMG\"==f?{name:f,index:o(f,p)}:n.tridentSel?n.tridentSel.getBookmark(e):s();if(e)return{rng:n.getRng()};if(l=n.getRng(),u=r.uniqueId(),d=n.isCollapsed(),m=\"overflow:hidden;line-height:0px\",l.duplicate||l.item){if(l.item)return p=l.item(0),f=p.nodeName,{name:f,index:o(f,p)};c=l.duplicate();try{l.collapse(),l.pasteHTML(''+h+\"\"),d||(c.collapse(!1),l.moveToElementText(c.parentElement()),0===l.compareEndPoints(\"StartToEnd\",c)&&c.move(\"character\",-1),c.pasteHTML(''+h+\"\"))}catch(g){return null}}else{if(p=n.getNode(),f=p.nodeName,\"IMG\"==f)return{name:f,index:o(f,p)};c=a(l.cloneRange()),d||(c.collapse(!1),c.insertNode(r.create(\"span\",{\"data-mce-type\":\"bookmark\",id:u+\"_end\",style:m},h))),l=a(l),l.collapse(!0),l.insertNode(r.create(\"span\",{\"data-mce-type\":\"bookmark\",id:u+\"_start\",style:m},h))}return n.moveToBookmark({id:u,keep:1}),{id:u}},this.moveToBookmark=function(i){function o(e){var t=i[e?\"start\":\"end\"],n,r,o,a;if(t){for(o=t[0],r=c,n=t.length-1;n>=1;n--){if(a=r.childNodes,t[n]>a.length-1)return;r=a[t[n]]}3===r.nodeType&&(o=Math.min(t[0],r.nodeValue.length)),1===r.nodeType&&(o=Math.min(t[0],r.childNodes.length)),e?l.setStart(r,o):l.setEnd(r,o)}return!0}function a(n){var o=r.get(i.id+\"_\"+n),a,s,l,c,h=i.keep;if(o&&(a=o.parentNode,\"start\"==n?(h?(a=o.firstChild,s=1):s=r.nodeIndex(o),u=d=a,f=p=s):(h?(a=o.firstChild,s=1):s=r.nodeIndex(o),d=a,p=s),!h)){for(c=o.previousSibling,l=o.nextSibling,t.each(t.grep(o.childNodes),function(e){3==e.nodeType&&(e.nodeValue=e.nodeValue.replace(/\\uFEFF/g,\"\"))});o=r.get(i.id+\"_\"+n);)r.remove(o,1);c&&l&&c.nodeType==l.nodeType&&3==c.nodeType&&!e.opera&&(s=c.nodeValue.length,c.appendData(l.nodeValue),r.remove(l),\"start\"==n?(u=d=c,f=p=s):(d=c,p=s))}}function s(t){return!r.isBlock(t)||t.innerHTML||e.ie||(t.innerHTML='
'),t}var l,c,u,d,f,p;if(i)if(i.start){if(l=r.createRng(),c=r.getRoot(),n.tridentSel)return n.tridentSel.moveToBookmark(i);o(!0)&&o()&&n.setRng(l)}else i.id?(a(\"start\"),a(\"end\"),u&&(l=r.createRng(),l.setStart(s(u),f),l.setEnd(s(d),p),n.setRng(l))):i.name?n.select(r.select(i.name)[i.index]):i.rng&&n.setRng(i.rng)}}return n.isBookmarkNode=function(e){return e&&\"SPAN\"===e.tagName&&\"bookmark\"===e.getAttribute(\"data-mce-type\")},n}),r(H,[h,A,D,x,M,u,d],function(e,n,r,i,o,a,s){function l(e,t,i,a){var s=this;s.dom=e,s.win=t,s.serializer=i,s.editor=a,s.bookmarkManager=new o(s),s.controlSelection=new r(s,a),s.win.getSelection||(s.tridentSel=new n(s))}var c=s.each,u=s.trim,d=a.ie;return l.prototype={setCursorLocation:function(e,t){var n=this,r=n.dom.createRng();e?(r.setStart(e,t),r.setEnd(e,t),n.setRng(r),n.collapse(!1)):(n._moveEndPoint(r,n.editor.getBody(),!0),n.setRng(r))},getContent:function(e){var n=this,r=n.getRng(),i=n.dom.create(\"body\"),o=n.getSel(),a,s,l;return e=e||{},a=s=\"\",e.get=!0,e.format=e.format||\"html\",e.selection=!0,n.editor.fire(\"BeforeGetContent\",e),\"text\"==e.format?n.isCollapsed()?\"\":r.text||(o.toString?o.toString():\"\"):(r.cloneContents?(l=r.cloneContents(),l&&i.appendChild(l)):r.item!==t||r.htmlText!==t?(i.innerHTML=\"
\"+(r.item?r.item(0).outerHTML:r.htmlText),i.removeChild(i.firstChild)):i.innerHTML=r.toString(),/^\\s/.test(i.innerHTML)&&(a=\" \"),/\\s+$/.test(i.innerHTML)&&(s=\" \"),e.getInner=!0,e.content=n.isCollapsed()?\"\":a+n.serializer.serialize(i,e)+s,n.editor.fire(\"GetContent\",e),e.content)},setContent:function(e,t){var n=this,r=n.getRng(),i,o=n.win.document,a,s;if(t=t||{format:\"html\"},t.set=!0,t.selection=!0,e=t.content=e,t.no_events||n.editor.fire(\"BeforeSetContent\",t),e=t.content,r.insertNode){e+='_',r.startContainer==o&&r.endContainer==o?o.body.innerHTML=e:(r.deleteContents(),0===o.body.childNodes.length?o.body.innerHTML=e:r.createContextualFragment?r.insertNode(r.createContextualFragment(e)):(a=o.createDocumentFragment(),s=o.createElement(\"div\"),a.appendChild(s),s.outerHTML=e,r.insertNode(a))),i=n.dom.get(\"__caret\"),r=o.createRange(),r.setStartBefore(i),r.setEndBefore(i),n.setRng(r),n.dom.remove(\"__caret\");try{n.setRng(r)}catch(l){}}else r.item&&(o.execCommand(\"Delete\",!1,null),r=n.getRng()),/^\\s+/.test(e)?(r.pasteHTML('_'+e),n.dom.remove(\"__mce_tmp\")):r.pasteHTML(e);t.no_events||n.editor.fire(\"SetContent\",t)},getStart:function(e){var t=this,n=t.getRng(),r,i,o,a;if(n.duplicate||n.item){if(n.item)return n.item(0);for(o=n.duplicate(),o.collapse(1),r=o.parentElement(),r.ownerDocument!==t.dom.doc&&(r=t.dom.getRoot()),i=a=n.parentElement();a=a.parentNode;)if(a==r){r=i;break}return r}return r=n.startContainer,1==r.nodeType&&r.hasChildNodes()&&(e&&n.collapsed||(r=r.childNodes[Math.min(r.childNodes.length-1,n.startOffset)])),r&&3==r.nodeType?r.parentNode:r},getEnd:function(e){var t=this,n=t.getRng(),r,i;return n.duplicate||n.item?n.item?n.item(0):(n=n.duplicate(),n.collapse(0),r=n.parentElement(),r.ownerDocument!==t.dom.doc&&(r=t.dom.getRoot()),r&&\"BODY\"==r.nodeName?r.lastChild||r:r):(r=n.endContainer,i=n.endOffset,1==r.nodeType&&r.hasChildNodes()&&(e&&n.collapsed||(r=r.childNodes[i>0?i-1:i])),r&&3==r.nodeType?r.parentNode:r)},getBookmark:function(e,t){return this.bookmarkManager.getBookmark(e,t)},moveToBookmark:function(e){return this.bookmarkManager.moveToBookmark(e)},select:function(e,t){var n=this,r=n.dom,i=r.createRng(),o;if(n.lastFocusBookmark=null,e){if(!t&&n.controlSelection.controlSelect(e))return;o=r.nodeIndex(e),i.setStart(e.parentNode,o),i.setEnd(e.parentNode,o+1),t&&(n._moveEndPoint(i,e,!0),n._moveEndPoint(i,e)),n.setRng(i)}return e},isCollapsed:function(){var e=this,t=e.getRng(),n=e.getSel();return!t||t.item?!1:t.compareEndPoints?0===t.compareEndPoints(\"StartToEnd\",t):!n||t.collapsed},collapse:function(e){var t=this,n=t.getRng(),r;n.item&&(r=n.item(0),n=t.win.document.body.createTextRange(),n.moveToElementText(r)),n.collapse(!!e),t.setRng(n)},getSel:function(){var e=this.win;return e.getSelection?e.getSelection():e.document.selection},getRng:function(e){function t(e,t,n){try{return t.compareBoundaryPoints(e,n)}catch(r){return-1}}var n=this,r,i,o,a=n.win.document,s;if(!e&&n.lastFocusBookmark){var l=n.lastFocusBookmark;return l.startContainer?(i=a.createRange(),i.setStart(l.startContainer,l.startOffset),i.setEnd(l.endContainer,l.endOffset)):i=l,i}if(e&&n.tridentSel)return n.tridentSel.getRangeAt(0);try{(r=n.getSel())&&(i=r.rangeCount>0?r.getRangeAt(0):r.createRange?r.createRange():a.createRange())}catch(c){}if(d&&i&&i.setStart&&a.selection){try{s=a.selection.createRange()}catch(c){}s&&s.item&&(o=s.item(0),i=a.createRange(),i.setStartBefore(o),i.setEndAfter(o))}return i||(i=a.createRange?a.createRange():a.body.createTextRange()),i.setStart&&9===i.startContainer.nodeType&&i.collapsed&&(o=n.dom.getRoot(),i.setStart(o,0),i.setEnd(o,0)),n.selectedRange&&n.explicitRange&&(0===t(i.START_TO_START,i,n.selectedRange)&&0===t(i.END_TO_END,i,n.selectedRange)?i=n.explicitRange:(n.selectedRange=null,n.explicitRange=null)),i},setRng:function(e,t){var n=this,r;if(e)if(e.select)try{e.select()}catch(i){}else if(n.tridentSel){if(e.cloneRange)try{return void n.tridentSel.addRange(e)}catch(i){}}else if(r=n.getSel()){n.explicitRange=e;try{r.removeAllRanges(),r.addRange(e)}catch(i){}t===!1&&r.extend&&(r.collapse(e.endContainer,e.endOffset),r.extend(e.startContainer,e.startOffset)),n.selectedRange=r.rangeCount>0?r.getRangeAt(0):null}},setNode:function(e){var t=this;return t.setContent(t.dom.getOuterHTML(e)),e},getNode:function(){function e(e,t){for(var n=e;e&&3===e.nodeType&&0===e.length;)e=t?e.nextSibling:e.previousSibling;return e||n}var t=this,n=t.getRng(),r,i=n.startContainer,o=n.endContainer,a=n.startOffset,s=n.endOffset,l=t.dom.getRoot();return n?n.setStart?(r=n.commonAncestorContainer,!n.collapsed&&(i==o&&2>s-a&&i.hasChildNodes()&&(r=i.childNodes[a]),3===i.nodeType&&3===o.nodeType&&(i=i.length===a?e(i.nextSibling,!0):i.parentNode,o=0===s?e(o.previousSibling,!1):o.parentNode,i&&i===o))?i:r&&3==r.nodeType?r.parentNode:r):(r=n.item?n.item(0):n.parentElement(),r.ownerDocument!==t.win.document&&(r=l),r):l},getSelectedBlocks:function(t,n){var r=this,i=r.dom,o,a,s=[];if(a=i.getRoot(),t=i.getParent(t||r.getStart(),i.isBlock),n=i.getParent(n||r.getEnd(),i.isBlock),t&&t!=a&&s.push(t),t&&n&&t!=n){o=t;for(var l=new e(t,a);(o=l.next())&&o!=n;)i.isBlock(o)&&s.push(o)}return n&&t!=n&&n!=a&&s.push(n),s},isForward:function(){var e=this.dom,t=this.getSel(),n,r;return t&&t.anchorNode&&t.focusNode?(n=e.createRng(),n.setStart(t.anchorNode,t.anchorOffset),n.collapse(!0),r=e.createRng(),r.setStart(t.focusNode,t.focusOffset),r.collapse(!0),n.compareBoundaryPoints(n.START_TO_START,r)<=0):!0},normalize:function(){var e=this,t=e.getRng();return a.range&&new i(e.dom).normalize(t)&&e.setRng(t,e.isForward()),t},selectorChanged:function(e,t){var n=this,r;return n.selectorChangedData||(n.selectorChangedData={},r={},n.editor.on(\"NodeChange\",function(e){var t=e.element,i=n.dom,o=i.getParents(t,null,i.getRoot()),a={};c(n.selectorChangedData,function(e,t){c(o,function(n){return i.is(n,t)?(r[t]||(c(e,function(e){e(!0,{node:n,selector:t,parents:o})}),r[t]=e),a[t]=e,!1):void 0})}),c(r,function(e,n){a[n]||(delete r[n],c(e,function(e){e(!1,{node:t,selector:n,parents:o})}))})})),n.selectorChangedData[e]||(n.selectorChangedData[e]=[]),n.selectorChangedData[e].push(t),n},getScrollContainer:function(){for(var e,t=this.dom.getRoot();t&&\"BODY\"!=t.nodeName;){if(t.scrollHeight>t.clientHeight){e=t;break}t=t.parentNode}return e},scrollIntoView:function(e){function t(e){for(var t=0,n=0,r=e;r&&r.nodeType;)t+=r.offsetLeft||0,n+=r.offsetTop||0,r=r.offsetParent;return{x:t,y:n}}var n,r,i=this,o=i.dom,a=o.getRoot(),s,l;if(\"BODY\"!=a.nodeName){var c=i.getScrollContainer();if(c)return n=t(e).y-t(c).y,l=c.clientHeight,s=c.scrollTop,void((s>n||n+25>s+l)&&(c.scrollTop=s>n?n:n-l+25))}r=o.getViewPort(i.editor.getWin()),n=o.getPos(e).y,s=r.y,l=r.h,(ns+l)&&i.editor.getWin().scrollTo(0,s>n?n:n-l+25)},placeCaretAt:function(e,t){var n=this.editor.getDoc(),r,i;if(n.caretPositionFromPoint)i=n.caretPositionFromPoint(e,t),r=n.createRange(),r.setStart(i.offsetNode,i.offset),r.collapse(!0);else if(n.caretRangeFromPoint)r=n.caretRangeFromPoint(e,t);else if(n.body.createTextRange){r=n.body.createTextRange();try{r.moveToPoint(e,t),r.collapse(!0)}catch(o){r.collapse(t=e;e++)a.addShortcut(\"access+\"+e,\"\",[\"FormatBlock\",!1,\"h\"+e]);a.addShortcut(\"access+7\",\"\",[\"FormatBlock\",!1,\"p\"]),a.addShortcut(\"access+8\",\"\",[\"FormatBlock\",!1,\"div\"]),a.addShortcut(\"access+9\",\"\",[\"FormatBlock\",!1,\"address\"])}function p(e){return e?U[e]:U}function h(e,t){e&&(\"string\"!=typeof e?se(e,function(e,t){h(t,e)}):(t=t.length?t:[t],se(t,function(e){e.deep===ne&&(e.deep=!e.selector),e.split===ne&&(e.split=!e.selector||e.inline),e.remove===ne&&e.selector&&!e.inline&&(e.remove=\"none\"),e.selector&&e.inline&&(e.mixed=!0,e.block_expand=!0),\"string\"==typeof e.classes&&(e.classes=e.classes.split(/\\s+/))}),U[e]=t))}function m(e){return e&&U[e]&&delete U[e],U}function g(e){var t;return a.dom.getParent(e,function(e){return t=a.dom.getStyle(e,\"text-decoration\"),t&&\"none\"!==t}),t}function v(e){var t;1===e.nodeType&&e.parentNode&&1===e.parentNode.nodeType&&(t=g(e.parentNode),a.dom.getStyle(e,\"color\")&&t?a.dom.setStyle(e,\"text-decoration\",t):a.dom.getStyle(e,\"text-decoration\")===t&&a.dom.setStyle(e,\"text-decoration\",null))}function y(t,n,r){function i(e,t){if(t=t||d,e){if(t.onformat&&t.onformat(e,t,n,r),se(t.styles,function(t,r){$.setStyle(e,r,B(t,n))}),t.styles){var i=$.getAttrib(e,\"style\");i&&e.setAttribute(\"data-mce-style\",i)}se(t.attributes,function(t,r){$.setAttrib(e,r,B(t,n))}),se(t.classes,function(t){t=B(t,n),$.hasClass(e,t)||$.addClass(e,t)})}}function o(){function t(t,n){var i=new e(n);for(r=i.current();r;r=i.prev())if(r.childNodes.length>1||r==t||\"BR\"==r.tagName)return r}var n=a.selection.getRng(),i=n.startContainer,o=n.endContainer;if(i!=o&&0===n.endOffset){var s=t(i,o),l=3==s.nodeType?s.length:s.childNodes.length;n.setEnd(s,l)}return n}function l(e,r,o){var a=[],l,f,p=!0;l=d.inline||d.block,f=$.create(l),i(f),j.walk(e,function(e){function r(e){var g,v,y,b,C;return C=p,g=e.nodeName.toLowerCase(),v=e.parentNode.nodeName.toLowerCase(),1===e.nodeType&&re(e)&&(C=p,p=\"true\"===re(e),b=!0),T(g,\"br\")?(h=0,void(d.block&&$.remove(e))):d.wrapper&&x(e,t,n)?void(h=0):p&&!b&&d.block&&!d.wrapper&&s(g)&&K(v,l)?(e=$.rename(e,l),i(e),a.push(e),void(h=0)):d.selector&&(se(c,function(t){\"collapsed\"in t&&t.collapsed!==m||$.is(e,t.selector)&&!u(e)&&(i(e,t),y=!0)}),!d.inline||y)?void(h=0):void(!p||b||!K(l,g)||!K(v,l)||!o&&3===e.nodeType&&1===e.nodeValue.length&&65279===e.nodeValue.charCodeAt(0)||u(e)||d.inline&&Y(e)?(h=0,se(le(e.childNodes),r),b&&(p=C),h=0):(h||(h=$.clone(f,Z),e.parentNode.insertBefore(h,e),a.push(h)),h.appendChild(e)))}var h;se(e,r)}),d.links===!0&&se(a,function(e){function t(e){\"A\"===e.nodeName&&i(e,d),se(le(e.childNodes),t)}t(e)}),se(a,function(e){function r(e){var t=0;return se(e.childNodes,function(e){D(e)||ae(e)||t++}),t}function o(e){var t,n;return se(e.childNodes,function(e){return 1!=e.nodeType||ae(e)||u(e)?void 0:(t=e,Z)}),t&&!ae(t)&&S(t,d)&&(n=$.clone(t,Z),i(n),$.replace(n,e,ee),$.remove(t,1)),n||e}var s;if(s=r(e),(a.length>1||!Y(e))&&0===s)return void $.remove(e,1);if(d.inline||d.wrapper){if(d.exact||1!==s||(e=o(e)),se(c,function(t){se($.select(t.inline,e),function(e){ae(e)||P(t,n,e,t.exact?e:null)})}),x(e.parentNode,t,n))return $.remove(e,1),e=0,ee;d.merge_with_parents&&$.getParent(e.parentNode,function(r){return x(r,t,n)?($.remove(e,1),e=0,ee):void 0}),e&&d.merge_siblings!==!1&&(e=F(I(e),e),e=F(e,I(e,ee)))}})}var c=p(t),d=c[0],f,h,m=!r&&q.isCollapsed();if(d)if(r)r.nodeType?(h=$.createRng(),h.setStartBefore(r),h.setEndAfter(r),l(H(h,c),null,!0)):l(r,null,!0);else if(m&&d.inline&&!$.select(\"td.mce-item-selected,th.mce-item-selected\").length)W(\"apply\",t,n);else{var g=a.selection.getNode();G||!c[0].defaultBlock||$.getParent(g,$.isBlock)||y(c[0].defaultBlock),a.selection.setRng(o()),f=q.getBookmark(),l(H(q.getRng(ee),c),f),d.styles&&(d.styles.color||d.styles.textDecoration)&&(ce(g,v,\"childNodes\"),v(g)),q.moveToBookmark(f),V(q.getRng(ee)),a.nodeChanged()}}function b(e,t,n,r){function i(e){var n,r,o,a,s;if(1===e.nodeType&&re(e)&&(a=b,b=\"true\"===re(e),s=!0),n=le(e.childNodes),b&&!s)for(r=0,o=h.length;o>r&&!P(h[r],t,e,e);r++);if(m.deep&&n.length){for(r=0,o=n.length;o>r;r++)i(n[r]);s&&(b=a)}}function o(n){var i;return se(c(n.parentNode).reverse(),function(n){var o;i||\"_start\"==n.id||\"_end\"==n.id||(o=x(n,e,t,r),o&&o.split!==!1&&(i=n))}),i}function s(e,n,r,i){var o,a,s,l,c,u;if(e){for(u=e.parentNode,o=n.parentNode;o&&o!=u;o=o.parentNode){for(a=$.clone(o,Z),c=0;c=0;o--){if(a=t[o].selector,!a||t[o].defaultBlock)return ee;for(i=r.length-1;i>=0;i--)if($.is(r[i],a))return ee}return Z}function N(e,t,n){var r;return te||(te={},r={},a.on(\"NodeChange\",function(e){var t=c(e.element),n={};t=i.grep(t,function(e){return 1==e.nodeType&&!e.getAttribute(\"data-mce-bogus\")}),se(te,function(e,i){se(t,function(o){return x(o,i,{},e.similar)?(r[i]||(se(e,function(e){e(!0,{node:o,format:i,parents:t})}),r[i]=e),n[i]=e,!1):void 0})}),se(r,function(i,o){n[o]||(delete r[o],se(i,function(n){n(!1,{node:e.element,format:o,parents:t})}))})})),se(e.split(\",\"),function(e){te[e]||(te[e]=[],te[e].similar=n),te[e].push(t)}),this}function k(e){return o.getCssText(a,e)}function S(e,t){return T(e,t.inline)?ee:T(e,t.block)?ee:t.selector?1==e.nodeType&&$.is(e,t.selector):void 0}function T(e,t){return e=e||\"\",t=t||\"\",e=\"\"+(e.nodeName||e),t=\"\"+(t.nodeName||t),e.toLowerCase()==t.toLowerCase()}function R(e,t){return A($.getStyle(e,t),t)}function A(e,t){return(\"color\"==t||\"backgroundColor\"==t)&&(e=$.toHex(e)),\"fontWeight\"==t&&700==e&&(e=\"bold\"),\"fontFamily\"==t&&(e=e.replace(/[\\'\\\"]/g,\"\").replace(/,\\s+/g,\",\")),\"\"+e}function B(e,t){return\"string\"!=typeof e?e=e(t):t&&(e=e.replace(/%(\\w+)/g,function(e,n){return t[n]||e})),e}function D(e){return e&&3===e.nodeType&&/^([\\t \\r\\n]+|)$/.test(e.nodeValue)}function M(e,t,n){var r=$.create(t,n);return e.parentNode.insertBefore(r,e),r.appendChild(e),r}function H(t,n,r){function i(e){function t(e){return\"BR\"==e.nodeName&&e.getAttribute(\"data-mce-bogus\")&&!e.nextSibling}var r,i,o,a,s;if(r=i=e?g:y,a=e?\"previousSibling\":\"nextSibling\",s=$.getRoot(),3==r.nodeType&&!D(r)&&(e?v>0:bo?n:o,-1===n||r||n++):(n=a.indexOf(\" \",t),o=a.indexOf(\"\\xa0\",t),n=-1!==n&&(-1===o||o>n)?n:o),n}var s,l,c,u;if(3===t.nodeType){if(c=o(t,n),-1!==c)return{container:t,offset:c};u=t}for(s=new e(t,$.getParent(t,Y)||a.getBody());l=s[i?\"prev\":\"next\"]();)if(3===l.nodeType){if(u=l,c=o(l),-1!==c)return{container:l,offset:c}}else if(Y(l))break;return u?(n=i?0:u.length,{container:u,offset:n}):void 0}function d(e,r){var i,o,a,s;for(3==e.nodeType&&0===e.nodeValue.length&&e[r]&&(e=e[r]),i=c(e),o=0;op?p:v],3==g.nodeType&&(v=0)),1==y.nodeType&&y.hasChildNodes()&&(p=y.childNodes.length-1,y=y.childNodes[b>p?p:b-1],3==y.nodeType&&(b=y.nodeValue.length)),g=l(g),y=l(y),(ae(g.parentNode)||ae(g))&&(g=ae(g)?g:g.parentNode,g=g.nextSibling||g,3==g.nodeType&&(v=0)),(ae(y.parentNode)||ae(y))&&(y=ae(y)?y:y.parentNode,y=y.previousSibling||y,3==y.nodeType&&(b=y.length)),n[0].inline&&(t.collapsed&&(m=u(g,v,!0),m&&(g=m.container,v=m.offset),m=u(y,b),m&&(y=m.container,b=m.offset)),h=o(y,b),h.node)){for(;h.node&&0===h.offset&&h.node.previousSibling;)h=o(h.node.previousSibling);h.node&&h.offset>0&&3===h.node.nodeType&&\" \"===h.node.nodeValue.charAt(h.offset-1)&&h.offset>1&&(y=h.node,y.splitText(h.offset-1))}return(n[0].inline||n[0].block_expand)&&(n[0].inline&&3==g.nodeType&&0!==v||(g=i(!0)),n[0].inline&&3==y.nodeType&&b!==y.nodeValue.length||(y=i())),n[0].selector&&n[0].expand!==Z&&!n[0].inline&&(g=d(g,\"previousSibling\"),y=d(y,\"nextSibling\")),(n[0].block||n[0].selector)&&(g=f(g,\"previousSibling\"),y=f(y,\"nextSibling\"),n[0].block&&(Y(g)||(g=i(!0)),Y(y)||(y=i()))),1==g.nodeType&&(v=X(g),g=g.parentNode),1==y.nodeType&&(b=X(y)+1,y=y.parentNode),{startContainer:g,startOffset:v,endContainer:y,endOffset:b}}function L(e,t){return t.links&&\"A\"==e.tagName}function P(e,t,n,r){var i,o,a;if(!S(n,e)&&!L(n,e))return Z;if(\"all\"!=e.remove)for(se(e.styles,function(i,o){i=A(B(i,t),o),\"number\"==typeof o&&(o=i,r=0),(e.remove_similar||!r||T(R(r,o),i))&&$.setStyle(n,o,\"\"),a=1}),a&&\"\"===$.getAttrib(n,\"style\")&&(n.removeAttribute(\"style\"),n.removeAttribute(\"data-mce-style\")),se(e.attributes,function(e,i){var o;if(e=B(e,t),\"number\"==typeof i&&(i=e,r=0),!r||T($.getAttrib(r,i),e)){if(\"class\"==i&&(e=$.getAttrib(n,i),e&&(o=\"\",se(e.split(/\\s+/),function(e){/mce\\-\\w+/.test(e)&&(o+=(o?\" \":\"\")+e)}),o)))return void $.setAttrib(n,i,o);\"class\"==i&&n.removeAttribute(\"className\"),Q.test(i)&&n.removeAttribute(\"data-mce-\"+i),n.removeAttribute(i)}}),se(e.classes,function(e){e=B(e,t),(!r||$.hasClass(r,e))&&$.removeClass(n,e)}),o=$.getAttribs(n),i=0;io?o:i]),3===r.nodeType&&n&&i>=r.nodeValue.length&&(r=new e(r,a.getBody()).next()||r),3!==r.nodeType||n||0!==i||(r=new e(r,a.getBody()).prev()||r),r}function W(t,n,r,i){function o(e){var t=$.create(\"span\",{id:g,\"data-mce-bogus\":!0,style:v?\"color:red\":\"\"});return e&&t.appendChild(a.getDoc().createTextNode(J)),t}function l(e,t){for(;e;){if(3===e.nodeType&&e.nodeValue!==J||e.childNodes.length>1)return!1;t&&1===e.nodeType&&t.push(e),e=e.firstChild}return!0}function c(e){for(;e;){if(e.id===g)return e;e=e.parentNode}}function u(t){var n;if(t)for(n=new e(t,t),t=n.current();t;t=n.next())if(3===t.nodeType)return t}function d(e,t){var n,r;if(e)r=q.getRng(!0),l(e)?(t!==!1&&(r.setStartBefore(e),r.setEndBefore(e)),$.remove(e)):(n=u(e),n.nodeValue.charAt(0)===J&&(n.deleteData(0,1),r.startContainer==n&&r.startOffset>0&&r.setStart(n,r.startOffset-1),r.endContainer==n&&r.endOffset>0&&r.setEnd(n,r.endOffset-1)),$.remove(e,1)),q.setRng(r);else if(e=c(q.getStart()),!e)for(;e=$.get(g);)d(e,!1)}function f(){var e,t,i,a,s,l,d;e=q.getRng(!0),a=e.startOffset,l=e.startContainer,d=l.nodeValue,t=c(q.getStart()),t&&(i=u(t)),d&&a>0&&a=0;h--)u.appendChild($.clone(f[h],!1)),u=u.firstChild;u.appendChild($.doc.createTextNode(J)),u=u.firstChild;var g=$.getParent(d,s);g&&$.isEmpty(g)?d.parentNode.replaceChild(m,d):$.insertAfter(m,d),q.setCursorLocation(u,1),$.isEmpty(d)&&$.remove(d)}}function m(){var e;e=c(q.getStart()),e&&!$.isEmpty(e)&&ce(e,function(e){1!=e.nodeType||e.id===g||$.isEmpty(e)||$.setAttrib(e,\"data-mce-bogus\",null)},\"childNodes\")}var g=\"_mce_caret\",v=a.settings.caret_debug;a._hasCaretEvents||(oe=function(){var e=[],t;if(l(c(q.getStart()),e))for(t=e.length;t--;)$.setAttrib(e[t],\"data-mce-bogus\",\"1\")},ie=function(e){var t=e.keyCode;d(),(8==t&&q.isCollapsed()||37==t||39==t)&&d(c(q.getStart())),m()},a.on(\"SetContent\",function(e){e.selection&&m()}),a._hasCaretEvents=!0),\"apply\"==t?f():h()}function V(t){var n=t.startContainer,r=t.startOffset,i,o,a,s,l;if(3==n.nodeType&&r>=n.nodeValue.length&&(r=X(n),n=n.parentNode,i=!0),1==n.nodeType)for(s=n.childNodes,n=s[Math.min(r,s.length-1)],o=new e(n,$.getParent(n,$.isBlock)),(r>s.length-1||i)&&o.next(),a=o.current();a;a=o.next())if(3==a.nodeType&&!D(a))return l=$.create(\"a\",{\"data-mce-bogus\":\"all\"},J),a.parentNode.insertBefore(l,a),t.setStart(a,0),q.setRng(t),void $.remove(l)}var U={},$=a.dom,q=a.selection,j=new t($),K=a.schema.isValidChild,Y=$.isBlock,G=a.settings.forced_root_block,X=$.nodeIndex,J=\"\\ufeff\",Q=/^(src|href|style)$/,Z=!1,ee=!0,te,ne,re=$.getContentEditable,ie,oe,ae=n.isBookmarkNode,se=i.each,le=i.grep,ce=i.walk,ue=i.extend;ue(this,{get:p,register:h,unregister:m,apply:y,remove:b,toggle:C,match:w,matchAll:_,matchNode:x,canApply:E,formatChanged:N,getCssText:k}),d(),f(),a.on(\"BeforeGetContent\",function(e){oe&&\"raw\"!=e.format&&oe()}),a.on(\"mouseup keydown\",function(e){ie&&ie(e)})}}),r(I,[B,u,d,N],function(e,t,n,r){var i=n.trim,o;return o=new RegExp([\"]+data-mce-bogus[^>]+>[\\u200b\\ufeff]+<\\\\/span>\",'\\\\s?data-mce-selected=\"[^\"]+\"'].join(\"|\"),\"gi\"),function(e){function n(){var t=e.getContent({format:\"raw\",no_events:1}),n=/<(\\w+) [^>]*data-mce-bogus=\"all\"[^>]*>/g,a,s,l,c,u,d=e.schema;for(t=t.replace(o,\"\"),u=d.getShortEndedElements();c=n.exec(t);)s=n.lastIndex,l=c[0].length,a=u[c[1]]?s:r.findEndTag(d,t,s),t=t.substring(0,s-l)+t.substring(a),n.lastIndex=s-l;return i(t)}function a(t){e.isNotDirty=!t}function s(e){l.typing=!1,l.add({},e)}var l=this,c=0,u=[],d,f,p=0;return e.on(\"init\",function(){l.add()}),e.on(\"BeforeExecCommand\",function(e){var t=e.command;\"Undo\"!=t&&\"Redo\"!=t&&\"mceRepaint\"!=t&&l.beforeChange()}),e.on(\"ExecCommand\",function(e){var t=e.command;\"Undo\"!=t&&\"Redo\"!=t&&\"mceRepaint\"!=t&&s(e)}),e.on(\"ObjectResizeStart\",function(){l.beforeChange()}),e.on(\"SaveContent ObjectResized blur\",s),e.on(\"DragEnd\",s),e.on(\"KeyUp\",function(r){var i=r.keyCode;(i>=33&&36>=i||i>=37&&40>=i||45==i||13==i||r.ctrlKey)&&(s(),e.nodeChanged()),(46==i||8==i||t.mac&&(91==i||93==i))&&e.nodeChanged(),f&&l.typing&&(e.isDirty()||(a(u[0]&&n()!=u[0].content),e.isNotDirty||e.fire(\"change\",{level:u[0],lastLevel:null})),e.fire(\"TypingUndo\"),f=!1,e.nodeChanged())}),e.on(\"KeyDown\",function(e){var t=e.keyCode;if(t>=33&&36>=t||t>=37&&40>=t||45==t)return void(l.typing&&s(e));var n=e.ctrlKey&&!e.altKey||e.metaKey;!(16>t||t>20)||224==t||91==t||l.typing||n||(l.beforeChange(),l.typing=!0,l.add({},e),f=!0)}),e.on(\"MouseDown\",function(e){l.typing&&s(e)}),e.addShortcut(\"meta+z\",\"\",\"Undo\"),e.addShortcut(\"meta+y,meta+shift+z\",\"\",\"Redo\"),e.on(\"AddUndo Undo Redo ClearUndos\",function(t){t.isDefaultPrevented()||e.nodeChanged()}),l={data:u,typing:!1,beforeChange:function(){p||(d=e.selection.getBookmark(2,!0))},add:function(t,r){var i,o=e.settings,s;if(t=t||{},t.content=n(),p||e.removed)return null;if(s=u[c],e.fire(\"BeforeAddUndo\",{level:t,lastLevel:s,originalEvent:r}).isDefaultPrevented())return null;if(s&&s.content==t.content)return null;if(u[c]&&(u[c].beforeBookmark=d),o.custom_undo_redo_levels&&u.length>o.custom_undo_redo_levels){for(i=0;i0&&(a(!0),e.fire(\"change\",l)),t},undo:function(){var t;return l.typing&&(l.add(),l.typing=!1),c>0&&(t=u[--c],0===c&&a(!1),e.setContent(t.content,{format:\"raw\"}),e.selection.moveToBookmark(t.beforeBookmark),e.fire(\"undo\",{level:t})),t},redo:function(){var t;return c0||l.typing&&u[0]&&n()!=u[0].content},hasRedo:function(){return cD)&&(u=a.create(\"br\"),t.parentNode.insertBefore(u,t)),l.setStartBefore(t),l.setEndBefore(t)):(l.setStartAfter(t),l.setEndAfter(t)):(l.setStart(t,0),l.setEnd(t,0));s.setRng(l),a.remove(u),s.scrollIntoView(t)}}function v(e){var t=l.forced_root_block;t&&t.toLowerCase()===e.tagName.toLowerCase()&&a.setAttribs(e,l.forced_root_block_attrs)}function y(e){var t=R,n,i,o,s=u.getTextInlineElements();if(e||\"TABLE\"==O?(n=a.create(e||F),v(n)):n=B.cloneNode(!1),o=n,l.keep_styles!==!1)do if(s[t.nodeName]){if(\"_mce_caret\"==t.id)continue;i=t.cloneNode(!1),a.setAttrib(i,\"id\",\"\"),n.hasChildNodes()?(i.appendChild(n.firstChild),n.appendChild(i)):(o=i,n.appendChild(i))}while(t=t.parentNode);return r||(o.innerHTML='
'),n}function b(t){var n,r,i;if(3==R.nodeType&&(t?A>0:AR.childNodes.length-1,R=R.childNodes[Math.min(A,R.childNodes.length-1)]||R,A=z&&3==R.nodeType?R.nodeValue.length:0),T=E(R)){if(c.beforeChange(),!a.isBlock(T)&&T!=a.getRoot())return void((!F||M)&&w());if((F&&!M||!F&&M)&&(R=C(R,A)),B=a.getParent(R,a.isBlock),P=B?a.getParent(B.parentNode,a.isBlock):null,O=B?B.nodeName.toUpperCase():\"\",I=P?P.nodeName.toUpperCase():\"\",\"LI\"!=I||o.ctrlKey||(B=P,O=I),/^(LI|DT|DD)$/.test(O)){if(!F&&M)return void w();if(a.isEmpty(B))return void x()}if(\"PRE\"==O&&l.br_in_pre!==!1){if(!M)return void w()}else if(!F&&!M&&\"LI\"!=O||F&&M)return void w();F&&B===i.getBody()||(F=F||\"P\",b()?(H=/^(H[1-6]|PRE|FIGURE)$/.test(O)&&\"HGROUP\"!=I?y(F):y(),l.end_container_on_empty_block&&p(P)&&a.isEmpty(B)?H=a.split(P,B):a.insertAfter(H,B),g(H)):b(!0)?(H=B.parentNode.insertBefore(y(),B),h(H),g(B)):(S=k.cloneRange(),S.setEndAfter(B),L=S.extractContents(),_(L),H=L.firstChild,a.insertAfter(L,B),m(H),N(B),g(H)),a.setAttrib(H,\"id\",\"\"),i.fire(\"NewBlock\",{newBlock:H}),c.add())}}}var a=i.dom,s=i.selection,l=i.settings,c=i.undoManager,u=i.schema,d=u.getNonEmptyElements(),f=u.getMoveCaretBeforeOnEnterElements();i.on(\"keydown\",function(e){13==e.keyCode&&o(e)!==!1&&e.preventDefault()})}}),r(z,[],function(){return function(e){function t(){var t=i.getStart(),s=e.getBody(),l,c,u,d,f,p,h,m=-16777215,g,v,y,b,C;if(C=n.forced_root_block,t&&1===t.nodeType&&C){for(;t&&t!=s;){if(a[t.nodeName])return;t=t.parentNode}if(l=i.getRng(),l.setStart){c=l.startContainer,u=l.startOffset,d=l.endContainer,f=l.endOffset;try{v=e.getDoc().activeElement===s}catch(x){}}else l.item&&(t=l.item(0),l=e.getDoc().body.createTextRange(),l.moveToElementText(t)),v=l.parentElement().ownerDocument===e.getDoc(),y=l.duplicate(),y.collapse(!0),u=-1*y.move(\"character\",m),y.collapsed||(y=l.duplicate(),y.collapse(!1),f=-1*y.move(\"character\",m)-u);for(t=s.firstChild,b=s.nodeName.toLowerCase();t;)if((3===t.nodeType||1==t.nodeType&&!a[t.nodeName])&&o.isValidChild(b,C.toLowerCase())){if(3===t.nodeType&&0===t.nodeValue.length){h=t,t=t.nextSibling,r.remove(h);continue}p||(p=r.create(C,e.settings.forced_root_block_attrs),t.parentNode.insertBefore(p,t),g=!0),h=t,t=t.nextSibling,p.appendChild(h)}else p=null,t=t.nextSibling;if(g&&v){if(l.setStart)l.setStart(c,u),l.setEnd(d,f),i.setRng(l);else try{l=e.getDoc().body.createTextRange(),l.moveToElementText(s),l.collapse(!0),l.moveStart(\"character\",u),f>0&&l.moveEnd(\"character\",f),l.select()}catch(x){}e.nodeChanged()}}}var n=e.settings,r=e.dom,i=e.selection,o=e.schema,a=o.getBlockElements();n.forced_root_block&&e.on(\"NodeChange\",t)}}),r(W,[T,u,d,L,x,h],function(e,n,r,i,o,a){var s=r.each,l=r.extend,c=r.map,u=r.inArray,d=r.explode,f=n.gecko,p=n.ie,h=n.ie&&n.ie<11,m=!0,g=!1;return function(r){function v(e,t,n,i){var o,a,c=0;if(/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint)$/.test(e)||i&&i.skip_focus||r.focus(),i=l({},i),i=r.fire(\"BeforeExecCommand\",{command:e,ui:t,value:n}),i.isDefaultPrevented())return!1;if(a=e.toLowerCase(),o=H.exec[a])return o(a,t,n),r.fire(\"ExecCommand\",{command:e,ui:t,value:n}),!0;if(s(r.plugins,function(i){return i.execCommand&&i.execCommand(e,t,n)?(r.fire(\"ExecCommand\",{command:e,ui:t,value:n}),c=!0,!1):void 0}),c)return c;if(r.theme&&r.theme.execCommand&&r.theme.execCommand(e,t,n))return r.fire(\"ExecCommand\",{command:e,ui:t,value:n}),!0;try{c=r.getDoc().execCommand(e,t,n)}catch(u){}return c?(r.fire(\"ExecCommand\",{command:e,ui:t,value:n}),!0):!1}function y(e){var t;if(!r._isHidden()){if(e=e.toLowerCase(),t=H.state[e])return t(e);try{return r.getDoc().queryCommandState(e)}catch(n){}return!1}}function b(e){var t;if(!r._isHidden()){if(e=e.toLowerCase(),t=H.value[e])return t(e);try{return r.getDoc().queryCommandValue(e)}catch(n){}}}function C(e,t){t=t||\"exec\",s(e,function(e,n){s(n.toLowerCase().split(\",\"),function(n){H[t][n]=e})})}function x(e,t,n){e=e.toLowerCase(),H.exec[e]=function(e,i,o,a){return t.call(n||r,i,o,a)}}function w(e){if(e=e.toLowerCase(),H.exec[e])return!0;try{return r.getDoc().queryCommandSupported(e)}catch(t){}return!1}function _(e,t,n){e=e.toLowerCase(),H.state[e]=function(){return t.call(n||r)}}function E(e,t,n){e=e.toLowerCase(),H.value[e]=function(){return t.call(n||r)}}function N(e){return e=e.toLowerCase(),!!H.exec[e]}function k(e,n,i){return n===t&&(n=g),i===t&&(i=null),r.getDoc().execCommand(e,n,i)}function S(e){return M.match(e)}function T(e,n){M.toggle(e,n?{value:n}:t),r.nodeChanged()}function R(e){P=D.getBookmark(e)}function A(){D.moveToBookmark(P)}var B,D,M,H={state:{},exec:{},value:{}},L=r.settings,P;r.on(\"PreInit\",function(){B=r.dom,D=r.selection,L=r.settings,M=r.formatter}),l(this,{execCommand:v,queryCommandState:y,queryCommandValue:b,queryCommandSupported:w,addCommands:C,addCommand:x,addQueryStateHandler:_,addQueryValueHandler:E,hasCustomCommand:N}),C({\"mceResetDesignMode,mceBeginUndoLevel\":function(){},\"mceEndUndoLevel,mceAddUndoLevel\":function(){r.undoManager.add()},\"Cut,Copy,Paste\":function(e){var t=r.getDoc(),i;try{k(e)}catch(o){i=m}if(i||!t.queryCommandSupported(e)){var a=r.translate(\"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.\");n.mac&&(a=a.replace(/Ctrl\\+/g,\"\\u2318+\")),r.windowManager.alert(a)}},unlink:function(){if(D.isCollapsed()){var e=D.getNode();return void(\"A\"==e.tagName&&r.dom.remove(e,!0))}M.remove(\"link\")},\"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull\":function(e){var t=e.substring(7);\"full\"==t&&(t=\"justify\"),s(\"left,center,right,justify\".split(\",\"),function(e){t!=e&&M.remove(\"align\"+e)}),T(\"align\"+t),v(\"mceRepaint\")},\"InsertUnorderedList,InsertOrderedList\":function(e){var t,n;k(e),t=B.getParent(D.getNode(),\"ol,ul\"),t&&(n=t.parentNode,/^(H[1-6]|P|ADDRESS|PRE)$/.test(n.nodeName)&&(R(),B.split(n,t),A()))},\"Bold,Italic,Underline,Strikethrough,Superscript,Subscript\":function(e){T(e)},\"ForeColor,HiliteColor,FontName\":function(e,t,n){T(e,n)},FontSize:function(e,t,n){var r,i;n>=1&&7>=n&&(i=d(L.font_size_style_values),r=d(L.font_size_classes),n=r?r[n-1]||n:i[n-1]||n),T(e,n)},RemoveFormat:function(e){M.remove(e)},mceBlockQuote:function(){T(\"blockquote\")},FormatBlock:function(e,t,n){return T(n||\"p\")},mceCleanup:function(){var e=D.getBookmark();r.setContent(r.getContent({cleanup:m}),{cleanup:m}),D.moveToBookmark(e)},mceRemoveNode:function(e,t,n){var i=n||D.getNode();i!=r.getBody()&&(R(),r.dom.remove(i,m),A())},mceSelectNodeDepth:function(e,t,n){var i=0;B.getParent(D.getNode(),function(e){return 1==e.nodeType&&i++==n?(D.select(e),g):void 0},r.getBody())},mceSelectNode:function(e,t,n){D.select(n)},mceInsertContent:function(t,n,o){function a(e){function t(e){return r[e]&&3==r[e].nodeType}var n,r,i;return n=D.getRng(!0),r=n.startContainer,i=n.startOffset,3==r.nodeType&&(i>0?e=e.replace(/^ /,\" \"):t(\"previousSibling\")||(e=e.replace(/^ /,\" \")),i|)$/,\" \"):t(\"nextSibling\")||(e=e.replace(/( | )(
|)$/,\" \"))),e}function l(){var e,t,n;e=D.getRng(!0),t=e.startContainer,n=e.startOffset,3==t.nodeType&&e.collapsed&&(\"\\xa0\"===t.data[n]?(t.deleteData(n,1),/[\\u00a0| ]$/.test(o)||(o+=\" \")):\"\\xa0\"===t.data[n-1]&&(t.deleteData(n-1,1),/[\\u00a0| ]$/.test(o)||(o=\" \"+o)))}function c(e){if(_)for(C=e.firstChild;C;C=C.walk(!0))E[C.name]&&C.attr(\"data-mce-new\",\"true\")}function u(){if(_){var e=r.getBody(),t=new i(B);s(B.select(\"*[data-mce-new]\"),function(n){n.removeAttribute(\"data-mce-new\");for(var r=n.parentNode;r&&r!=e;r=r.parentNode)t.compare(r,n)&&B.remove(n,!0)})}}var d,f,h,m,g,v,y,b,C,x,w,_,E=r.schema.getTextInlineElements();\"string\"!=typeof o&&(_=o.merge,o=o.content),/^ | $/.test(o)&&(o=a(o)),d=r.parser,f=new e({},r.schema),w='​',v={content:o,format:\"html\",selection:!0},r.fire(\"BeforeSetContent\",v),o=v.content,-1==o.indexOf(\"{$caret}\")&&(o+=\"{$caret}\"),o=o.replace(/\\{\\$caret\\}/,w),b=D.getRng();var N=b.startContainer||(b.parentElement?b.parentElement():null),k=r.getBody();N===k&&D.isCollapsed()&&B.isBlock(k.firstChild)&&B.isEmpty(k.firstChild)&&(b=B.createRng(),b.setStart(k.firstChild,0),b.setEnd(k.firstChild,0),D.setRng(b)),D.isCollapsed()||(r.getDoc().execCommand(\"Delete\",!1,null),l()),h=D.getNode();var S={context:h.nodeName.toLowerCase()};if(g=d.parse(o,S),c(g),C=g.lastChild,\"mce_marker\"==C.attr(\"id\"))for(y=C,C=C.prev;C;C=C.walk(!0))if(3==C.type||!B.isBlock(C.name)){r.schema.isValidChild(C.parent.name,\"span\")&&C.parent.insert(y,C,\"br\"===C.name);break}if(S.invalid){for(D.setContent(w),h=D.getNode(),m=r.getBody(),9==h.nodeType?h=C=m:C=h;C!==m;)h=C,C=C.parentNode;o=h==m?m.innerHTML:B.getOuterHTML(h),o=f.serialize(d.parse(o.replace(//i,function(){return f.serialize(g)}))),h==m?B.setHTML(m,o):B.setOuterHTML(h,o)}else o=f.serialize(g),C=h.firstChild,x=h.lastChild,!C||C===x&&\"BR\"===C.nodeName?B.setHTML(h,o):D.setContent(o);u(),y=B.get(\"mce_marker\"),D.scrollIntoView(y),b=B.createRng(),C=y.previousSibling,C&&3==C.nodeType?(b.setStart(C,C.nodeValue.length),p||(x=y.nextSibling,x&&3==x.nodeType&&(C.appendData(x.data),x.parentNode.removeChild(x)))):(b.setStartBefore(y),b.setEndBefore(y)),B.remove(y),D.setRng(b),r.fire(\"SetContent\",v),r.addVisual()},mceInsertRawHTML:function(e,t,n){D.setContent(\"tiny_mce_marker\"),r.setContent(r.getContent().replace(/tiny_mce_marker/g,function(){return n}))},mceToggleFormat:function(e,t,n){T(n)},mceSetContent:function(e,t,n){r.setContent(n)},\"Indent,Outdent\":function(e){var t,n,i;t=L.indentation,n=/[a-z%]+$/i.exec(t),t=parseInt(t,10),y(\"InsertUnorderedList\")||y(\"InsertOrderedList\")?k(e):(L.forced_root_block||B.getParent(D.getNode(),B.isBlock)||M.apply(\"div\"),s(D.getSelectedBlocks(),function(o){if(\"LI\"!=o.nodeName){var a=r.getParam(\"indent_use_margin\",!1)?\"margin\":\"padding\";a+=\"rtl\"==B.getStyle(o,\"direction\",!0)?\"Right\":\"Left\",\"outdent\"==e?(i=Math.max(0,parseInt(o.style[a]||0,10)-t),B.setStyle(o,a,i?i+n:\"\")):(i=parseInt(o.style[a]||0,10)+t+n,B.setStyle(o,a,i))}}))},mceRepaint:function(){if(f)try{R(m),D.getSel()&&D.getSel().selectAllChildren(r.getBody()),D.collapse(m),A()}catch(e){}},InsertHorizontalRule:function(){r.execCommand(\"mceInsertContent\",!1,\"
\")},mceToggleVisualAid:function(){r.hasVisual=!r.hasVisual,r.addVisual()},mceReplaceContent:function(e,t,n){r.execCommand(\"mceInsertContent\",!1,n.replace(/\\{\\$selection\\}/g,D.getContent({format:\"text\"})))},mceInsertLink:function(e,t,n){var r;\"string\"==typeof n&&(n={href:n}),r=B.getParent(D.getNode(),\"a\"),n.href=n.href.replace(\" \",\"%20\"),r&&n.href||M.remove(\"link\"),n.href&&M.apply(\"link\",n,r)},selectAll:function(){var e=B.getRoot(),t;D.getRng().setStart?(t=B.createRng(),t.setStart(e,0),t.setEnd(e,e.childNodes.length),D.setRng(t)):(t=D.getRng(),t.item||(t.moveToElementText(e),t.select()))},\"delete\":function(){k(\"Delete\");var e=r.getBody();B.isEmpty(e)&&(r.setContent(\"\"),e.firstChild&&B.isBlock(e.firstChild)?r.selection.setCursorLocation(e.firstChild,0):r.selection.setCursorLocation(e,0))},mceNewDocument:function(){r.setContent(\"\")},InsertLineBreak:function(e,t,n){function i(){for(var e=new a(p,v),t,n=r.schema.getNonEmptyElements();t=e.next();)if(n[t.nodeName.toLowerCase()]||t.length>0)return!0}var s=n,l,c,u,d=D.getRng(!0);new o(B).normalize(d);var f=d.startOffset,p=d.startContainer;if(1==p.nodeType&&p.hasChildNodes()){var g=f>p.childNodes.length-1;p=p.childNodes[Math.min(f,p.childNodes.length-1)]||p,f=g&&3==p.nodeType?p.nodeValue.length:0}var v=B.getParent(p,B.isBlock),y=v?v.nodeName.toUpperCase():\"\",b=v?B.getParent(v.parentNode,B.isBlock):null,C=b?b.nodeName.toUpperCase():\"\",x=s&&s.ctrlKey;\"LI\"!=C||x||(v=b,y=C),p&&3==p.nodeType&&f>=p.nodeValue.length&&(h||i()||(l=B.create(\"br\"),d.insertNode(l),d.setStartAfter(l),d.setEndAfter(l),c=!0)),l=B.create(\"br\"),d.insertNode(l);var w=B.doc.documentMode;return h&&\"PRE\"==y&&(!w||8>w)&&l.parentNode.insertBefore(B.doc.createTextNode(\"\\r\"),l),u=B.create(\"span\",{},\" \"),l.parentNode.insertBefore(u,l),D.scrollIntoView(u),B.remove(u),c?(d.setStartBefore(l),d.setEndBefore(l)):(d.setStartAfter(l),d.setEndAfter(l)),D.setRng(d),r.undoManager.add(),m}}),C({\"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull\":function(e){var t=\"align\"+e.substring(7),n=D.isCollapsed()?[B.getParent(D.getNode(),B.isBlock)]:D.getSelectedBlocks(),r=c(n,function(e){return!!M.matchNode(e,t)});return-1!==u(r,m)},\"Bold,Italic,Underline,Strikethrough,Superscript,Subscript\":function(e){return S(e)},mceBlockQuote:function(){return S(\"blockquote\")},Outdent:function(){var e;if(L.inline_styles){if((e=B.getParent(D.getStart(),B.isBlock))&&parseInt(e.style.paddingLeft,10)>0)return m;if((e=B.getParent(D.getEnd(),B.isBlock))&&parseInt(e.style.paddingLeft,10)>0)return m}return y(\"InsertUnorderedList\")||y(\"InsertOrderedList\")||!L.inline_styles&&!!B.getParent(D.getNode(),\"BLOCKQUOTE\")},\"InsertUnorderedList,InsertOrderedList\":function(e){var t=B.getParent(D.getNode(),\"ul,ol\");return t&&(\"insertunorderedlist\"===e&&\"UL\"===t.tagName||\"insertorderedlist\"===e&&\"OL\"===t.tagName)}},\"state\"),C({\"FontSize,FontName\":function(e){var t=0,n;return(n=B.getParent(D.getNode(),\"span\"))&&(t=\"fontsize\"==e?n.style.fontSize:n.style.fontFamily.replace(/, /g,\",\").replace(/[\\'\\\"]/g,\"\").toLowerCase()),t}},\"value\"),C({Undo:function(){r.undoManager.undo()},Redo:function(){r.undoManager.redo()}})}}),r(V,[d],function(e){function t(e,o){var a=this,s,l;if(e=r(e),o=a.settings=o||{},s=o.base_uri,/^([\\w\\-]+):([^\\/]{2})/i.test(e)||/^\\s*#/.test(e))return void(a.source=e);var c=0===e.indexOf(\"//\");0!==e.indexOf(\"/\")||c||(e=(s?s.protocol||\"http\":\"http\")+\"://mce_host\"+e),/^[\\w\\-]*:?\\/\\//.test(e)||(l=o.base_uri?o.base_uri.path:new t(location.href).directory,\"\"===o.base_uri.protocol?e=\"//mce_host\"+a.toAbsPath(l,e):(e=/([^#?]*)([#?]?.*)/.exec(e),e=(s&&s.protocol||\"http\")+\"://mce_host\"+a.toAbsPath(l,e[1])+e[2])),e=e.replace(/@@/g,\"(mce_at)\"),e=/^(?:(?![^:@]+:[^:@\\/]*@)([^:\\/?#.]+):)?(?:\\/\\/)?((?:(([^:@\\/]*):?([^:@\\/]*))?@)?([^:\\/?#]*)(?::(\\d*))?)(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*))(?:\\?([^#]*))?(?:#(.*))?)/.exec(e),n(i,function(t,n){var r=e[n];r&&(r=r.replace(/\\(mce_at\\)/g,\"@@\")),a[t]=r}),s&&(a.protocol||(a.protocol=s.protocol),a.userInfo||(a.userInfo=s.userInfo),a.port||\"mce_host\"!==a.host||(a.port=s.port),a.host&&\"mce_host\"!==a.host||(a.host=s.host),a.source=\"\"),c&&(a.protocol=\"\")}var n=e.each,r=e.trim,i=\"source protocol authority userInfo user password host port relative path directory file query anchor\".split(\" \"),o={ftp:21,http:80,https:443,mailto:25};return t.prototype={setPath:function(e){var t=this;e=/^(.*?)\\/?(\\w+)?$/.exec(e),t.path=e[0],t.directory=e[1],t.file=e[2],t.source=\"\",t.getURI()},toRelative:function(e){var n=this,r;if(\"./\"===e)return e;if(e=new t(e,{base_uri:n}),\"mce_host\"!=e.host&&n.host!=e.host&&e.host||n.port!=e.port||n.protocol!=e.protocol&&\"\"!==e.protocol)return e.getURI();var i=n.getURI(),o=e.getURI();return i==o||\"/\"==i.charAt(i.length-1)&&i.substr(0,i.length-1)==o?i:(r=n.toRelPath(n.path,e.path),e.query&&(r+=\"?\"+e.query),e.anchor&&(r+=\"#\"+e.anchor),r)},toAbsolute:function(e,n){return e=new t(e,{base_uri:this}),e.getURI(n&&this.isSameOrigin(e))},isSameOrigin:function(e){if(this.host==e.host&&this.protocol==e.protocol){if(this.port==e.port)return!0;var t=o[this.protocol];if(t&&(this.port||t)==(e.port||t))return!0}return!1},toRelPath:function(e,t){var n,r=0,i=\"\",o,a;if(e=e.substring(0,e.lastIndexOf(\"/\")),e=e.split(\"/\"),n=t.split(\"/\"),e.length>=n.length)for(o=0,a=e.length;a>o;o++)if(o>=n.length||e[o]!=n[o]){r=o+1;break}if(e.lengtho;o++)if(o>=e.length||e[o]!=n[o]){r=o+1;break}if(1===r)return t;for(o=0,a=e.length-(r-1);a>o;o++)i+=\"../\";for(o=r-1,a=n.length;a>o;o++)i+=o!=r-1?\"/\"+n[o]:n[o];return i},toAbsPath:function(e,t){var r,i=0,o=[],a,s;for(a=/\\/$/.test(t)?\"/\":\"\",e=e.split(\"/\"),t=t.split(\"/\"),n(e,function(e){e&&o.push(e)}),e=o,r=t.length-1,o=[];r>=0;r--)0!==t[r].length&&\".\"!==t[r]&&(\"..\"!==t[r]?i>0?i--:o.push(t[r]):i++);return r=e.length-i,s=0>=r?o.reverse().join(\"/\"):e.slice(0,r).join(\"/\")+\"/\"+o.reverse().join(\"/\"),0!==s.indexOf(\"/\")&&(s=\"/\"+s),a&&s.lastIndexOf(\"/\")!==s.length-1&&(s+=a),s},getURI:function(e){var t,n=this;return(!n.source||e)&&(t=\"\",e||(t+=n.protocol?n.protocol+\"://\":\"//\",n.userInfo&&(t+=n.userInfo+\"@\"),n.host&&(t+=n.host),n.port&&(t+=\":\"+n.port)),n.path&&(t+=n.path),n.query&&(t+=\"?\"+n.query),n.anchor&&(t+=\"#\"+n.anchor),n.source=t),n.source}},t}),r(U,[d],function(e){function t(){}var n=e.each,r=e.extend,i,o;return t.extend=i=function(e){function t(){var e,t,n,r=this;if(!o&&(r.init&&r.init.apply(r,arguments),t=r.Mixins))for(e=t.length;e--;)n=t[e],n.init&&n.init.apply(r,arguments)}function a(){return this}function s(e,t){return function(){var n=this,r=n._super,i;return n._super=c[e],i=t.apply(n,arguments),n._super=r,i}}var l=this,c=l.prototype,u,d,f;o=!0,u=new l,o=!1,e.Mixins&&(n(e.Mixins,function(t){t=t;for(var n in t)\"init\"!==n&&(e[n]=t[n])}),c.Mixins&&(e.Mixins=c.Mixins.concat(e.Mixins))),e.Methods&&n(e.Methods.split(\",\"),function(t){e[t]=a}),e.Properties&&n(e.Properties.split(\",\"),function(t){var n=\"_\"+t;e[t]=function(e){var t=this,r;return e!==r?(t[n]=e,t):t[n]}}),e.Statics&&n(e.Statics,function(e,n){t[n]=e}),e.Defaults&&c.Defaults&&(e.Defaults=r({},c.Defaults,e.Defaults));for(d in e)f=e[d],\"function\"==typeof f&&c[d]?u[d]=s(d,f):u[d]=f;return t.prototype=u,t.constructor=t,t.extend=i,t},t}),r($,[d],function(e){function t(t){function n(){return!1}function r(){return!0}function i(e,i){var o,s,l,c;if(e=e.toLowerCase(),i=i||{},i.type=e,i.target||(i.target=u),i.preventDefault||(i.preventDefault=function(){i.isDefaultPrevented=r},i.stopPropagation=function(){i.isPropagationStopped=r},i.stopImmediatePropagation=function(){i.isImmediatePropagationStopped=r},i.isDefaultPrevented=n,i.isPropagationStopped=n,i.isImmediatePropagationStopped=n),t.beforeFire&&t.beforeFire(i),o=d[e])for(s=0,l=o.length;l>s;s++){if(c=o[s],c.once&&a(e,c.func),i.isImmediatePropagationStopped())return i.stopPropagation(),i;if(c.func.call(u,i)===!1)return i.preventDefault(),i}return i}function o(t,r,i,o){var a,s,l;if(r===!1&&(r=n),r)for(r={func:r},o&&e.extend(r,o),s=t.toLowerCase().split(\" \"),l=s.length;l--;)t=s[l],a=d[t],a||(a=d[t]=[],f(t,!0)),i?a.unshift(r):a.push(r);return c}function a(e,t){var n,r,i,o,a;if(e)for(o=e.toLowerCase().split(\" \"),n=o.length;n--;){if(e=o[n],r=d[e],!e){for(i in d)f(i,!1),delete d[i];return c}if(r){if(t)for(a=r.length;a--;)r[a].func===t&&(r=r.slice(0,a).concat(r.slice(a+1)),d[e]=r);else r.length=0;r.length||(f(e,!1),delete d[e])}}else{for(e in d)f(e,!1);d={}}return c}function s(e,t,n){return o(e,t,n,{once:!0})}function l(e){return e=e.toLowerCase(),!(!d[e]||0===d[e].length)}var c=this,u,d={},f;t=t||{},u=t.scope||c,f=t.toggleEvent||n,c.fire=i,c.on=o,c.off=a,c.once=s,c.has=l}var n=e.makeMap(\"focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange mouseout mouseenter mouseleave wheel keydown keypress keyup input contextmenu dragstart dragend dragover draggesture dragdrop drop drag submit compositionstart compositionend compositionupdate touchstart touchend\",\" \");return t.isNative=function(e){return!!n[e.toLowerCase()]},t}),r(q,[U],function(e){function t(e){for(var t=[],n=e.length,r;n--;)r=e[n],r.__checked||(t.push(r),r.__checked=1);for(n=t.length;n--;)delete t[n].__checked;return t}var n=/^([\\w\\\\*]+)?(?:#([\\w\\\\]+))?(?:\\.([\\w\\\\\\.]+))?(?:\\[\\@?([\\w\\\\]+)([\\^\\$\\*!~]?=)([\\w\\\\]+)\\])?(?:\\:(.+))?/i,r=/((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,i=/^\\s*|\\s*$/g,o,a=e.extend({init:function(e){function t(e){return e?(e=e.toLowerCase(),function(t){return\"*\"===e||t.type===e}):void 0}function o(e){return e?function(t){return t._name===e}:void 0}function a(e){return e?(e=e.split(\".\"),function(t){for(var n=e.length;n--;)if(!t.hasClass(e[n]))return!1;return!0}):void 0}function s(e,t,n){return e?function(r){var i=r[e]?r[e]():\"\";return t?\"=\"===t?i===n:\"*=\"===t?i.indexOf(n)>=0:\"~=\"===t?(\" \"+i+\" \").indexOf(\" \"+n+\" \")>=0:\"!=\"===t?i!=n:\"^=\"===t?0===i.indexOf(n):\"$=\"===t?i.substr(i.length-n.length)===n:!1:!!n}:void 0}function l(e){var t;return e?(e=/(?:not\\((.+)\\))|(.+)/i.exec(e),e[1]?(t=u(e[1],[]),function(e){return!d(e,t)}):(e=e[2],function(t,n,r){return\"first\"===e?0===n:\"last\"===e?n===r-1:\"even\"===e?n%2===0:\"odd\"===e?n%2===1:t[e]?t[e]():!1})):void 0}function c(e,r,c){function u(e){e&&r.push(e)}var d;return d=n.exec(e.replace(i,\"\")),u(t(d[1])),u(o(d[2])),u(a(d[3])),u(s(d[4],d[5],d[6])),u(l(d[7])),r.psuedo=!!d[7],r.direct=c,r}function u(e,t){var n=[],i,o,a;do if(r.exec(\"\"),o=r.exec(e),o&&(e=o[3],n.push(o[1]),o[2])){i=o[3];break}while(o);for(i&&u(i,t),e=[],a=0;a\"!=n[a]&&e.push(c(n[a],[],\">\"===n[a-1]));return t.push(e),t}var d=this.match;this._selectors=u(e,[])},match:function(e,t){var n,r,i,o,a,s,l,c,u,d,f,p,h;for(t=t||this._selectors,n=0,r=t.length;r>n;n++){for(a=t[n],o=a.length,h=e,p=0,i=o-1;i>=0;i--)for(c=a[i];h;){if(c.psuedo)for(f=h.parent().items(),u=d=f.length;u--&&f[u]!==h;);for(s=0,l=c.length;l>s;s++)if(!c[s](h,u,d)){s=l+1;break}if(s===l){p++;break}if(i===o-1)break;h=h.parent()}if(p===o)return!0}return!1},find:function(e){function n(e,t,i){var o,a,s,l,c,u=t[i];for(o=0,a=e.length;a>o;o++){for(c=e[o],s=0,l=u.length;l>s;s++)if(!u[s](c,o,a)){s=l+1;break}if(s===l)i==t.length-1?r.push(c):c.items&&n(c.items(),t,i+1);else if(u.direct)return;c.items&&n(c.items(),t,i)}}var r=[],i,s,l=this._selectors;if(e.items){for(i=0,s=l.length;s>i;i++)n(e.items(),l[i],0);s>1&&(r=t(r))}return o||(o=a.Collection),new o(r)}});return a}),r(j,[d,q,U],function(e,t,n){var r,i,o=Array.prototype.push,a=Array.prototype.slice;return i={length:0,init:function(e){e&&this.add(e)},add:function(t){var n=this;return e.isArray(t)?o.apply(n,t):t instanceof r?n.add(t.toArray()):o.call(n,t),n},set:function(e){var t=this,n=t.length,r;for(t.length=0,t.add(e),r=t.length;n>r;r++)delete t[r];return t},filter:function(e){var n=this,i,o,a=[],s,l;for(\"string\"==typeof e?(e=new t(e),l=function(t){return e.match(t)}):l=e,i=0,o=n.length;o>i;i++)s=n[i],l(s)&&a.push(s);\n\nreturn new r(a)},slice:function(){return new r(a.apply(this,arguments))},eq:function(e){return-1===e?this.slice(e):this.slice(e,+e+1)},each:function(t){return e.each(this,t),this},toArray:function(){return e.toArray(this)},indexOf:function(e){for(var t=this,n=t.length;n--&&t[n]!==e;);return n},reverse:function(){return new r(e.toArray(this).reverse())},hasClass:function(e){return this[0]?this[0].hasClass(e):!1},prop:function(e,t){var n=this,r,i;return t!==r?(n.each(function(n){n[e]&&n[e](t)}),n):(i=n[0],i&&i[e]?i[e]():void 0)},exec:function(t){var n=this,r=e.toArray(arguments).slice(1);return n.each(function(e){e[t]&&e[t].apply(e,r)}),n},remove:function(){for(var e=this.length;e--;)this[e].remove();return this}},e.each(\"fire on off show hide addClass removeClass append prepend before after reflow\".split(\" \"),function(t){i[t]=function(){var n=e.toArray(arguments);return this.each(function(e){t in e&&e[t].apply(e,n)}),this}}),e.each(\"text name disabled active selected checked visible parent value data\".split(\" \"),function(e){i[e]=function(t){return this.prop(e,t)}}),r=n.extend(i),t.Collection=r,r}),r(K,[d,y],function(e,t){var n=0;return{id:function(){return\"mceu_\"+n++},createFragment:function(e){return t.DOM.createFragment(e)},getWindowSize:function(){return t.DOM.getViewPort()},getSize:function(e){var t,n;if(e.getBoundingClientRect){var r=e.getBoundingClientRect();t=Math.max(r.width||r.right-r.left,e.offsetWidth),n=Math.max(r.height||r.bottom-r.bottom,e.offsetHeight)}else t=e.offsetWidth,n=e.offsetHeight;return{width:t,height:n}},getPos:function(e,n){return t.DOM.getPos(e,n)},getViewPort:function(e){return t.DOM.getViewPort(e)},get:function(e){return document.getElementById(e)},addClass:function(e,n){return t.DOM.addClass(e,n)},removeClass:function(e,n){return t.DOM.removeClass(e,n)},hasClass:function(e,n){return t.DOM.hasClass(e,n)},toggleClass:function(e,n,r){return t.DOM.toggleClass(e,n,r)},css:function(e,n,r){return t.DOM.setStyle(e,n,r)},getRuntimeStyle:function(e,n){return t.DOM.getStyle(e,n,!0)},on:function(e,n,r,i){return t.DOM.bind(e,n,r,i)},off:function(e,n,r){return t.DOM.unbind(e,n,r)},fire:function(e,n,r){return t.DOM.fire(e,n,r)},innerHtml:function(e,n){t.DOM.setHTML(e,n)}}}),r(Y,[U,d,$,j,K],function(e,t,n,r,i){function o(e){return e._eventDispatcher||(e._eventDispatcher=new n({scope:e,toggleEvent:function(t,r){r&&n.isNative(t)&&(e._nativeEvents||(e._nativeEvents={}),e._nativeEvents[t]=!0,e._rendered&&e.bindPendingEvents())}})),e._eventDispatcher}var a=\"onmousewheel\"in document,s=!1,l=\"mce-\",c=e.extend({Statics:{classPrefix:l},isRtl:function(){return c.rtl},classPrefix:l,init:function(e){var n=this,r,o;if(n.settings=e=t.extend({},n.Defaults,e),n._id=e.id||i.id(),n._text=n._name=\"\",n._width=n._height=0,n._aria={role:e.role},this._elmCache={},r=e.classes)for(r=r.split(\" \"),r.map={},o=r.length;o--;)r.map[r[o]]=!0;n._classes=r||[],n.visible(!0),t.each(\"title text width height name classes visible disabled active value\".split(\" \"),function(t){var r=e[t],i;r!==i?n[t](r):n[\"_\"+t]===i&&(n[\"_\"+t]=!1)}),n.on(\"click\",function(){return n.disabled()?!1:void 0}),e.classes&&t.each(e.classes.split(\" \"),function(e){n.addClass(e)}),n.settings=e,n._borderBox=n.parseBox(e.border),n._paddingBox=n.parseBox(e.padding),n._marginBox=n.parseBox(e.margin),e.hidden&&n.hide()},Properties:\"parent,title,text,width,height,disabled,active,name,value\",Methods:\"renderHtml\",getContainerElm:function(){return document.body},getParentCtrl:function(e){for(var t,n=this.getRoot().controlIdLookup;e&&n&&!(t=n[e.id]);)e=e.parentNode;return t},parseBox:function(e){var t,n=10;if(e)return\"number\"==typeof e?(e=e||0,{top:e,left:e,bottom:e,right:e}):(e=e.split(\" \"),t=e.length,1===t?e[1]=e[2]=e[3]=e[0]:2===t?(e[2]=e[0],e[3]=e[1]):3===t&&(e[3]=e[1]),{top:parseInt(e[0],n)||0,right:parseInt(e[1],n)||0,bottom:parseInt(e[2],n)||0,left:parseInt(e[3],n)||0})},borderBox:function(){return this._borderBox},paddingBox:function(){return this._paddingBox},marginBox:function(){return this._marginBox},measureBox:function(e,t){function n(t){var n=document.defaultView;return n?(t=t.replace(/[A-Z]/g,function(e){return\"-\"+e}),n.getComputedStyle(e,null).getPropertyValue(t)):e.currentStyle[t]}function r(e){var t=parseFloat(n(e),10);return isNaN(t)?0:t}return{top:r(t+\"TopWidth\"),right:r(t+\"RightWidth\"),bottom:r(t+\"BottomWidth\"),left:r(t+\"LeftWidth\")}},initLayoutRect:function(){var e=this,t=e.settings,n,r,o=e.getEl(),a,s,l,c,u,d,f,p;n=e._borderBox=e._borderBox||e.measureBox(o,\"border\"),e._paddingBox=e._paddingBox||e.measureBox(o,\"padding\"),e._marginBox=e._marginBox||e.measureBox(o,\"margin\"),p=i.getSize(o),d=t.minWidth,f=t.minHeight,l=d||p.width,c=f||p.height,a=t.width,s=t.height,u=t.autoResize,u=\"undefined\"!=typeof u?u:!a&&!s,a=a||l,s=s||c;var h=n.left+n.right,m=n.top+n.bottom,g=t.maxWidth||65535,v=t.maxHeight||65535;return e._layoutRect=r={x:t.x||0,y:t.y||0,w:a,h:s,deltaW:h,deltaH:m,contentW:a-h,contentH:s-m,innerW:a-h,innerH:s-m,startMinWidth:d||0,startMinHeight:f||0,minW:Math.min(l,g),minH:Math.min(c,v),maxW:g,maxH:v,autoResize:u,scrollW:0},e._lastLayoutRect={},r},layoutRect:function(e){var t=this,n=t._layoutRect,r,i,o,a,s,l;return n||(n=t.initLayoutRect()),e?(o=n.deltaW,a=n.deltaH,e.x!==s&&(n.x=e.x),e.y!==s&&(n.y=e.y),e.minW!==s&&(n.minW=e.minW),e.minH!==s&&(n.minH=e.minH),i=e.w,i!==s&&(i=in.maxW?n.maxW:i,n.w=i,n.innerW=i-o),i=e.h,i!==s&&(i=in.maxH?n.maxH:i,n.h=i,n.innerH=i-a),i=e.innerW,i!==s&&(i=in.maxW-o?n.maxW-o:i,n.innerW=i,n.w=i+o),i=e.innerH,i!==s&&(i=in.maxH-a?n.maxH-a:i,n.innerH=i,n.h=i+a),e.contentW!==s&&(n.contentW=e.contentW),e.contentH!==s&&(n.contentH=e.contentH),r=t._lastLayoutRect,(r.x!==n.x||r.y!==n.y||r.w!==n.w||r.h!==n.h)&&(l=c.repaintControls,l&&l.map&&!l.map[t._id]&&(l.push(t),l.map[t._id]=!0),r.x=n.x,r.y=n.y,r.w=n.w,r.h=n.h),t):n},repaint:function(){var e=this,t,n,r,i,o=0,a=0,s,l;l=document.createRange?function(e){return e}:Math.round,t=e.getEl().style,r=e._layoutRect,s=e._lastRepaintRect||{},i=e._borderBox,o=i.left+i.right,a=i.top+i.bottom,r.x!==s.x&&(t.left=l(r.x)+\"px\",s.x=r.x),r.y!==s.y&&(t.top=l(r.y)+\"px\",s.y=r.y),r.w!==s.w&&(t.width=l(r.w-o)+\"px\",s.w=r.w),r.h!==s.h&&(t.height=l(r.h-a)+\"px\",s.h=r.h),e._hasBody&&r.innerW!==s.innerW&&(n=e.getEl(\"body\").style,n.width=l(r.innerW)+\"px\",s.innerW=r.innerW),e._hasBody&&r.innerH!==s.innerH&&(n=n||e.getEl(\"body\").style,n.height=l(r.innerH)+\"px\",s.innerH=r.innerH),e._lastRepaintRect=s,e.fire(\"repaint\",{},!1)},on:function(e,t){function n(e){var t,n;return\"string\"!=typeof e?e:function(i){return t||r.parentsAndSelf().each(function(r){var i=r.settings.callbacks;return i&&(t=i[e])?(n=r,!1):void 0}),t.call(n,i)}}var r=this;return o(r).on(e,n(t)),r},off:function(e,t){return o(this).off(e,t),this},fire:function(e,t,n){var r=this;if(t=t||{},t.control||(t.control=r),t=o(r).fire(e,t),n!==!1&&r.parent)for(var i=r.parent();i&&!t.isPropagationStopped();)i.fire(e,t,!1),i=i.parent();return t},hasEventListeners:function(e){return o(this).has(e)},parents:function(e){var t=this,n,i=new r;for(n=t.parent();n;n=n.parent())i.add(n);return e&&(i=i.filter(e)),i},parentsAndSelf:function(e){return new r(this).add(this.parents(e))},next:function(){var e=this.parent().items();return e[e.indexOf(this)+1]},prev:function(){var e=this.parent().items();return e[e.indexOf(this)-1]},findCommonAncestor:function(e,t){for(var n;e;){for(n=t;n&&e!=n;)n=n.parent();if(e==n)break;e=e.parent()}return e},hasClass:function(e,t){var n=this._classes[t||\"control\"];return e=this.classPrefix+e,n&&!!n.map[e]},addClass:function(e,t){var n=this,r,i;return e=this.classPrefix+e,r=n._classes[t||\"control\"],r||(r=[],r.map={},n._classes[t||\"control\"]=r),r.map[e]||(r.map[e]=e,r.push(e),n._rendered&&(i=n.getEl(t),i&&(i.className=r.join(\" \")))),n},removeClass:function(e,t){var n=this,r,i,o;if(e=this.classPrefix+e,r=n._classes[t||\"control\"],r&&r.map[e])for(delete r.map[e],i=r.length;i--;)r[i]===e&&r.splice(i,1);return n._rendered&&(o=n.getEl(t),o&&(o.className=r.join(\" \"))),n},toggleClass:function(e,t,n){var r=this;return t?r.addClass(e,n):r.removeClass(e,n),r},classes:function(e){var t=this._classes[e||\"control\"];return t?t.join(\" \"):\"\"},innerHtml:function(e){return i.innerHtml(this.getEl(),e),this},getEl:function(e){var t=e?this._id+\"-\"+e:this._id;return this._elmCache[t]||(this._elmCache[t]=i.get(t)),this._elmCache[t]},visible:function(e){var t=this,n;return\"undefined\"!=typeof e?(t._visible!==e&&(t._rendered&&(t.getEl().style.display=e?\"\":\"none\"),t._visible=e,n=t.parent(),n&&(n._lastRect=null),t.fire(e?\"show\":\"hide\")),t):t._visible},show:function(){return this.visible(!0)},hide:function(){return this.visible(!1)},focus:function(){try{this.getEl().focus()}catch(e){}return this},blur:function(){return this.getEl().blur(),this},aria:function(e,t){var n=this,r=n.getEl(n.ariaTarget);return\"undefined\"==typeof t?n._aria[e]:(n._aria[e]=t,n._rendered&&r.setAttribute(\"role\"==e?e:\"aria-\"+e,t),n)},encode:function(e,t){return t!==!1&&(e=this.translate(e)),(e||\"\").replace(/[&<>\"]/g,function(e){return\"&#\"+e.charCodeAt(0)+\";\"})},translate:function(e){return c.translate?c.translate(e):e},before:function(e){var t=this,n=t.parent();return n&&n.insert(e,n.items().indexOf(t),!0),t},after:function(e){var t=this,n=t.parent();return n&&n.insert(e,n.items().indexOf(t)),t},remove:function(){var e=this,t=e.getEl(),n=e.parent(),r,o;if(e.items){var a=e.items().toArray();for(o=a.length;o--;)a[o].remove()}n&&n.items&&(r=[],n.items().each(function(t){t!==e&&r.push(t)}),n.items().set(r),n._lastRect=null),e._eventsRoot&&e._eventsRoot==e&&i.off(t);var s=e.getRoot().controlIdLookup;return s&&delete s[e._id],t&&t.parentNode&&t.parentNode.removeChild(t),e._rendered=!1,e},renderBefore:function(e){var t=this;return e.parentNode.insertBefore(i.createFragment(t.renderHtml()),e),t.postRender(),t},renderTo:function(e){var t=this;return e=e||t.getContainerElm(),e.appendChild(i.createFragment(t.renderHtml())),t.postRender(),t},postRender:function(){var e=this,t=e.settings,n,r,o,a,s;for(a in t)0===a.indexOf(\"on\")&&e.on(a.substr(2),t[a]);if(e._eventsRoot){for(o=e.parent();!s&&o;o=o.parent())s=o._eventsRoot;if(s)for(a in s._nativeEvents)e._nativeEvents[a]=!0}e.bindPendingEvents(),t.style&&(n=e.getEl(),n&&(n.setAttribute(\"style\",t.style),n.style.cssText=t.style)),e._visible||i.css(e.getEl(),\"display\",\"none\"),e.settings.border&&(r=e.borderBox(),i.css(e.getEl(),{\"border-top-width\":r.top,\"border-right-width\":r.right,\"border-bottom-width\":r.bottom,\"border-left-width\":r.left}));var l=e.getRoot();l.controlIdLookup||(l.controlIdLookup={}),l.controlIdLookup[e._id]=e;for(var c in e._aria)e.aria(c,e._aria[c]);e.fire(\"postrender\",{},!1)},scrollIntoView:function(e){function t(e,t){var n,r,i=e;for(n=r=0;i&&i!=t&&i.nodeType;)n+=i.offsetLeft||0,r+=i.offsetTop||0,i=i.offsetParent;return{x:n,y:r}}var n=this.getEl(),r=n.parentNode,i,o,a,s,l,c,u=t(n,r);return i=u.x,o=u.y,a=n.offsetWidth,s=n.offsetHeight,l=r.clientWidth,c=r.clientHeight,\"end\"==e?(i-=l-a,o-=c-s):\"center\"==e&&(i-=l/2-a/2,o-=c/2-s/2),r.scrollLeft=i,r.scrollTop=o,this},bindPendingEvents:function(){function e(e){var t=o.getParentCtrl(e.target);t&&t.fire(e.type,e)}function t(){var e=d._lastHoverCtrl;e&&(e.fire(\"mouseleave\",{target:e.getEl()}),e.parents().each(function(e){e.fire(\"mouseleave\",{target:e.getEl()})}),d._lastHoverCtrl=null)}function n(e){var t=o.getParentCtrl(e.target),n=d._lastHoverCtrl,r=0,i,a,s;if(t!==n){if(d._lastHoverCtrl=t,a=t.parents().toArray().reverse(),a.push(t),n){for(s=n.parents().toArray().reverse(),s.push(n),r=0;r=r;i--)n=s[i],n.fire(\"mouseleave\",{target:n.getEl()})}for(i=r;il;l++)d=u[l]._eventsRoot;for(d||(d=u[u.length-1]||o),o._eventsRoot=d,c=l,l=0;c>l;l++)u[l]._eventsRoot=d;var h=d._delegates;h||(h=d._delegates={});for(p in f){if(!f)return!1;\"wheel\"!==p||s?(\"mouseenter\"===p||\"mouseleave\"===p?d._hasMouseEnter||(i.on(d.getEl(),\"mouseleave\",t),i.on(d.getEl(),\"mouseover\",n),d._hasMouseEnter=1):h[p]||(i.on(d.getEl(),p,e),h[p]=!0),f[p]=!1):a?i.on(o.getEl(),\"mousewheel\",r):i.on(o.getEl(),\"DOMMouseScroll\",r)}}},getRoot:function(){for(var e=this,t,n=[];e;){if(e.rootControl){t=e.rootControl;break}n.push(e),t=e,e=e.parent()}t||(t=this);for(var r=n.length;r--;)n[r].rootControl=t;return t},reflow:function(){return this.repaint(),this}});return c}),r(G,[],function(){var e={},t;return{add:function(t,n){e[t.toLowerCase()]=n},has:function(t){return!!e[t.toLowerCase()]},create:function(n,r){var i,o,a;if(!t){a=tinymce.ui;for(o in a)e[o.toLowerCase()]=a[o];t=!0}if(\"string\"==typeof n?(r=r||{},r.type=n):(r=n,n=r.type),n=n.toLowerCase(),i=e[n],!i)throw new Error(\"Could not find control by type: \"+n);return i=new i(r),i.type=n,i}}}),r(X,[],function(){return function(e){function t(e){return e=e||b,e&&e.getAttribute(\"role\")}function n(e){for(var n,r=e||b;r=r.parentNode;)if(n=t(r))return n}function r(e){var t=b;return t?t.getAttribute(\"aria-\"+e):void 0}function i(e){var t=e.tagName.toUpperCase();return\"INPUT\"==t||\"TEXTAREA\"==t}function o(e){return i(e)&&!e.hidden?!0:/^(button|menuitem|checkbox|tab|menuitemcheckbox|option|gridcell)$/.test(t(e))?!0:!1}function a(e){function t(e){if(1==e.nodeType&&\"none\"!=e.style.display){o(e)&&n.push(e);for(var r=0;re?e=t.length-1:e>=t.length&&(e=0),t[e]&&t[e].focus(),e}function u(e,t){var n=-1,r=s();t=t||a(r.getEl());for(var i=0;i=0&&(n=t.getEl(),n&&n.parentNode.removeChild(n),n=e.getEl(),n&&n.parentNode.removeChild(n)),t.parent(this)},create:function(t){var n=this,i,a=[];return o.isArray(t)||(t=[t]),o.each(t,function(t){t&&(t instanceof e||(\"string\"==typeof t&&(t={type:t}),i=o.extend({},n.settings.defaults,t),t.type=i.type=i.type||t.type||n.settings.defaultType||(i.defaults?i.defaults.type:null),t=r.create(i)),a.push(t))}),a},renderNew:function(){var e=this;return e.items().each(function(t,n){var r,i;t.parent(e),t._rendered||(r=e.getEl(\"body\"),i=a.createFragment(t.renderHtml()),r.hasChildNodes()&&n<=r.childNodes.length-1?r.insertBefore(i,r.childNodes[n]):r.appendChild(i),t.postRender())}),e._layout.applyClasses(e),e._lastRect=null,e},append:function(e){return this.add(e).renderNew()},prepend:function(e){var t=this;return t.items().set(t.create(e).concat(t.items().toArray())),t.renderNew()},insert:function(e,t,n){var r=this,i,o,a;return e=r.create(e),i=r.items(),!n&&t=0&&t
'+(e.settings.html||\"\")+t.renderHtml(e)+\"
\"},postRender:function(){var e=this,t;return e.items().exec(\"postRender\"),e._super(),e._layout.postRender(e),e._rendered=!0,e.settings.style&&a.css(e.getEl(),e.settings.style),e.settings.border&&(t=e.borderBox(),a.css(e.getEl(),{\"border-top-width\":t.top,\"border-right-width\":t.right,\"border-bottom-width\":t.bottom,\"border-left-width\":t.left})),e.parent()||(e.keyboardNav=new i({root:e})),e},initLayoutRect:function(){var e=this,t=e._super();return e._layout.recalc(e),t},recalc:function(){var e=this,t=e._layoutRect,n=e._lastRect;return n&&n.w==t.w&&n.h==t.h?void 0:(e._layout.recalc(e),t=e.layoutRect(),e._lastRect={x:t.x,y:t.y,w:t.w,h:t.h},!0)},reflow:function(){var t;if(this.visible()){for(e.repaintControls=[],e.repaintControls.map={},this.recalc(),t=e.repaintControls.length;t--;)e.repaintControls[t].repaint();\"flow\"!==this.settings.layout&&\"stack\"!==this.settings.layout&&this.repaint(),e.repaintControls=[]}return this}})}),r(Q,[K],function(e){function t(){var e=document,t,n,r,i,o,a,s,l,c=Math.max;return t=e.documentElement,n=e.body,r=c(t.scrollWidth,n.scrollWidth),i=c(t.clientWidth,n.clientWidth),o=c(t.offsetWidth,n.offsetWidth),a=c(t.scrollHeight,n.scrollHeight),s=c(t.clientHeight,n.clientHeight),l=c(t.offsetHeight,n.offsetHeight),{width:o>r?i:r,height:l>a?s:a}}return function(n,r){function i(){return a.getElementById(r.handle||n)}var o,a=document,s,l,c,u,d,f;r=r||{},l=function(n){var l=t(),p,h;n.preventDefault(),s=n.button,p=i(),d=n.screenX,f=n.screenY,h=window.getComputedStyle?window.getComputedStyle(p,null).getPropertyValue(\"cursor\"):p.runtimeStyle.cursor,o=a.createElement(\"div\"),e.css(o,{position:\"absolute\",top:0,left:0,width:l.width,height:l.height,zIndex:2147483647,opacity:1e-4,cursor:h}),a.body.appendChild(o),e.on(a,\"mousemove\",u),e.on(a,\"mouseup\",c),r.start(n)},u=function(e){return e.button!==s?c(e):(e.deltaX=e.screenX-d,e.deltaY=e.screenY-f,e.preventDefault(),void r.drag(e))},c=function(t){e.off(a,\"mousemove\",u),e.off(a,\"mouseup\",c),o.parentNode.removeChild(o),r.stop&&r.stop(t)},this.destroy=function(){e.off(i())},e.on(i(),\"mousedown\",l)}}),r(Z,[K,Q],function(e,t){return{init:function(){var e=this;e.on(\"repaint\",e.renderScroll)},renderScroll:function(){function n(){function t(t,a,s,l,c,u){var d,f,p,h,m,g,v,y,b;if(f=i.getEl(\"scroll\"+t)){if(y=a.toLowerCase(),b=s.toLowerCase(),i.getEl(\"absend\")&&e.css(i.getEl(\"absend\"),y,i.layoutRect()[l]-1),!c)return void e.css(f,\"display\",\"none\");e.css(f,\"display\",\"block\"),d=i.getEl(\"body\"),p=i.getEl(\"scroll\"+t+\"t\"),h=d[\"client\"+s]-2*o,h-=n&&r?f[\"client\"+u]:0,m=d[\"scroll\"+s],g=h/m,v={},v[y]=d[\"offset\"+a]+o,v[b]=h,e.css(f,v),v={},v[y]=d[\"scroll\"+a]*g,v[b]=h*g,e.css(p,v)}}var n,r,a;a=i.getEl(\"body\"),n=a.scrollWidth>a.clientWidth,r=a.scrollHeight>a.clientHeight,t(\"h\",\"Left\",\"Width\",\"contentW\",n,\"Height\"),t(\"v\",\"Top\",\"Height\",\"contentH\",r,\"Width\")}function r(){function n(n,r,a,s,l){var c,u=i._id+\"-scroll\"+n,d=i.classPrefix;i.getEl().appendChild(e.createFragment('
')),i.draghelper=new t(u+\"t\",{start:function(){c=i.getEl(\"body\")[\"scroll\"+r],e.addClass(e.get(u),d+\"active\")},drag:function(e){var t,u,d,f,p=i.layoutRect();u=p.contentW>p.innerW,d=p.contentH>p.innerH,f=i.getEl(\"body\")[\"client\"+a]-2*o,f-=u&&d?i.getEl(\"scroll\"+n)[\"client\"+l]:0,t=f/i.getEl(\"body\")[\"scroll\"+a],i.getEl(\"body\")[\"scroll\"+r]=c+e[\"delta\"+s]/t},stop:function(){e.removeClass(e.get(u),d+\"active\")}})}i.addClass(\"scroll\"),n(\"v\",\"Top\",\"Height\",\"Y\",\"Width\"),n(\"h\",\"Left\",\"Width\",\"X\",\"Height\")}var i=this,o=2;i.settings.autoScroll&&(i._hasScroll||(i._hasScroll=!0,r(),i.on(\"wheel\",function(e){var t=i.getEl(\"body\");t.scrollLeft+=10*(e.deltaX||0),t.scrollTop+=10*e.deltaY,n()}),e.on(i.getEl(\"body\"),\"scroll\",n)),n())}}}),r(ee,[J,Z],function(e,t){return e.extend({Defaults:{layout:\"fit\",containerCls:\"panel\"},Mixins:[t],renderHtml:function(){var e=this,t=e._layout,n=e.settings.html;return e.preRender(),t.preRender(e),\"undefined\"==typeof n?n='
'+t.renderHtml(e)+\"
\":(\"function\"==typeof n&&(n=n.call(e)),e._hasBody=!1),'
'+(e._preBodyHtml||\"\")+n+\"
\"}})}),r(te,[K],function(e){function t(t,n,r){var i,o,a,s,l,c,u,d,f,p;return f=e.getViewPort(),o=e.getPos(n),a=o.x,s=o.y,t._fixed&&\"static\"==e.getRuntimeStyle(document.body,\"position\")&&(a-=f.x,s-=f.y),i=t.getEl(),p=e.getSize(i),l=p.width,c=p.height,p=e.getSize(n),u=p.width,d=p.height,r=(r||\"\").split(\"\"),\"b\"===r[0]&&(s+=d),\"r\"===r[1]&&(a+=u),\"c\"===r[0]&&(s+=Math.round(d/2)),\"c\"===r[1]&&(a+=Math.round(u/2)),\"b\"===r[3]&&(s-=c),\"r\"===r[4]&&(a-=l),\"c\"===r[3]&&(s-=Math.round(c/2)),\"c\"===r[4]&&(a-=Math.round(l/2)),{x:a,y:s,w:l,h:c}}return{testMoveRel:function(n,r){for(var i=e.getViewPort(),o=0;o0&&a.x+a.w0&&a.y+a.hi.x&&a.x+a.wi.y&&a.y+a.he?0:e+n>t?(e=t-n,0>e?0:e):e}var i=this;if(i.settings.constrainToViewport){var o=e.getViewPort(window),a=i.layoutRect();t=r(t,o.w+o.x,a.w),n=r(n,o.h+o.y,a.h)}return i._rendered?i.layoutRect({x:t,y:n}).repaint():(i.settings.x=t,i.settings.y=n),i.fire(\"move\",{x:t,y:n}),i}}}),r(ne,[K],function(e){return{resizeToContent:function(){this._layoutRect.autoResize=!0,this._lastRect=null,this.reflow()},resizeTo:function(t,n){if(1>=t||1>=n){var r=e.getWindowSize();t=1>=t?t*r.w:t,n=1>=n?n*r.h:n}return this._layoutRect.autoResize=!1,this.layoutRect({minW:t,minH:n,w:t,h:n}).reflow()},resizeBy:function(e,t){var n=this,r=n.layoutRect();return n.resizeTo(r.w+e,r.h+t)}}}),r(re,[ee,te,ne,K],function(e,t,n,r){function i(){function e(e,t){for(;e;){if(e==t)return!0;e=e.parent()}}u||(u=function(t){if(2!=t.button)for(var n=p.length;n--;){var r=p[n],i=r.getParentCtrl(t.target);if(r.settings.autohide){if(i&&(e(i,r)||r.parent()===i))continue;t=r.fire(\"autohide\",{target:t.target}),t.isDefaultPrevented()||r.hide()}}},r.on(document,\"click\",u))}function o(){d||(d=function(){var e;for(e=p.length;e--;)s(p[e])},r.on(window,\"scroll\",d))}function a(){if(!f){var e=document.documentElement,t=e.clientWidth,n=e.clientHeight;f=function(){document.all&&t==e.clientWidth&&n==e.clientHeight||(t=e.clientWidth,n=e.clientHeight,g.hideAll())},r.on(window,\"resize\",f)}}function s(e){function t(t,n){for(var r,i=0;in&&(e.fixed(!1).layoutRect({y:e._autoFixY}).repaint(),t(!1,e._autoFixY-n)):(e._autoFixY=e.layoutRect().y,e._autoFixY
'),n=n.firstChild,t.getContainerElm().appendChild(n),setTimeout(function(){r.addClass(n,i+\"in\"),r.addClass(t.getEl(),i+\"in\")},0),m=!0),l(!0,t)}}),t.on(\"show\",function(){t.parents().each(function(e){return e._fixed?(t.fixed(!0),!1):void 0})}),e.popover&&(t._preBodyHtml='
',t.addClass(\"popover\").addClass(\"bottom\").addClass(t.isRtl()?\"end\":\"start\"))},fixed:function(e){var t=this;if(t._fixed!=e){if(t._rendered){var n=r.getViewPort();e?t.layoutRect().y-=n.y:t.layoutRect().y+=n.y}t.toggleClass(\"fixed\",e),t._fixed=e}return t},show:function(){var e=this,t,n=e._super();for(t=p.length;t--&&p[t]!==e;);return-1===t&&p.push(e),n},hide:function(){return c(this),l(!1,this),this._super()},hideAll:function(){g.hideAll()},close:function(){var e=this;return e.fire(\"close\").isDefaultPrevented()||(e.remove(),l(!1,e)),e},remove:function(){c(this),this._super()},postRender:function(){var e=this;return e.settings.bodyRole&&this.getEl(\"body\").setAttribute(\"role\",e.settings.bodyRole),e._super()}});return g.hideAll=function(){for(var e=p.length;e--;){var t=p[e];t&&t.settings.autohide&&(t.hide(),p.splice(e,1))}},g}),r(ie,[re,ee,K,Q],function(e,t,n,r){var i=e.extend({modal:!0,Defaults:{border:1,layout:\"flex\",containerCls:\"panel\",role:\"dialog\",callbacks:{submit:function(){this.fire(\"submit\",{data:this.toJSON()})},close:function(){this.close()}}},init:function(e){var n=this;n._super(e),n.isRtl()&&n.addClass(\"rtl\"),n.addClass(\"window\"),n._fixed=!0,e.buttons&&(n.statusbar=new t({layout:\"flex\",border:\"1 0 0 0\",spacing:3,padding:10,align:\"center\",pack:n.isRtl()?\"start\":\"end\",defaults:{type:\"button\"},items:e.buttons}),n.statusbar.addClass(\"foot\"),n.statusbar.parent(n)),n.on(\"click\",function(e){-1!=e.target.className.indexOf(n.classPrefix+\"close\")&&n.close()}),n.on(\"cancel\",function(){n.close()}),n.aria(\"describedby\",n.describedBy||n._id+\"-none\"),n.aria(\"label\",e.title),n._fullscreen=!1},recalc:function(){var e=this,t=e.statusbar,r,i,o,a;e._fullscreen&&(e.layoutRect(n.getWindowSize()),e.layoutRect().contentH=e.layoutRect().innerH),e._super(),r=e.layoutRect(),e.settings.title&&!e._fullscreen&&(i=r.headerW,i>r.w&&(o=r.x-Math.max(0,i/2),e.layoutRect({w:i,x:o}),a=!0)),t&&(t.layoutRect({w:e.layoutRect().innerW}).recalc(),i=t.layoutRect().minW+r.deltaW,i>r.w&&(o=r.x-Math.max(0,i-r.w),e.layoutRect({w:i,x:o}),a=!0)),a&&e.recalc()},initLayoutRect:function(){var e=this,t=e._super(),r=0,i;if(e.settings.title&&!e._fullscreen){i=e.getEl(\"head\");var o=n.getSize(i);t.headerW=o.width,t.headerH=o.height,r+=t.headerH}e.statusbar&&(r+=e.statusbar.layoutRect().h),t.deltaH+=r,t.minH+=r,t.h+=r;var a=n.getWindowSize();return t.x=Math.max(0,a.w/2-t.w/2),t.y=Math.max(0,a.h/2-t.h/2),t},renderHtml:function(){var e=this,t=e._layout,n=e._id,r=e.classPrefix,i=e.settings,o=\"\",a=\"\",s=i.html;return e.preRender(),t.preRender(e),i.title&&(o='
'+e.encode(i.title)+'
'),i.url&&(s=''),\"undefined\"==typeof s&&(s=t.renderHtml(e)),e.statusbar&&(a=e.statusbar.renderHtml()),'
'+o+'
'+s+\"
\"+a+\"
\"},fullscreen:function(e){var t=this,r=document.documentElement,i,o=t.classPrefix,a;if(e!=t._fullscreen)if(n.on(window,\"resize\",function(){var e;if(t._fullscreen)if(i)t._timer||(t._timer=setTimeout(function(){var e=n.getWindowSize();t.moveTo(0,0).resizeTo(e.w,e.h),t._timer=0},50));else{e=(new Date).getTime();var r=n.getWindowSize();t.moveTo(0,0).resizeTo(r.w,r.h),(new Date).getTime()-e>50&&(i=!0)}}),a=t.layoutRect(),t._fullscreen=e,e){t._initial={x:a.x,y:a.y,w:a.w,h:a.h},t._borderBox=t.parseBox(\"0\"),t.getEl(\"head\").style.display=\"none\",a.deltaH-=a.headerH+2,n.addClass(r,o+\"fullscreen\"),n.addClass(document.body,o+\"fullscreen\"),t.addClass(\"fullscreen\");var s=n.getWindowSize();t.moveTo(0,0).resizeTo(s.w,s.h)}else t._borderBox=t.parseBox(t.settings.border),t.getEl(\"head\").style.display=\"\",a.deltaH+=a.headerH,n.removeClass(r,o+\"fullscreen\"),n.removeClass(document.body,o+\"fullscreen\"),t.removeClass(\"fullscreen\"),t.moveTo(t._initial.x,t._initial.y).resizeTo(t._initial.w,t._initial.h);return t.reflow()},postRender:function(){var e=this,t;setTimeout(function(){e.addClass(\"in\")},0),e._super(),e.statusbar&&e.statusbar.postRender(),e.focus(),this.dragHelper=new r(e._id+\"-dragh\",{start:function(){t={x:e.layoutRect().x,y:e.layoutRect().y}},drag:function(n){e.moveTo(t.x+n.deltaX,t.y+n.deltaY)}}),e.on(\"submit\",function(t){t.isDefaultPrevented()||e.close()})},submit:function(){return this.fire(\"submit\",{data:this.toJSON()})},remove:function(){var e=this,t=e.classPrefix;e.dragHelper.destroy(),e._super(),e.statusbar&&this.statusbar.remove(),e._fullscreen&&(n.removeClass(document.documentElement,t+\"fullscreen\"),n.removeClass(document.body,t+\"fullscreen\"))},getContentWindow:function(){var e=this.getEl().getElementsByTagName(\"iframe\")[0];return e?e.contentWindow:null}});return i}),r(oe,[ie],function(e){var t=e.extend({init:function(e){e={border:1,padding:20,layout:\"flex\",pack:\"center\",align:\"center\",containerCls:\"panel\",autoScroll:!0,buttons:{type:\"button\",text:\"Ok\",action:\"ok\"},items:{type:\"label\",multiline:!0,maxWidth:500,maxHeight:200}},this._super(e)},Statics:{OK:1,OK_CANCEL:2,YES_NO:3,YES_NO_CANCEL:4,msgBox:function(n){function r(e,t,n){return{type:\"button\",text:e,subtype:n?\"primary\":\"\",onClick:function(e){e.control.parents()[1].close(),o(t)}}}var i,o=n.callback||function(){};switch(n.buttons){case t.OK_CANCEL:i=[r(\"Ok\",!0,!0),r(\"Cancel\",!1)];break;case t.YES_NO:case t.YES_NO_CANCEL:i=[r(\"Yes\",1,!0),r(\"No\",0)],n.buttons==t.YES_NO_CANCEL&&i.push(r(\"Cancel\",-1));break;default:i=[r(\"Ok\",!0,!0)]}return new e({padding:20,x:n.x,y:n.y,minWidth:300,minHeight:100,layout:\"flex\",pack:\"center\",align:\"center\",buttons:i,title:n.title,role:\"alertdialog\",items:{type:\"label\",multiline:!0,maxWidth:500,maxHeight:200,text:n.text},onPostRender:function(){this.aria(\"describedby\",this.items()[0]._id)},onClose:n.onClose,onCancel:function(){o(!1)}}).renderTo(document.body).reflow()},alert:function(e,n){return\"string\"==typeof e&&(e={\ntext:e}),e.callback=n,t.msgBox(e)},confirm:function(e,n){return\"string\"==typeof e&&(e={text:e}),e.callback=n,e.buttons=t.OK_CANCEL,t.msgBox(e)}}});return t}),r(ae,[ie,oe],function(e,t){return function(n){function r(){return o.length?o[o.length-1]:void 0}var i=this,o=[];i.windows=o,n.on(\"remove\",function(){for(var e=o.length;e--;)o[e].close()}),i.open=function(t,r){var i;return n.editorManager.setActive(n),t.title=t.title||\" \",t.url=t.url||t.file,t.url&&(t.width=parseInt(t.width||320,10),t.height=parseInt(t.height||240,10)),t.body&&(t.items={defaults:t.defaults,type:t.bodyType||\"form\",items:t.body}),t.url||t.buttons||(t.buttons=[{text:\"Ok\",subtype:\"primary\",onclick:function(){i.find(\"form\")[0].submit()}},{text:\"Cancel\",onclick:function(){i.close()}}]),i=new e(t),o.push(i),i.on(\"close\",function(){for(var e=o.length;e--;)o[e]===i&&o.splice(e,1);o.length||n.focus()}),t.data&&i.on(\"postRender\",function(){this.find(\"*\").each(function(e){var n=e.name();n in t.data&&e.value(t.data[n])})}),i.features=t||{},i.params=r||{},1===o.length&&n.nodeChanged(),i.renderTo().reflow()},i.alert=function(e,r,i){t.alert(e,function(){r?r.call(i||this):n.focus()})},i.confirm=function(e,n,r){t.confirm(e,function(e){n.call(r||this,e)})},i.close=function(){r()&&r().close()},i.getParams=function(){return r()?r().params:null},i.setParams=function(e){r()&&(r().params=e)},i.getWindows=function(){return o}}}),r(se,[B,x,h,_,g,u,d],function(e,t,n,r,i,o,a){return function(s){function l(e,t){try{s.getDoc().execCommand(e,!1,t)}catch(n){}}function c(){var e=s.getDoc().documentMode;return e?e:6}function u(e){return e.isDefaultPrevented()}function d(e){var t;e.dataTransfer&&(s.selection.isCollapsed()&&\"IMG\"==e.target.tagName&&Q.select(e.target),t=s.selection.getContent(),t.length>0&&e.dataTransfer.setData(ae,oe+escape(t)))}function f(e){var t,n;return e.dataTransfer&&(t=e.dataTransfer.getData(ae),t&&t.indexOf(oe)>=0&&(n=unescape(t.substr(oe.length)))),n}function p(e){s.queryCommandSupported(\"mceInsertClipboardContent\")?s.execCommand(\"mceInsertClipboardContent\",!1,{content:e}):s.execCommand(\"mceInsertContent\",!1,e)}function h(){function r(e){var t=v.schema.getBlockElements(),n=s.getBody();if(\"BR\"!=e.nodeName)return!1;for(e=e;e!=n&&!t[e.nodeName];e=e.parentNode)if(e.nextSibling)return!1;return!0}function i(e,t){var n;for(n=e.nextSibling;n&&n!=t;n=n.nextSibling)if((3!=n.nodeType||0!==Y.trim(n.data).length)&&n!==t)return!1;return n===t}function o(e,t,i){var o,a,s;for(s=v.schema.getNonEmptyElements(),o=new n(i||e,e);a=o[t?\"next\":\"prev\"]();){if(s[a.nodeName]&&!r(a))return a;if(3==a.nodeType&&a.data.length>0)return a}}function l(e){var n,r,i,a,l;if(!e.collapsed&&(n=v.getParent(t.getNode(e.startContainer,e.startOffset),v.isBlock),r=v.getParent(t.getNode(e.endContainer,e.endOffset),v.isBlock),l=s.schema.getTextBlockElements(),n!=r&&l[n.nodeName]&&l[r.nodeName]&&\"false\"!==v.getContentEditable(n)&&\"false\"!==v.getContentEditable(r)))return e.deleteContents(),i=o(n,!1),a=o(r,!0),v.isEmpty(r)||Y(n).append(r.childNodes),Y(r).remove(),i?1==i.nodeType?\"BR\"==i.nodeName?(e.setStartBefore(i),e.setEndBefore(i)):(e.setStartAfter(i),e.setEndAfter(i)):(e.setStart(i,i.data.length),e.setEnd(i,i.data.length)):a&&(1==a.nodeType?(e.setStartBefore(a),e.setEndBefore(a)):(e.setStart(a,0),e.setEnd(a,0))),y.setRng(e),!0}function c(e,n){var r,a,l,c,u,d;if(!e.collapsed)return e;if(u=e.startContainer,d=e.startOffset,3==u.nodeType)if(n){if(d0)return e;if(r=t.getNode(e.startContainer,e.startOffset),l=v.getParent(r,v.isBlock),a=o(s.getBody(),n,r),c=v.getParent(a,v.isBlock),!r||!a)return e;if(c&&l!=c)if(n){if(!i(l,c))return e;1==r.nodeType?\"BR\"==r.nodeName?e.setStartBefore(r):e.setStartAfter(r):e.setStart(r,r.data.length),1==a.nodeType?e.setEnd(a,0):e.setEndBefore(a)}else{if(!i(c,l))return e;1==a.nodeType?\"BR\"==a.nodeName?e.setStartBefore(a):e.setStartAfter(a):e.setStart(a,a.data.length),1==r.nodeType?e.setEnd(r,0):e.setEndBefore(r)}return e}function h(e){var t=y.getRng();return t=c(t,e),l(t)?!0:void 0}function m(e){var t,n,r;h(e)||(a.each(s.getBody().getElementsByTagName(\"*\"),function(e){\"SPAN\"==e.tagName&&e.setAttribute(\"mce-data-marked\",1),!e.hasAttribute(\"data-mce-style\")&&e.hasAttribute(\"style\")&&s.dom.setAttrib(e,\"style\",s.dom.getAttrib(e,\"style\"))}),t=new b(function(){}),t.observe(s.getDoc(),{childList:!0,attributes:!0,subtree:!0,attributeFilter:[\"style\"]}),s.getDoc().execCommand(e?\"ForwardDelete\":\"Delete\",!1,null),n=s.selection.getRng(),r=n.startContainer.parentNode,a.each(t.takeRecords(),function(e){if(v.isChildOf(e.target,s.getBody())){if(\"style\"==e.attributeName){var t=e.target.getAttribute(\"data-mce-style\");t?e.target.setAttribute(\"style\",t):e.target.removeAttribute(\"style\")}a.each(e.addedNodes,function(e){if(\"SPAN\"==e.nodeName&&!e.getAttribute(\"mce-data-marked\")){var t,i;e==r&&(t=n.startOffset,i=e.firstChild),v.remove(e,!0),i&&(n.setStart(i,t),n.setEnd(i,t),s.selection.setRng(n))}})}}),t.disconnect(),a.each(s.dom.select(\"span[mce-data-marked]\"),function(e){e.removeAttribute(\"mce-data-marked\")}))}var g=s.getDoc(),v=s.dom,y=s.selection,b=window.MutationObserver,C,x;b||(C=!0,b=function(){function e(e){var t=e.relatedNode||e.target;n.push({target:t,addedNodes:[t]})}function t(e){var t=e.relatedNode||e.target;n.push({target:t,attributeName:e.attrName})}var n=[],r;this.observe=function(n){r=n,r.addEventListener(\"DOMSubtreeModified\",e,!1),r.addEventListener(\"DOMNodeInsertedIntoDocument\",e,!1),r.addEventListener(\"DOMNodeInserted\",e,!1),r.addEventListener(\"DOMAttrModified\",t,!1)},this.disconnect=function(){r.removeEventListener(\"DOMSubtreeModified\",e,!1),r.removeEventListener(\"DOMNodeInsertedIntoDocument\",e,!1),r.removeEventListener(\"DOMNodeInserted\",e,!1),r.removeEventListener(\"DOMAttrModified\",t,!1)},this.takeRecords=function(){return n}}),s.on(\"keydown\",function(e){var t=e.keyCode==X,n=e.ctrlKey||e.metaKey;if(!u(e)&&(t||e.keyCode==G)){var r=s.selection.getRng(),i=r.startContainer,o=r.startOffset;if(!n&&r.collapsed&&3==i.nodeType&&(t?o0))return;e.preventDefault(),n&&s.selection.getSel().modify(\"extend\",t?\"forward\":\"backward\",e.metaKey?\"lineboundary\":\"word\"),m(t)}}),s.on(\"keypress\",function(t){if(!u(t)&&!y.isCollapsed()&&t.charCode&&!e.metaKeyPressed(t)){var n,r,i,o,a,l;n=s.selection.getRng(),l=String.fromCharCode(t.charCode),t.preventDefault(),r=Y(n.startContainer).parents().filter(function(e,t){return!!s.schema.getTextInlineElements()[t.nodeName]}),m(!0),r=r.filter(function(e,t){return!Y.contains(s.getBody(),t)}),r.length?(i=v.createFragment(),r.each(function(e,t){t=t.cloneNode(!1),i.hasChildNodes()?(t.appendChild(i.firstChild),i.appendChild(t)):(a=t,i.appendChild(t)),i.appendChild(t)}),a.appendChild(s.getDoc().createTextNode(l)),o=v.getParent(n.startContainer,v.isBlock),v.isEmpty(o)?Y(o).empty().append(i):n.insertNode(i),n.setStart(a.firstChild,1),n.setEnd(a.firstChild,1),s.selection.setRng(n)):s.selection.setContent(l)}}),s.addCommand(\"Delete\",function(){m()}),s.addCommand(\"ForwardDelete\",function(){m(!0)}),C||(s.on(\"dragstart\",function(e){x=y.getRng(),d(e)}),s.on(\"drop\",function(e){if(!u(e)){var n=f(e);n&&(e.preventDefault(),window.setTimeout(function(){var r=t.getCaretRangeFromPoint(e.x,e.y,g);x&&(y.setRng(x),x=null),m(),y.setRng(r),p(n)},0))}}),s.on(\"cut\",function(e){!u(e)&&e.clipboardData&&(e.preventDefault(),e.clipboardData.clearData(),e.clipboardData.setData(\"text/html\",s.selection.getContent()),e.clipboardData.setData(\"text/plain\",s.selection.getContent({format:\"text\"})),m(!0))}))}function m(){function e(e){var t=J.create(\"body\"),n=e.cloneContents();return t.appendChild(n),Q.serializer.serialize(t,{format:\"html\"})}function n(n){if(!n.setStart){if(n.item)return!1;var r=n.duplicate();return r.moveToElementText(s.getBody()),t.compareRanges(n,r)}var i=e(n),o=J.createRng();o.selectNode(s.getBody());var a=e(o);return i===a}s.on(\"keydown\",function(e){var t=e.keyCode,r,i;if(!u(e)&&(t==X||t==G)){if(r=s.selection.isCollapsed(),i=s.getBody(),r&&!J.isEmpty(i))return;if(!r&&!n(s.selection.getRng()))return;e.preventDefault(),s.setContent(\"\"),i.firstChild&&J.isBlock(i.firstChild)?s.selection.setCursorLocation(i.firstChild,0):s.selection.setCursorLocation(i,0),s.nodeChanged()}})}function g(){s.shortcuts.add(\"meta+a\",null,\"SelectAll\")}function v(){s.settings.content_editable||(J.bind(s.getDoc(),\"focusin\",function(){Q.setRng(Q.getRng())}),J.bind(s.getDoc(),\"mousedown mouseup\",function(e){e.target==s.getDoc().documentElement&&(s.getBody().focus(),\"mousedown\"==e.type?Q.placeCaretAt(e.clientX,e.clientY):Q.setRng(Q.getRng()))}))}function y(){s.on(\"keydown\",function(e){if(!u(e)&&e.keyCode===G){if(!s.getBody().getElementsByTagName(\"hr\").length)return;if(Q.isCollapsed()&&0===Q.getRng(!0).startOffset){var t=Q.getNode(),n=t.previousSibling;if(\"HR\"==t.nodeName)return J.remove(t),void e.preventDefault();n&&n.nodeName&&\"hr\"===n.nodeName.toLowerCase()&&(J.remove(n),e.preventDefault())}}})}function b(){window.Range.prototype.getClientRects||s.on(\"mousedown\",function(e){if(!u(e)&&\"HTML\"===e.target.nodeName){var t=s.getBody();t.blur(),setTimeout(function(){t.focus()},0)}})}function C(){s.on(\"click\",function(e){var t=e.target;/^(IMG|HR)$/.test(t.nodeName)&&(e.preventDefault(),Q.getSel().setBaseAndExtent(t,0,t,1),s.nodeChanged()),\"A\"==t.nodeName&&J.hasClass(t,\"mce-item-anchor\")&&(e.preventDefault(),Q.select(t))})}function x(){function e(){var e=J.getAttribs(Q.getStart().cloneNode(!1));return function(){var t=Q.getStart();t!==s.getBody()&&(J.setAttrib(t,\"style\",null),K(e,function(e){t.setAttributeNode(e.cloneNode(!0))}))}}function t(){return!Q.isCollapsed()&&J.getParent(Q.getStart(),J.isBlock)!=J.getParent(Q.getEnd(),J.isBlock)}s.on(\"keypress\",function(n){var r;return u(n)||8!=n.keyCode&&46!=n.keyCode||!t()?void 0:(r=e(),s.getDoc().execCommand(\"delete\",!1,null),r(),n.preventDefault(),!1)}),J.bind(s.getDoc(),\"cut\",function(n){var r;!u(n)&&t()&&(r=e(),setTimeout(function(){r()},0))})}function w(){document.body.setAttribute(\"role\",\"application\")}function _(){s.on(\"keydown\",function(e){if(!u(e)&&e.keyCode===G&&Q.isCollapsed()&&0===Q.getRng(!0).startOffset){var t=Q.getNode().previousSibling;if(t&&t.nodeName&&\"table\"===t.nodeName.toLowerCase())return e.preventDefault(),!1}})}function E(){c()>7||(l(\"RespectVisibilityInDesign\",!0),s.contentStyles.push(\".mceHideBrInPre pre br {display: none}\"),J.addClass(s.getBody(),\"mceHideBrInPre\"),ee.addNodeFilter(\"pre\",function(e){for(var t=e.length,n,i,o,a;t--;)for(n=e[t].getAll(\"br\"),i=n.length;i--;)o=n[i],a=o.prev,a&&3===a.type&&\"\\n\"!=a.value.charAt(a.value-1)?a.value+=\"\\n\":o.parent.insert(new r(\"#text\",3),o,!0).value=\"\\n\"}),te.addNodeFilter(\"pre\",function(e){for(var t=e.length,n,r,i,o;t--;)for(n=e[t].getAll(\"br\"),r=n.length;r--;)i=n[r],o=i.prev,o&&3==o.type&&(o.value=o.value.replace(/\\r?\\n$/,\"\"))}))}function N(){J.bind(s.getBody(),\"mouseup\",function(){var e,t=Q.getNode();\"IMG\"==t.nodeName&&((e=J.getStyle(t,\"width\"))&&(J.setAttrib(t,\"width\",e.replace(/[^0-9%]+/g,\"\")),J.setStyle(t,\"width\",\"\")),(e=J.getStyle(t,\"height\"))&&(J.setAttrib(t,\"height\",e.replace(/[^0-9%]+/g,\"\")),J.setStyle(t,\"height\",\"\")))})}function k(){s.on(\"keydown\",function(t){var n,r,i,o,a;if(!u(t)&&t.keyCode==e.BACKSPACE&&(n=Q.getRng(),r=n.startContainer,i=n.startOffset,o=J.getRoot(),a=r,n.collapsed&&0===i)){for(;a&&a.parentNode&&a.parentNode.firstChild==a&&a.parentNode!=o;)a=a.parentNode;\"BLOCKQUOTE\"===a.tagName&&(s.formatter.toggle(\"blockquote\",null,a),n=J.createRng(),n.setStart(r,0),n.setEnd(r,0),Q.setRng(n))}})}function S(){function e(){s._refreshContentEditable(),l(\"StyleWithCSS\",!1),l(\"enableInlineTableEditing\",!1),Z.object_resizing||l(\"enableObjectResizing\",!1)}Z.readonly||s.on(\"BeforeExecCommand MouseDown\",e)}function T(){function e(){K(J.select(\"a\"),function(e){var t=e.parentNode,n=J.getRoot();if(t.lastChild===e){for(;t&&!J.isBlock(t);){if(t.parentNode.lastChild!==t||t===n)return;t=t.parentNode}J.add(t,\"br\",{\"data-mce-bogus\":1})}})}s.on(\"SetContent ExecCommand\",function(t){(\"setcontent\"==t.type||\"mceInsertLink\"===t.command)&&e()})}function R(){Z.forced_root_block&&s.on(\"init\",function(){l(\"DefaultParagraphSeparator\",Z.forced_root_block)})}function A(){s.on(\"Undo Redo SetContent\",function(e){e.initial||s.execCommand(\"mceRepaint\")})}function B(){s.on(\"keydown\",function(e){var t;u(e)||e.keyCode!=G||(t=s.getDoc().selection.createRange(),t&&t.item&&(e.preventDefault(),s.undoManager.beforeChange(),J.remove(t.item(0)),s.undoManager.add()))})}function D(){var e;c()>=10&&(e=\"\",K(\"p div h1 h2 h3 h4 h5 h6\".split(\" \"),function(t,n){e+=(n>0?\",\":\"\")+t+\":empty\"}),s.contentStyles.push(e+\"{padding-right: 1px !important}\"))}function M(){c()<9&&(ee.addNodeFilter(\"noscript\",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.firstChild,r&&n.attr(\"data-mce-innertext\",r.value)}),te.addNodeFilter(\"noscript\",function(e){for(var t=e.length,n,o,a;t--;)n=e[t],o=e[t].firstChild,o?o.value=i.decode(o.value):(a=n.attributes.map[\"data-mce-innertext\"],a&&(n.attr(\"data-mce-innertext\",null),o=new r(\"#text\",3),o.value=a,o.raw=!0,n.append(o)))}))}function H(){function e(e,t){var n=i.createTextRange();try{n.moveToPoint(e,t)}catch(r){n=null}return n}function t(t){var r;t.button?(r=e(t.x,t.y),r&&(r.compareEndPoints(\"StartToStart\",a)>0?r.setEndPoint(\"StartToStart\",a):r.setEndPoint(\"EndToEnd\",a),r.select())):n()}function n(){var e=r.selection.createRange();a&&!e.item&&0===e.compareEndPoints(\"StartToEnd\",e)&&a.select(),J.unbind(r,\"mouseup\",n),J.unbind(r,\"mousemove\",t),a=o=0}var r=J.doc,i=r.body,o,a,s;r.documentElement.unselectable=!0,J.bind(r,\"mousedown contextmenu\",function(i){if(\"HTML\"===i.target.nodeName){if(o&&n(),s=r.documentElement,s.scrollHeight>s.clientHeight)return;o=1,a=e(i.x,i.y),a&&(J.bind(r,\"mouseup\",n),J.bind(r,\"mousemove\",t),J.getRoot().focus(),a.select())}})}function L(){s.on(\"keyup focusin mouseup\",function(t){65==t.keyCode&&e.metaKeyPressed(t)||Q.normalize()},!0)}function P(){s.contentStyles.push(\"img:-moz-broken {-moz-force-broken-image-icon:1;min-width:24px;min-height:24px}\")}function O(){s.inline||s.on(\"keydown\",function(){document.activeElement==document.body&&s.getWin().focus()})}function I(){s.inline||(s.contentStyles.push(\"body {min-height: 150px}\"),s.on(\"click\",function(e){if(\"HTML\"==e.target.nodeName){var t;t=s.selection.getRng(),s.getBody().focus(),s.selection.setRng(t),s.selection.normalize(),s.nodeChanged()}}))}function F(){o.mac&&s.on(\"keydown\",function(t){!e.metaKeyPressed(t)||37!=t.keyCode&&39!=t.keyCode||(t.preventDefault(),s.selection.getSel().modify(\"move\",37==t.keyCode?\"backward\":\"forward\",\"lineboundary\"))})}function z(){l(\"AutoUrlDetect\",!1)}function W(){s.inline||s.on(\"focus blur beforegetcontent\",function(){var e=s.dom.create(\"br\");s.getBody().appendChild(e),e.parentNode.removeChild(e)},!0)}function V(){s.on(\"click\",function(e){var t=e.target;do if(\"A\"===t.tagName)return void e.preventDefault();while(t=t.parentNode)}),s.contentStyles.push(\".mce-content-body {-webkit-touch-callout: none}\")}function U(){s.on(\"touchstart\",function(e){var t,n,r,i;t=e.target,n=(new Date).getTime(),i=e.changedTouches,!i||i.length>1||(r=i[0],s.once(\"touchend\",function(e){var i=e.changedTouches[0],o;(new Date).getTime()-n>500||Math.abs(r.clientX-i.clientX)>5||Math.abs(r.clientY-i.clientY)>5||(o={target:t},K(\"pageX pageY clientX clientY screenX screenY\".split(\" \"),function(e){o[e]=i[e]}),o=s.fire(\"click\",o),o.isDefaultPrevented()||(s.selection.placeCaretAt(i.clientX,i.clientY),s.nodeChanged()))}))})}function $(){s.on(\"init\",function(){s.dom.bind(s.getBody(),\"submit\",function(e){e.preventDefault()})})}function q(){ee.addNodeFilter(\"br\",function(e){for(var t=e.length;t--;)\"Apple-interchange-newline\"==e[t].attr(\"class\")&&e[t].remove()})}function j(){s.on(\"dragstart\",function(e){d(e)}),s.on(\"drop\",function(e){if(!u(e)){var n=f(e);if(n){e.preventDefault();var r=t.getCaretRangeFromPoint(e.x,e.y,s.getDoc());Q.setRng(r),p(n)}}})}var K=a.each,Y=s.$,G=e.BACKSPACE,X=e.DELETE,J=s.dom,Q=s.selection,Z=s.settings,ee=s.parser,te=s.serializer,ne=o.gecko,re=o.ie,ie=o.webkit,oe=\"data:text/mce-internal,\",ae=re?\"Text\":\"URL\";k(),m(),L(),ie&&(h(),v(),C(),R(),$(),_(),q(),U(),o.iOS?(O(),I(),V()):g()),re&&o.ie<11&&(y(),w(),E(),N(),B(),D(),M(),H()),o.ie>=11&&(I(),W(),_()),o.ie&&(g(),z(),j()),ne&&(y(),b(),x(),S(),T(),A(),P(),F(),_())}}),r(le,[$],function(e){function t(t){return t._eventDispatcher||(t._eventDispatcher=new e({scope:t,toggleEvent:function(n,r){e.isNative(n)&&t.toggleNativeEvent&&t.toggleNativeEvent(n,r)}})),t._eventDispatcher}return{fire:function(e,n,r){var i=this;if(i.removed&&\"remove\"!==e)return n;if(n=t(i).fire(e,n,r),r!==!1&&i.parent)for(var o=i.parent();o&&!n.isPropagationStopped();)o.fire(e,n,!1),o=o.parent();return n},on:function(e,n,r){return t(this).on(e,n,r)},off:function(e,n){return t(this).off(e,n)},once:function(e,n){return t(this).once(e,n)},hasEventListeners:function(e){return t(this).has(e)}}}),r(ce,[le,y,d],function(e,t,n){function r(e,t){return\"selectionchange\"==t?e.getDoc():!e.inline&&/^mouse|click|contextmenu|drop|dragover|dragend/.test(t)?e.getDoc().documentElement:e.settings.event_root?(e.eventRoot||(e.eventRoot=o.select(e.settings.event_root)[0]),e.eventRoot):e.getBody()}function i(e,t){var n=r(e,t),i;if(e.delegates||(e.delegates={}),!e.delegates[t])if(e.settings.event_root){if(a||(a={},e.editorManager.on(\"removeEditor\",function(){var t;if(!e.editorManager.activeEditor&&a){for(t in a)e.dom.unbind(r(e,t));a=null}})),a[t])return;i=function(n){for(var r=n.target,i=e.editorManager.editors,a=i.length;a--;){var s=i[a].getBody();(s===r||o.isChildOf(r,s))&&(i[a].hidden||i[a].fire(t,n))}},a[t]=i,o.bind(n,t,i)}else i=function(n){e.hidden||e.fire(t,n)},o.bind(n,t,i),e.delegates[t]=i}var o=t.DOM,a,s={bindPendingEventDelegates:function(){var e=this;n.each(e._pendingNativeEvents,function(t){i(e,t)})},toggleNativeEvent:function(e,t){var n=this;n.settings.readonly||\"focus\"!=e&&\"blur\"!=e&&(t?n.initialized?i(n,e):n._pendingNativeEvents?n._pendingNativeEvents.push(e):n._pendingNativeEvents=[e]:n.initialized&&(n.dom.unbind(r(n,e),e,n.delegates[e]),delete n.delegates[e]))},unbindAllNativeEvents:function(){var e=this,t;if(e.delegates){for(t in e.delegates)e.dom.unbind(r(e,t),t,e.delegates[t]);delete e.delegates}e.inline||(e.getBody().onload=null,e.dom.unbind(e.getWin()),e.dom.unbind(e.getDoc())),e.dom.unbind(e.getBody()),e.dom.unbind(e.getContainer())}};return s=n.extend({},e,s)}),r(ue,[d,u],function(e,t){var n=e.each,r=e.explode,i={f9:120,f10:121,f11:122},o=e.makeMap(\"alt,ctrl,shift,meta,access\");return function(a){function s(e,s,l,c){var u,d,f;f={func:l,scope:c||a,desc:a.translate(s)},n(r(e,\"+\"),function(e){e in o?f[e]=!0:/^[0-9]{2,}$/.test(e)?f.keyCode=parseInt(e,10):(f.charCode=e.charCodeAt(0),f.keyCode=i[e]||e.toUpperCase().charCodeAt(0))}),u=[f.keyCode];for(d in o)f[d]?u.push(d):f[d]=!1;return f.id=u.join(\",\"),f.access&&(f.alt=!0,t.mac?f.ctrl=!0:f.shift=!0),f.meta&&(t.mac?f.meta=!0:(f.ctrl=!0,f.meta=!1)),f}var l=this,c={};a.on(\"keyup keypress keydown\",function(e){(e.altKey||e.ctrlKey||e.metaKey)&&!e.isDefaultPrevented()&&n(c,function(t){return t.ctrl==e.ctrlKey&&t.meta==e.metaKey&&t.alt==e.altKey&&t.shift==e.shiftKey&&(e.keyCode==t.keyCode||e.charCode&&e.charCode==t.charCode)?(e.preventDefault(),\"keydown\"==e.type&&t.func.call(t.scope),!0):void 0})}),l.add=function(t,i,o,l){var u;return u=o,\"string\"==typeof o?o=function(){a.execCommand(u,!1,null)}:e.isArray(u)&&(o=function(){a.execCommand(u[0],u[1],u[2])}),n(r(t.toLowerCase()),function(e){var t=s(e,i,o,l);c[t.id]=t}),!0},l.remove=function(e){var t=s(e);return c[t.id]?(delete c[t.id],!0):!1}}}),r(de,[y,f,C,w,_,R,T,H,O,I,F,z,W,V,b,l,ae,E,k,se,u,d,ce,ue],function(e,n,r,i,o,a,s,l,c,u,d,f,p,h,m,g,v,y,b,C,x,w,_,E){function N(e,t,i){var o=this,a,s;a=o.documentBaseUrl=i.documentBaseURL,s=i.baseURI,o.settings=t=R({id:e,theme:\"modern\",delta_width:0,delta_height:0,popup_css:\"\",plugins:\"\",document_base_url:a,add_form_submit_trigger:!0,submit_patch:!0,add_unload_trigger:!0,convert_urls:!0,relative_urls:!0,remove_script_host:!0,object_resizing:!0,doctype:\"\",visual:!0,font_size_style_values:\"xx-small,x-small,small,medium,large,x-large,xx-large\",font_size_legacy_values:\"xx-small,small,medium,large,x-large,xx-large,300%\",forced_root_block:\"p\",hidden_input:!0,padd_empty_editor:!0,render_ui:!0,indentation:\"30px\",inline_styles:!0,convert_fonts_to_spans:!0,indent:\"simple\",indent_before:\"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist\",indent_after:\"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist\",validate:!0,entity_encoding:\"named\",url_converter:o.convertURL,url_converter_scope:o,ie7_compat:!0},t),r.language=t.language||\"en\",r.languageLoad=t.language_load,r.baseURL=i.baseURL,o.id=t.id=e,o.isNotDirty=!0,o.plugins={},o.documentBaseURI=new h(t.document_base_url||a,{base_uri:s}),o.baseURI=s,o.contentCSS=[],o.contentStyles=[],o.shortcuts=new E(o),o.loadedCSS={},o.editorCommands=new p(o),t.target&&(o.targetElm=t.target),o.suffix=i.suffix,o.editorManager=i,o.inline=t.inline,t.cache_suffix&&(x.cacheSuffix=t.cache_suffix.replace(/^[\\?\\&]+/,\"\")),i.fire(\"SetupEditor\",o),o.execCallback(\"setup\",o),o.$=n.overrideDefaults(function(){return{context:o.inline?o.getBody():o.getDoc(),element:o.getBody()}})}var k=e.DOM,S=r.ThemeManager,T=r.PluginManager,R=w.extend,A=w.each,B=w.explode,D=w.inArray,M=w.trim,H=w.resolve,L=g.Event,P=x.gecko,O=x.ie;return N.prototype={render:function(){function e(){k.unbind(window,\"ready\",e),n.render()}function t(){var e=m.ScriptLoader;if(r.language&&\"en\"!=r.language&&!r.language_url&&(r.language_url=n.editorManager.baseURL+\"/langs/\"+r.language+\".js\"),r.language_url&&e.add(r.language_url),r.theme&&\"function\"!=typeof r.theme&&\"-\"!=r.theme.charAt(0)&&!S.urls[r.theme]){var t=r.theme_url;t=t?n.documentBaseURI.toAbsolute(t):\"themes/\"+r.theme+\"/theme\"+o+\".js\",S.load(r.theme,t)}w.isArray(r.plugins)&&(r.plugins=r.plugins.join(\" \")),A(r.external_plugins,function(e,t){T.load(t,e),r.plugins+=\" \"+t}),A(r.plugins.split(/[ ,]/),function(e){if(e=M(e),e&&!T.urls[e])if(\"-\"==e.charAt(0)){e=e.substr(1,e.length);var t=T.dependencies(e);A(t,function(e){var t={prefix:\"plugins/\",resource:e,suffix:\"/plugin\"+o+\".js\"};e=T.createUrl(t,e),T.load(e.resource,e)})}else T.load(e,{prefix:\"plugins/\",resource:e,suffix:\"/plugin\"+o+\".js\"})}),e.loadQueue(function(){n.removed||n.init()})}var n=this,r=n.settings,i=n.id,o=n.suffix;if(!L.domLoaded)return void k.bind(window,\"ready\",e);if(n.getElement()&&x.contentEditable){r.inline?n.inline=!0:(n.orgVisibility=n.getElement().style.visibility,n.getElement().style.visibility=\"hidden\");var a=n.getElement().form||k.getParent(i,\"form\");a&&(n.formElement=a,r.hidden_input&&!/TEXTAREA|INPUT/i.test(n.getElement().nodeName)&&(k.insertAfter(k.create(\"input\",{type:\"hidden\",name:i}),i),n.hasHiddenInput=!0),n.formEventDelegate=function(e){n.fire(e.type,e)},k.bind(a,\"submit reset\",n.formEventDelegate),n.on(\"reset\",function(){n.setContent(n.startContent,{format:\"raw\"})}),!r.submit_patch||a.submit.nodeType||a.submit.length||a._mceOldSubmit||(a._mceOldSubmit=a.submit,a.submit=function(){return n.editorManager.triggerSave(),n.isNotDirty=!0,a._mceOldSubmit(a)})),n.windowManager=new v(n),\"xml\"==r.encoding&&n.on(\"GetContent\",function(e){e.save&&(e.content=k.encode(e.content))}),r.add_form_submit_trigger&&n.on(\"submit\",function(){n.initialized&&n.save()}),r.add_unload_trigger&&(n._beforeUnload=function(){!n.initialized||n.destroyed||n.isHidden()||n.save({format:\"raw\",no_events:!0,set_dirty:!1})},n.editorManager.on(\"BeforeUnload\",n._beforeUnload)),t()}},init:function(){function e(n){var r=T.get(n),i,o;i=T.urls[n]||t.documentBaseUrl.replace(/\\/$/,\"\"),n=M(n),r&&-1===D(m,n)&&(A(T.dependencies(n),function(t){e(t)}),o=new r(t,i,t.$),t.plugins[n]=o,o.init&&(o.init(t,i),m.push(n)))}var t=this,n=t.settings,r=t.getElement(),i,o,a,s,l,c,u,d,f,p,h,m=[];if(this.editorManager.i18n.setCode(n.language),t.rtl=this.editorManager.i18n.rtl,t.editorManager.add(t),n.aria_label=n.aria_label||k.getAttrib(r,\"aria-label\",t.getLang(\"aria.rich_text_area\")),n.theme&&(\"function\"!=typeof n.theme?(n.theme=n.theme.replace(/-/,\"\"),c=S.get(n.theme),t.theme=new c(t,S.urls[n.theme]),t.theme.init&&t.theme.init(t,S.urls[n.theme]||t.documentBaseUrl.replace(/\\/$/,\"\"),t.$)):t.theme=n.theme),A(n.plugins.replace(/\\-/g,\"\").split(/[ ,]/),e),n.render_ui&&t.theme&&(t.orgDisplay=r.style.display,\"function\"!=typeof n.theme?(i=n.width||r.style.width||r.offsetWidth,o=n.height||r.style.height||r.offsetHeight,a=n.min_height||100,p=/^[0-9\\.]+(|px)$/i,p.test(\"\"+i)&&(i=Math.max(parseInt(i,10),100)),p.test(\"\"+o)&&(o=Math.max(parseInt(o,10),a)),l=t.theme.renderUI({targetNode:r,width:i,height:o,deltaWidth:n.delta_width,deltaHeight:n.delta_height}),n.content_editable||(o=(l.iframeHeight||o)+(\"number\"==typeof o?l.deltaHeight||0:\"\"),a>o&&(o=a))):(l=n.theme(t,r),l.editorContainer.nodeType&&(l.editorContainer=l.editorContainer.id=l.editorContainer.id||t.id+\"_parent\"),l.iframeContainer.nodeType&&(l.iframeContainer=l.iframeContainer.id=l.iframeContainer.id||t.id+\"_iframecontainer\"),o=l.iframeHeight||r.offsetHeight),t.editorContainer=l.editorContainer),n.content_css&&A(B(n.content_css),function(e){t.contentCSS.push(t.documentBaseURI.toAbsolute(e))}),n.content_style&&t.contentStyles.push(n.content_style),n.content_editable)return r=s=l=null,t.initContentBody();for(t.iframeHTML=n.doctype+\"\",n.document_base_url!=t.documentBaseUrl&&(t.iframeHTML+=''),!x.caretAfter&&n.ie7_compat&&(t.iframeHTML+=''),t.iframeHTML+='',h=0;h',t.loadedCSS[g]=!0}d=n.body_id||\"tinymce\",-1!=d.indexOf(\"=\")&&(d=t.getParam(\"body_id\",\"\",\"hash\"),d=d[t.id]||d),f=n.body_class||\"\",-1!=f.indexOf(\"=\")&&(f=t.getParam(\"body_class\",\"\",\"hash\"),f=f[t.id]||\"\"),n.content_security_policy&&(t.iframeHTML+=''),t.iframeHTML+='
';var v='javascript:(function(){document.open();document.domain=\"'+document.domain+'\";var ed = window.parent.tinymce.get(\"'+t.id+'\");document.write(ed.iframeHTML);document.close();ed.initContentBody(true);})()';document.domain!=location.hostname&&(u=v);var y=k.create(\"iframe\",{id:t.id+\"_ifr\",frameBorder:\"0\",allowTransparency:\"true\",title:t.editorManager.translate(\"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help\"),style:{width:\"100%\",height:o,display:\"block\"}});if(y.onload=function(){y.onload=null,t.fire(\"load\")},k.setAttrib(y,\"src\",u||'javascript:\"\"'),t.contentAreaContainer=l.iframeContainer,t.iframeElement=y,s=k.add(l.iframeContainer,y),O)try{t.getDoc()}catch(b){s.src=u=v}l.editorContainer&&(k.get(l.editorContainer).style.display=t.orgDisplay,t.hidden=k.isHidden(l.editorContainer)),t.getElement().style.display=\"none\",k.setAttrib(t.id,\"aria-hidden\",!0),u||t.initContentBody(),r=s=l=null},initContentBody:function(t){var n=this,r=n.settings,s=n.getElement(),p=n.getDoc(),h,m;r.inline||(n.getElement().style.visibility=n.orgVisibility),t||r.content_editable||(p.open(),p.write(n.iframeHTML),p.close()),r.content_editable&&(n.on(\"remove\",function(){var e=this.getBody();k.removeClass(e,\"mce-content-body\"),k.removeClass(e,\"mce-edit-focus\"),k.setAttrib(e,\"contentEditable\",null)}),k.addClass(s,\"mce-content-body\"),n.contentDocument=p=r.content_document||document,n.contentWindow=r.content_window||window,n.bodyElement=s,r.content_document=r.content_window=null,r.root_name=s.nodeName.toLowerCase()),h=n.getBody(),h.disabled=!0,r.readonly||(n.inline&&\"static\"==k.getStyle(h,\"position\",!0)&&(h.style.position=\"relative\"),h.contentEditable=n.getParam(\"content_editable_state\",!0)),h.disabled=!1,n.schema=new y(r),n.dom=new e(p,{keep_values:!0,url_converter:n.convertURL,url_converter_scope:n,hex_colors:r.force_hex_style_colors,class_filter:r.class_filter,update_styles:!0,root_element:n.inline?n.getBody():null,collect:r.content_editable,schema:n.schema,onSetAttrib:function(e){n.fire(\"SetAttrib\",e)}}),n.parser=new b(r,n.schema),n.parser.addAttributeFilter(\"src,href,style,tabindex\",function(e,t){for(var r=e.length,i,o=n.dom,a,s;r--;)i=e[r],a=i.attr(t),s=\"data-mce-\"+t,i.attributes.map[s]||(\"style\"===t?(a=o.serializeStyle(o.parseStyle(a),i.name),a.length||(a=null),i.attr(s,a),i.attr(t,a)):\"tabindex\"===t?(i.attr(s,a),i.attr(t,null)):i.attr(s,n.convertURL(a,t,i.name)))}),n.parser.addNodeFilter(\"script\",function(e){for(var t=e.length,n;t--;)n=e[t],n.attr(\"type\",\"mce-\"+(n.attr(\"type\")||\"no/type\"))}),n.parser.addNodeFilter(\"#cdata\",function(e){for(var t=e.length,n;t--;)n=e[t],n.type=8,n.name=\"#comment\",n.value=\"[CDATA[\"+n.value+\"]]\"}),n.parser.addNodeFilter(\"p,h1,h2,h3,h4,h5,h6,div\",function(e){for(var t=e.length,r,i=n.schema.getNonEmptyElements();t--;)r=e[t],r.isEmpty(i)&&(r.append(new o(\"br\",1)).shortEnded=!0)}),n.serializer=new a(r,n),n.selection=new l(n.dom,n.getWin(),n.serializer,n),n.formatter=new c(n),n.undoManager=new u(n),n.forceBlocks=new f(n),n.enterKey=new d(n),n._nodeChangeDispatcher=new i(n),n.fire(\"PreInit\"),r.browser_spellcheck||r.gecko_spellcheck||(p.body.spellcheck=!1,k.setAttrib(h,\"spellcheck\",\"false\")),n.fire(\"PostRender\"),n.quirks=new C(n),r.directionality&&(h.dir=r.directionality),r.nowrap&&(h.style.whiteSpace=\"nowrap\"),r.protect&&n.on(\"BeforeSetContent\",function(e){A(r.protect,function(t){e.content=e.content.replace(t,function(e){return\"\"})})}),n.on(\"SetContent\",function(){n.addVisual(n.getBody())}),r.padd_empty_editor&&n.on(\"PostProcess\",function(e){e.content=e.content.replace(/^(]*>( | |\\s|\\u00a0|)<\\/p>[\\r\\n]*|
[\\r\\n]*)$/,\"\")}),n.load({initial:!0,format:\"html\"}),n.startContent=n.getContent({format:\"raw\"}),n.initialized=!0,n.bindPendingEventDelegates(),n.fire(\"init\"),n.focus(!0),n.nodeChanged({initial:!0}),n.execCallback(\"init_instance_callback\",n),n.contentStyles.length>0&&(m=\"\",A(n.contentStyles,function(e){m+=e+\"\\r\\n\"}),n.dom.addStyle(m)),A(n.contentCSS,function(e){n.loadedCSS[e]||(n.dom.loadCSS(e),n.loadedCSS[e]=!0)}),r.auto_focus&&setTimeout(function(){var e;e=r.auto_focus===!0?n:n.editorManager.get(r.auto_focus),e.destroyed||e.focus()},100),s=p=h=null},focus:function(e){var t=this,n=t.selection,r=t.settings.content_editable,i,o,a=t.getDoc(),s;if(!e){if(i=n.getRng(),i.item&&(o=i.item(0)),t._refreshContentEditable(),r||(x.opera||t.getBody().focus(),t.getWin().focus()),P||r){if(s=t.getBody(),s.setActive)try{s.setActive()}catch(l){s.focus()}else s.focus();r&&n.normalize()}o&&o.ownerDocument==a&&(i=a.body.createControlRange(),i.addElement(o),i.select())}t.editorManager.setActive(t)},execCallback:function(e){var t=this,n=t.settings[e],r;if(n)return t.callbackLookup&&(r=t.callbackLookup[e])&&(n=r.func,r=r.scope),\"string\"==typeof n&&(r=n.replace(/\\.\\w+$/,\"\"),r=r?H(r):0,n=H(n),t.callbackLookup=t.callbackLookup||{},t.callbackLookup[e]={func:n,scope:r}),n.apply(r||t,Array.prototype.slice.call(arguments,1))},translate:function(e){var t=this.settings.language||\"en\",n=this.editorManager.i18n;return e?n.data[t+\".\"+e]||e.replace(/\\{\\#([^\\}]+)\\}/g,function(e,r){return n.data[t+\".\"+r]||\"{#\"+r+\"}\"}):\"\"},getLang:function(e,n){return this.editorManager.i18n.data[(this.settings.language||\"en\")+\".\"+e]||(n!==t?n:\"{#\"+e+\"}\")},getParam:function(e,t,n){var r=e in this.settings?this.settings[e]:t,i;return\"hash\"===n?(i={},\"string\"==typeof r?A(r.split(r.indexOf(\"=\")>0?/[;,](?![^=;,]*(?:[;,]|$))/:\",\"),function(e){e=e.split(\"=\"),e.length>1?i[M(e[0])]=M(e[1]):i[M(e[0])]=M(e)}):i=r,i):r},nodeChanged:function(e){this._nodeChangeDispatcher.nodeChanged(e);\n\n},addButton:function(e,t){var n=this;t.cmd&&(t.onclick=function(){n.execCommand(t.cmd)}),t.text||t.icon||(t.icon=e),n.buttons=n.buttons||{},t.tooltip=t.tooltip||t.title,n.buttons[e]=t},addMenuItem:function(e,t){var n=this;t.cmd&&(t.onclick=function(){n.execCommand(t.cmd)}),n.menuItems=n.menuItems||{},n.menuItems[e]=t},addCommand:function(e,t,n){this.editorCommands.addCommand(e,t,n)},addQueryStateHandler:function(e,t,n){this.editorCommands.addQueryStateHandler(e,t,n)},addQueryValueHandler:function(e,t,n){this.editorCommands.addQueryValueHandler(e,t,n)},addShortcut:function(e,t,n,r){this.shortcuts.add(e,t,n,r)},execCommand:function(e,t,n,r){return this.editorCommands.execCommand(e,t,n,r)},queryCommandState:function(e){return this.editorCommands.queryCommandState(e)},queryCommandValue:function(e){return this.editorCommands.queryCommandValue(e)},queryCommandSupported:function(e){return this.editorCommands.queryCommandSupported(e)},show:function(){var e=this;e.hidden&&(e.hidden=!1,e.inline?e.getBody().contentEditable=!0:(k.show(e.getContainer()),k.hide(e.id)),e.load(),e.fire(\"show\"))},hide:function(){var e=this,t=e.getDoc();e.hidden||(O&&t&&!e.inline&&t.execCommand(\"SelectAll\"),e.save(),e.inline?(e.getBody().contentEditable=!1,e==e.editorManager.focusedEditor&&(e.editorManager.focusedEditor=null)):(k.hide(e.getContainer()),k.setStyle(e.id,\"display\",e.orgDisplay)),e.hidden=!0,e.fire(\"hide\"))},isHidden:function(){return!!this.hidden},setProgressState:function(e,t){this.fire(\"ProgressState\",{state:e,time:t})},load:function(e){var n=this,r=n.getElement(),i;return r?(e=e||{},e.load=!0,i=n.setContent(r.value!==t?r.value:r.innerHTML,e),e.element=r,e.no_events||n.fire(\"LoadContent\",e),e.element=r=null,i):void 0},save:function(e){var t=this,n=t.getElement(),r,i;if(n&&t.initialized)return e=e||{},e.save=!0,e.element=n,r=e.content=t.getContent(e),e.no_events||t.fire(\"SaveContent\",e),r=e.content,/TEXTAREA|INPUT/i.test(n.nodeName)?n.value=r:(t.inline||(n.innerHTML=r),(i=k.getParent(t.id,\"form\"))&&A(i.elements,function(e){return e.name==t.id?(e.value=r,!1):void 0})),e.element=n=null,e.set_dirty!==!1&&(t.isNotDirty=!0),r},setContent:function(e,t){var n=this,r=n.getBody(),i;return t=t||{},t.format=t.format||\"html\",t.set=!0,t.content=e,t.no_events||n.fire(\"BeforeSetContent\",t),e=t.content,0===e.length||/^\\s+$/.test(e)?(i=n.settings.forced_root_block,i&&n.schema.isValidChild(r.nodeName.toLowerCase(),i.toLowerCase())?(e=O&&11>O?\"\":'
',e=n.dom.createHTML(i,n.settings.forced_root_block_attrs,e)):O||(e='
'),n.dom.setHTML(r,e),n.fire(\"SetContent\",t)):(\"raw\"!==t.format&&(e=new s({},n.schema).serialize(n.parser.parse(e,{isRootContent:!0}))),t.content=M(e),n.dom.setHTML(r,t.content),t.no_events||n.fire(\"SetContent\",t)),t.content},getContent:function(e){var t=this,n,r=t.getBody();return e=e||{},e.format=e.format||\"html\",e.get=!0,e.getInner=!0,e.no_events||t.fire(\"BeforeGetContent\",e),n=\"raw\"==e.format?r.innerHTML:\"text\"==e.format?r.innerText||r.textContent:t.serializer.serialize(r,e),\"text\"!=e.format?e.content=M(n):e.content=n,e.no_events||t.fire(\"GetContent\",e),e.content},insertContent:function(e,t){t&&(e=R({content:e},t)),this.execCommand(\"mceInsertContent\",!1,e)},isDirty:function(){return!this.isNotDirty},getContainer:function(){var e=this;return e.container||(e.container=k.get(e.editorContainer||e.id+\"_parent\")),e.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return this.targetElm||(this.targetElm=k.get(this.id)),this.targetElm},getWin:function(){var e=this,t;return e.contentWindow||(t=e.iframeElement,t&&(e.contentWindow=t.contentWindow)),e.contentWindow},getDoc:function(){var e=this,t;return e.contentDocument||(t=e.getWin(),t&&(e.contentDocument=t.document)),e.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(e,t,n){var r=this,i=r.settings;return i.urlconverter_callback?r.execCallback(\"urlconverter_callback\",e,n,!0,t):!i.convert_urls||n&&\"LINK\"==n.nodeName||0===e.indexOf(\"file:\")||0===e.length?e:i.relative_urls?r.documentBaseURI.toRelative(e):e=r.documentBaseURI.toAbsolute(e,i.remove_script_host)},addVisual:function(e){var n=this,r=n.settings,i=n.dom,o;e=e||n.getBody(),n.hasVisual===t&&(n.hasVisual=r.visual),A(i.select(\"table,a\",e),function(e){var t;switch(e.nodeName){case\"TABLE\":return o=r.visual_table_class||\"mce-item-table\",t=i.getAttrib(e,\"border\"),void(t&&\"0\"!=t||!n.hasVisual?i.removeClass(e,o):i.addClass(e,o));case\"A\":return void(i.getAttrib(e,\"href\",!1)||(t=i.getAttrib(e,\"name\")||e.id,o=r.visual_anchor_class||\"mce-item-anchor\",t&&n.hasVisual?i.addClass(e,o):i.removeClass(e,o)))}}),n.fire(\"VisualAid\",{element:e,hasVisual:n.hasVisual})},remove:function(){var e=this;e.removed||(e.save(),e.removed=1,e.unbindAllNativeEvents(),e.hasHiddenInput&&k.remove(e.getElement().nextSibling),e.inline||(O&&10>O&&e.getDoc().execCommand(\"SelectAll\",!1,null),k.setStyle(e.id,\"display\",e.orgDisplay),e.getBody().onload=null),e.fire(\"remove\"),e.editorManager.remove(e),k.remove(e.getContainer()),e.destroy())},destroy:function(e){var t=this,n;if(!t.destroyed){if(!e&&!t.removed)return void t.remove();e||(t.editorManager.off(\"beforeunload\",t._beforeUnload),t.theme&&t.theme.destroy&&t.theme.destroy(),t.selection.destroy(),t.dom.destroy()),n=t.formElement,n&&(n._mceOldSubmit&&(n.submit=n._mceOldSubmit,n._mceOldSubmit=null),k.unbind(n,\"submit reset\",t.formEventDelegate)),t.contentAreaContainer=t.formElement=t.container=t.editorContainer=null,t.bodyElement=t.contentDocument=t.contentWindow=null,t.iframeElement=t.targetElm=null,t.selection&&(t.selection=t.selection.win=t.selection.dom=t.selection.dom.doc=null),t.destroyed=1}},_refreshContentEditable:function(){var e=this,t,n;e._isHidden()&&(t=e.getBody(),n=t.parentNode,n.removeChild(t),n.appendChild(t),t.focus())},_isHidden:function(){var e;return P?(e=this.selection.getSel(),!e||!e.rangeCount||0===e.rangeCount):0}},R(N.prototype,_),N}),r(fe,[],function(){var e={},t=\"en\";return{setCode:function(e){e&&(t=e,this.rtl=this.data[e]?\"rtl\"===this.data[e]._dir:!1)},getCode:function(){return t},rtl:!1,add:function(t,n){var r=e[t];r||(e[t]=r={});for(var i in n)r[i]=n[i];this.setCode(t)},translate:function(n){var r;if(r=e[t],r||(r={}),\"undefined\"==typeof n)return n;if(\"string\"!=typeof n&&n.raw)return n.raw;if(n.push){var i=n.slice(1);n=(r[n[0]]||n[0]).replace(/\\{([0-9]+)\\}/g,function(e,t){return i[t]})}return(r[n]||n).replace(/{context:\\w+}$/,\"\")},data:e}}),r(pe,[y,u],function(e,t){function n(e){function s(){try{return document.activeElement}catch(e){return document.body}}function l(e,t){if(t&&t.startContainer){if(!e.isChildOf(t.startContainer,e.getRoot())||!e.isChildOf(t.endContainer,e.getRoot()))return;return{startContainer:t.startContainer,startOffset:t.startOffset,endContainer:t.endContainer,endOffset:t.endOffset}}return t}function c(e,t){var n;return t.startContainer?(n=e.getDoc().createRange(),n.setStart(t.startContainer,t.startOffset),n.setEnd(t.endContainer,t.endOffset)):n=t,n}function u(e){return!!a.getParent(e,n.isEditorUIElement)}function d(n){var d=n.editor;d.on(\"init\",function(){(d.inline||t.ie)&&(\"onbeforedeactivate\"in document&&t.ie<9?d.dom.bind(d.getBody(),\"beforedeactivate\",function(e){if(e.target==d.getBody())try{d.lastRng=d.selection.getRng()}catch(t){}}):d.on(\"nodechange mouseup keyup\",function(e){var t=s();\"nodechange\"==e.type&&e.selectionChange||(t&&t.id==d.id+\"_ifr\"&&(t=d.getBody()),d.dom.isChildOf(t,d.getBody())&&(d.lastRng=d.selection.getRng()))}),t.webkit&&!r&&(r=function(){var t=e.activeEditor;if(t&&t.selection){var n=t.selection.getRng();n&&!n.collapsed&&(d.lastRng=n)}},a.bind(document,\"selectionchange\",r)))}),d.on(\"setcontent\",function(){d.lastRng=null}),d.on(\"mousedown\",function(){d.selection.lastFocusBookmark=null}),d.on(\"focusin\",function(){var t=e.focusedEditor;d.selection.lastFocusBookmark&&(d.selection.setRng(c(d,d.selection.lastFocusBookmark)),d.selection.lastFocusBookmark=null),t!=d&&(t&&t.fire(\"blur\",{focusedEditor:d}),e.setActive(d),e.focusedEditor=d,d.fire(\"focus\",{blurredEditor:t}),d.focus(!0)),d.lastRng=null}),d.on(\"focusout\",function(){window.setTimeout(function(){var t=e.focusedEditor;u(s())||t!=d||(d.fire(\"blur\",{focusedEditor:null}),e.focusedEditor=null,d.selection&&(d.selection.lastFocusBookmark=null))},0)}),i||(i=function(t){var n=e.activeEditor;n&&t.target.ownerDocument==document&&(n.selection&&t.target!=n.getBody()&&(n.selection.lastFocusBookmark=l(n.dom,n.lastRng)),t.target==document.body||u(t.target)||e.focusedEditor!=n||(n.fire(\"blur\",{focusedEditor:null}),e.focusedEditor=null))},a.bind(document,\"focusin\",i)),d.inline&&!o&&(o=function(t){var n=e.activeEditor;if(n.inline&&!n.dom.isChildOf(t.target,n.getBody())){var r=n.selection.getRng();r.collapsed||(n.lastRng=r)}},a.bind(document,\"mouseup\",o))}function f(t){e.focusedEditor==t.editor&&(e.focusedEditor=null),e.activeEditor||(a.unbind(document,\"selectionchange\",r),a.unbind(document,\"focusin\",i),a.unbind(document,\"mouseup\",o),r=i=o=null)}e.on(\"AddEditor\",d),e.on(\"RemoveEditor\",f)}var r,i,o,a=e.DOM;return n.isEditorUIElement=function(e){return-1!==e.className.toString().indexOf(\"mce-\")},n}),r(he,[de,f,y,V,u,d,le,fe,pe],function(e,t,n,r,i,o,a,s,l){function c(e){var t=v.editors,n;delete t[e.id];for(var r=0;r0&&p(f(e),function(e){var n;(n=d.get(e))?r(e,t,n):p(document.forms,function(n){p(n.elements,function(n){n.name===e&&(e=\"mce_editor_\"+m++,d.setAttrib(n,\"id\",e),r(e,t,n))})})});break;case\"textareas\":case\"specific_textareas\":p(d.select(\"textarea\"),function(e){t.editor_deselector&&o(e,t.editor_deselector)||(!t.editor_selector||o(e,t.editor_selector))&&r(n(e),t,e)})}t.oninit&&(e=s=0,p(l,function(t){s++,t.initialized?e++:t.on(\"init\",function(){e++,e==s&&i(\"oninit\")}),e==s&&i(\"oninit\")}))}var s=this,l=[];s.settings=t,d.bind(window,\"ready\",a)},get:function(e){return arguments.length?e in this.editors?this.editors[e]:null:this.editors},add:function(e){var t=this,n=t.editors;return n[e.id]=e,n.push(e),t.activeEditor=e,t.fire(\"AddEditor\",{editor:e}),g||(g=function(){t.fire(\"BeforeUnload\")},d.bind(window,\"beforeunload\",g)),e},createEditor:function(t,n){return this.add(new e(t,n,this))},remove:function(e){var t=this,n,r=t.editors,i;{if(e)return\"string\"==typeof e?(e=e.selector||e,void p(d.select(e),function(e){i=r[e.id],i&&t.remove(i)})):(i=e,r[i.id]?(c(i)&&t.fire(\"RemoveEditor\",{editor:i}),r.length||d.unbind(window,\"beforeunload\",g),i.remove(),i):null);for(n=r.length-1;n>=0;n--)t.remove(r[n])}},execCommand:function(t,n,r){var i=this,o=i.get(r);switch(t){case\"mceAddEditor\":return i.get(r)||new e(r,i.settings,i).render(),!0;case\"mceRemoveEditor\":return o&&o.remove(),!0;case\"mceToggleEditor\":return o?(o.isHidden()?o.show():o.hide(),!0):(i.execCommand(\"mceAddEditor\",0,r),!0)}return i.activeEditor?i.activeEditor.execCommand(t,n,r):!1},triggerSave:function(){p(this.editors,function(e){e.save()})},addI18n:function(e,t){s.add(e,t)},translate:function(e){return s.translate(e)},setActive:function(e){var t=this.activeEditor;this.activeEditor!=e&&(t&&t.fire(\"deactivate\",{relatedTarget:e}),e.fire(\"activate\",{relatedTarget:t})),this.activeEditor=e}},h(v,a),v.setup(),window.tinymce=window.tinyMCE=v,v}),r(me,[he,d],function(e,t){var n=t.each,r=t.explode;e.on(\"AddEditor\",function(e){var t=e.editor;t.on(\"preInit\",function(){function e(e,t){n(t,function(t,n){t&&s.setStyle(e,n,t)}),s.rename(e,\"span\")}function i(e){s=t.dom,l.convert_fonts_to_spans&&n(s.select(\"font,u,strike\",e.node),function(e){o[e.nodeName.toLowerCase()](s,e)})}var o,a,s,l=t.settings;l.inline_styles&&(a=r(l.font_size_legacy_values),o={font:function(t,n){e(n,{backgroundColor:n.style.backgroundColor,color:n.color,fontFamily:n.face,fontSize:a[parseInt(n.size,10)-1]})},u:function(n,r){\"html4\"===t.settings.schema&&e(r,{textDecoration:\"underline\"})},strike:function(t,n){e(n,{textDecoration:\"line-through\"})}},t.on(\"PreProcess SetContent\",i))})})}),r(ge,[le,d],function(e,t){var n={send:function(e){function t(){!e.async||4==r.readyState||i++>1e4?(e.success&&1e4>i&&200==r.status?e.success.call(e.success_scope,\"\"+r.responseText,r,e):e.error&&e.error.call(e.error_scope,i>1e4?\"TIMED_OUT\":\"GENERAL\",r,e),r=null):setTimeout(t,10)}var r,i=0;if(e.scope=e.scope||this,e.success_scope=e.success_scope||e.scope,e.error_scope=e.error_scope||e.scope,e.async=e.async===!1?!1:!0,e.data=e.data||\"\",r=new XMLHttpRequest){if(r.overrideMimeType&&r.overrideMimeType(e.content_type),r.open(e.type||(e.data?\"POST\":\"GET\"),e.url,e.async),e.crossDomain&&(r.withCredentials=!0),e.content_type&&r.setRequestHeader(\"Content-Type\",e.content_type),r.setRequestHeader(\"X-Requested-With\",\"XMLHttpRequest\"),r=n.fire(\"beforeSend\",{xhr:r,settings:e}).xhr,r.send(e.data),!e.async)return t();setTimeout(t,10)}}};return t.extend(n,e),n}),r(ve,[],function(){function e(t,n){var r,i,o,a;if(n=n||'\"',null===t)return\"null\";if(o=typeof t,\"string\"==o)return i=\"\\bb\tt\\nn\\ff\\rr\\\"\\\"''\\\\\\\\\",n+t.replace(/([\\u0080-\\uFFFF\\x00-\\x1f\\\"\\'\\\\])/g,function(e,t){return'\"'===n&&\"'\"===e?e:(r=i.indexOf(t),r+1?\"\\\\\"+i.charAt(r+1):(e=t.charCodeAt().toString(16),\"\\\\u\"+\"0000\".substring(e.length)+e))})+n;if(\"object\"==o){if(t.hasOwnProperty&&\"[object Array]\"===Object.prototype.toString.call(t)){for(r=0,i=\"[\";r0?\",\":\"\")+e(t[r],n);return i+\"]\"}i=\"{\";for(a in t)t.hasOwnProperty(a)&&(i+=\"function\"!=typeof t[a]?(i.length>1?\",\"+n:n)+a+n+\":\"+e(t[a],n):\"\");return i+\"}\"}return\"\"+t}return{serialize:e,parse:function(e){try{return window[String.fromCharCode(101)+\"val\"](\"(\"+e+\")\")}catch(t){}}}}),r(ye,[ve,ge,d],function(e,t,n){function r(e){this.settings=i({},e),this.count=0}var i=n.extend;return r.sendRPC=function(e){return(new r).send(e)},r.prototype={send:function(n){var r=n.error,o=n.success;n=i(this.settings,n),n.success=function(t,i){t=e.parse(t),\"undefined\"==typeof t&&(t={error:\"JSON Parse error.\"}),t.error?r.call(n.error_scope||n.scope,t.error,i):o.call(n.success_scope||n.scope,t.result)},n.error=function(e,t){r&&r.call(n.error_scope||n.scope,e,t)},n.data=e.serialize({id:n.id||\"c\"+this.count++,method:n.method,params:n.params}),n.content_type=\"application/json\",t.send(n)}},r}),r(be,[y],function(e){return{callbacks:{},count:0,send:function(n){var r=this,i=e.DOM,o=n.count!==t?n.count:r.count,a=\"tinymce_jsonp_\"+o;r.callbacks[o]=function(e){i.remove(a),delete r.callbacks[o],n.callback(e)},i.add(i.doc.body,\"script\",{id:a,src:n.url,type:\"text/javascript\"}),r.count++}}}),r(Ce,[],function(){function e(){s=[];for(var e in a)s.push(e);i.length=s.length}function n(){function n(e){var n,r;return r=e!==t?u+e:i.indexOf(\",\",u),-1===r||r>i.length?null:(n=i.substring(u,r),u=r+1,n)}var r,i,s,u=0;if(a={},c){o.load(l),i=o.getAttribute(l)||\"\";do{var d=n();if(null===d)break;if(r=n(parseInt(d,32)||0),null!==r){if(d=n(),null===d)break;s=n(parseInt(d,32)||0),r&&(a[r]=s)}}while(null!==r);e()}}function r(){var t,n=\"\";if(c){for(var r in a)t=a[r],n+=(n?\",\":\"\")+r.length.toString(32)+\",\"+r+\",\"+t.length.toString(32)+\",\"+t;o.setAttribute(l,n);try{o.save(l)}catch(i){}e()}}var i,o,a,s,l,c;try{if(window.localStorage)return localStorage}catch(u){}return l=\"tinymce\",o=document.documentElement,c=!!o.addBehavior,c&&o.addBehavior(\"#default#userData\"),i={key:function(e){return s[e]},getItem:function(e){return e in a?a[e]:null},setItem:function(e,t){a[e]=\"\"+t,r()},removeItem:function(e){delete a[e],r()},clear:function(){a={},r()}},n(),i}),r(xe,[y,l,b,C,d,u],function(e,t,n,r,i,o){var a=window.tinymce;return a.DOM=e.DOM,a.ScriptLoader=n.ScriptLoader,a.PluginManager=r.PluginManager,a.ThemeManager=r.ThemeManager,a.dom=a.dom||{},a.dom.Event=t.Event,i.each(i,function(e,t){a[t]=e}),i.each(\"isOpera isWebKit isIE isGecko isMac\".split(\" \"),function(e){a[e]=o[e.substr(2).toLowerCase()]}),{}}),r(we,[U,d],function(e,t){return e.extend({Defaults:{firstControlClass:\"first\",lastControlClass:\"last\"},init:function(e){this.settings=t.extend({},this.Defaults,e)},preRender:function(e){e.addClass(this.settings.containerClass,\"body\")},applyClasses:function(e){var t=this,n=t.settings,r,i,o;r=e.items().filter(\":visible\"),i=n.firstControlClass,o=n.lastControlClass,r.each(function(e){e.removeClass(i).removeClass(o),n.controlClass&&e.addClass(n.controlClass)}),r.eq(0).addClass(i),r.eq(-1).addClass(o)},renderHtml:function(e){var t=this,n=t.settings,r,i=\"\";return r=e.items(),r.eq(0).addClass(n.firstControlClass),r.eq(-1).addClass(n.lastControlClass),r.each(function(e){n.controlClass&&e.addClass(n.controlClass),i+=e.renderHtml()}),i},recalc:function(){},postRender:function(){}})}),r(_e,[we],function(e){return e.extend({Defaults:{containerClass:\"abs-layout\",controlClass:\"abs-layout-item\"},recalc:function(e){e.items().filter(\":visible\").each(function(e){var t=e.settings;e.layoutRect({x:t.x,y:t.y,w:t.w,h:t.h}),e.recalc&&e.recalc()})},renderHtml:function(e){return'
'+this._super(e)}})}),r(Ee,[Y,te],function(e,t){return e.extend({Mixins:[t],Defaults:{classes:\"widget tooltip tooltip-n\"},text:function(e){var t=this;return\"undefined\"!=typeof e?(t._value=e,t._rendered&&(t.getEl().lastChild.innerHTML=t.encode(e)),t):t._value},renderHtml:function(){var e=this,t=e.classPrefix;return'
'+e.encode(e._text)+\"
\"},repaint:function(){var e=this,t,n;t=e.getEl().style,n=e._layoutRect,t.left=n.x+\"px\",t.top=n.y+\"px\",t.zIndex=131070}})}),r(Ne,[Y,Ee],function(e,t){var n,r=e.extend({init:function(e){var t=this;t._super(e),e=t.settings,t.canFocus=!0,e.tooltip&&r.tooltips!==!1&&(t.on(\"mouseenter\",function(n){var r=t.tooltip().moveTo(-65535);if(n.control==t){var i=r.text(e.tooltip).show().testMoveRel(t.getEl(),[\"bc-tc\",\"bc-tl\",\"bc-tr\"]);r.toggleClass(\"tooltip-n\",\"bc-tc\"==i),r.toggleClass(\"tooltip-nw\",\"bc-tl\"==i),r.toggleClass(\"tooltip-ne\",\"bc-tr\"==i),r.moveRel(t.getEl(),i)}else r.hide()}),t.on(\"mouseleave mousedown click\",function(){t.tooltip().hide()})),t.aria(\"label\",e.ariaLabel||e.tooltip)},tooltip:function(){return n||(n=new t({type:\"tooltip\"}),n.renderTo()),n},active:function(e){var t=this,n;return e!==n&&(t.aria(\"pressed\",e),t.toggleClass(\"active\",e)),t._super(e)},disabled:function(e){var t=this,n;return e!==n&&(t.aria(\"disabled\",e),t.toggleClass(\"disabled\",e)),t._super(e)},postRender:function(){var e=this,t=e.settings;e._rendered=!0,e._super(),e.parent()||!t.width&&!t.height||(e.initLayoutRect(),e.repaint()),t.autofocus&&e.focus()},remove:function(){this._super(),n&&(n.remove(),n=null)}});return r}),r(ke,[Ne],function(e){return e.extend({Defaults:{classes:\"widget btn\",role:\"button\"},init:function(e){var t=this,n;t.on(\"click mousedown\",function(e){e.preventDefault()}),t._super(e),n=e.size,e.subtype&&t.addClass(e.subtype),n&&t.addClass(\"btn-\"+n)},icon:function(e){var t=this,n=t.classPrefix;if(\"undefined\"==typeof e)return t.settings.icon;if(t.settings.icon=e,e=e?n+\"ico \"+n+\"i-\"+t.settings.icon:\"\",t._rendered){var r=t.getEl().firstChild,i=r.getElementsByTagName(\"i\")[0];e?(i&&i==r.firstChild||(i=document.createElement(\"i\"),r.insertBefore(i,r.firstChild)),i.className=e):i&&r.removeChild(i),t.text(t._text)}return t},repaint:function(){var e=this.getEl().firstChild.style;e.width=e.height=\"100%\",this._super()},text:function(e){var t=this;if(t._rendered){var n=t.getEl().lastChild.lastChild;n&&(n.data=t.translate(e))}return t._super(e)},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.settings.icon,i;return i=e.settings.image,i?(r=\"none\",\"string\"!=typeof i&&(i=window.getSelection?i[0]:i[1]),i=\" style=\\\"background-image: url('\"+i+\"')\\\"\"):i=\"\",r=e.settings.icon?n+\"ico \"+n+\"i-\"+r:\"\",'
\"}})}),r(Se,[J],function(e){return e.extend({Defaults:{defaultType:\"button\",role:\"group\"},renderHtml:function(){var e=this,t=e._layout;return e.addClass(\"btn-group\"),e.preRender(),t.preRender(e),'
'+(e.settings.html||\"\")+t.renderHtml(e)+\"
\"}})}),r(Te,[Ne],function(e){return e.extend({Defaults:{classes:\"checkbox\",role:\"checkbox\",checked:!1},init:function(e){var t=this;t._super(e),t.on(\"click mousedown\",function(e){e.preventDefault()}),t.on(\"click\",function(e){e.preventDefault(),t.disabled()||t.checked(!t.checked())}),t.checked(t.settings.checked)},checked:function(e){var t=this;return\"undefined\"!=typeof e?(e?t.addClass(\"checked\"):t.removeClass(\"checked\"),t._checked=e,t.aria(\"checked\",e),t):t._checked},value:function(e){return this.checked(e)},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix;return'
'+e.encode(e._text)+\"
\"}})}),r(Re,[Ne,G,K],function(e,t,n){return e.extend({init:function(e){var t=this;t._super(e),t.addClass(\"combobox\"),t.subinput=!0,t.ariaTarget=\"inp\",e=t.settings,e.menu=e.menu||e.values,e.menu&&(e.icon=\"caret\"),t.on(\"click\",function(n){for(var r=n.target,i=t.getEl();r&&r!=i;)r.id&&-1!=r.id.indexOf(\"-open\")&&(t.fire(\"action\"),e.menu&&(t.showMenu(),n.aria&&t.menu.items()[0].focus())),r=r.parentNode}),t.on(\"keydown\",function(e){\"INPUT\"==e.target.nodeName&&13==e.keyCode&&t.parents().reverse().each(function(n){return e.preventDefault(),t.fire(\"change\"),n.hasEventListeners(\"submit\")&&n.toJSON?(n.fire(\"submit\",{data:n.toJSON()}),!1):void 0})}),e.placeholder&&(t.addClass(\"placeholder\"),t.on(\"focusin\",function(){t._hasOnChange||(n.on(t.getEl(\"inp\"),\"change\",function(){t.fire(\"change\")}),t._hasOnChange=!0),t.hasClass(\"placeholder\")&&(t.getEl(\"inp\").value=\"\",t.removeClass(\"placeholder\"))}),t.on(\"focusout\",function(){0===t.value().length&&(t.getEl(\"inp\").value=e.placeholder,t.addClass(\"placeholder\"))}))},showMenu:function(){var e=this,n=e.settings,r;e.menu||(r=n.menu||[],r.length?r={type:\"menu\",items:r}:r.type=r.type||\"menu\",e.menu=t.create(r).parent(e).renderTo(e.getContainerElm()),e.fire(\"createmenu\"),e.menu.reflow(),e.menu.on(\"cancel\",function(t){t.control===e.menu&&e.focus()}),e.menu.on(\"show hide\",function(t){t.control.items().each(function(t){t.active(t.value()==e.value())})}).fire(\"show\"),e.menu.on(\"select\",function(t){e.value(t.control.value())}),e.on(\"focusin\",function(t){\"INPUT\"==t.target.tagName.toUpperCase()&&e.menu.hide()}),e.aria(\"expanded\",!0)),e.menu.show(),e.menu.layoutRect({w:e.layoutRect().w}),e.menu.moveRel(e.getEl(),e.isRtl()?[\"br-tr\",\"tr-br\"]:[\"bl-tl\",\"tl-bl\"])},value:function(e){var t=this;return\"undefined\"!=typeof e?(t._value=e,t.removeClass(\"placeholder\"),t._rendered&&(t.getEl(\"inp\").value=e),t):t._rendered?(e=t.getEl(\"inp\").value,e!=t.settings.placeholder?e:\"\"):t._value},disabled:function(e){var t=this;return t._rendered&&\"undefined\"!=typeof e&&(t.getEl(\"inp\").disabled=e),t._super(e)},focus:function(){this.getEl(\"inp\").focus()},repaint:function(){var e=this,t=e.getEl(),r=e.getEl(\"open\"),i=e.layoutRect(),o,a;o=r?i.w-n.getSize(r).width-10:i.w-10;var s=document;return s.all&&(!s.documentMode||s.documentMode<=8)&&(a=e.layoutRect().h-2+\"px\"),n.css(t.firstChild,{width:o,lineHeight:a}),e._super(),e},postRender:function(){var e=this;return n.on(this.getEl(\"inp\"),\"change\",function(){e.fire(\"change\")}),e._super()},remove:function(){n.off(this.getEl(\"inp\")),this._super()},renderHtml:function(){var e=this,t=e._id,n=e.settings,r=e.classPrefix,i=n.value||n.placeholder||\"\",o,a,s=\"\",l=\"\";return\"spellcheck\"in n&&(l+=' spellcheck=\"'+n.spellcheck+'\"'),n.maxLength&&(l+=' maxlength=\"'+n.maxLength+'\"'),n.size&&(l+=' size=\"'+n.size+'\"'),n.subtype&&(l+=' type=\"'+n.subtype+'\"'),e.disabled()&&(l+=' disabled=\"disabled\"'),o=n.icon,o&&\"caret\"!=o&&(o=r+\"ico \"+r+\"i-\"+n.icon),a=e._text,(o||a)&&(s='
\",e.addClass(\"has-open\")),'
\"+s+\"
\"}})}),r(Ae,[Re],function(e){return e.extend({init:function(e){var t=this;e.spellcheck=!1,e.onaction&&(e.icon=\"none\"),t._super(e),t.addClass(\"colorbox\"),t.on(\"change keyup postrender\",function(){t.repaintColor(t.value())})},repaintColor:function(e){var t=this.getEl().getElementsByTagName(\"i\")[0];if(t)try{t.style.background=e}catch(n){}},value:function(e){var t=this;return\"undefined\"!=typeof e&&t._rendered&&t.repaintColor(e),t._super(e)}})}),r(Be,[ke,re],function(e,t){return e.extend({showPanel:function(){var e=this,n=e.settings;if(e.active(!0),e.panel)e.panel.show();else{var r=n.panel;r.type&&(r={layout:\"grid\",items:r}),r.role=r.role||\"dialog\",r.popover=!0,r.autohide=!0,r.ariaRoot=!0,e.panel=new t(r).on(\"hide\",function(){e.active(!1)}).on(\"cancel\",function(t){t.stopPropagation(),e.focus(),e.hidePanel()}).parent(e).renderTo(e.getContainerElm()),e.panel.fire(\"show\"),e.panel.reflow()}e.panel.moveRel(e.getEl(),n.popoverAlign||(e.isRtl()?[\"bc-tr\",\"bc-tc\"]:[\"bc-tl\",\"bc-tc\"]))},hidePanel:function(){var e=this;e.panel&&e.panel.hide()},postRender:function(){var e=this;return e.aria(\"haspopup\",!0),e.on(\"click\",function(t){t.control===e&&(e.panel&&e.panel.visible()?e.hidePanel():(e.showPanel(),e.panel.focus(!!t.aria)))}),e._super()},remove:function(){return this.panel&&(this.panel.remove(),this.panel=null),this._super()}})}),r(De,[Be,y],function(e,t){var n=t.DOM;return e.extend({init:function(e){this._super(e),this.addClass(\"colorbutton\")},color:function(e){return e?(this._color=e,this.getEl(\"preview\").style.backgroundColor=e,this):this._color},resetColor:function(){return this._color=null,this.getEl(\"preview\").style.backgroundColor=null,this},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r=e.settings.icon?n+\"ico \"+n+\"i-\"+e.settings.icon:\"\",i=e.settings.image?\" style=\\\"background-image: url('\"+e.settings.image+\"')\\\"\":\"\";return'
'},postRender:function(){var e=this,t=e.settings.onclick;return e.on(\"click\",function(r){r.aria&&\"down\"==r.aria.key||r.control!=e||n.getParent(r.target,\".\"+e.classPrefix+\"open\")||(r.stopImmediatePropagation(),t.call(e,r))}),delete e.settings.onclick,e._super()}})}),r(Me,[],function(){function e(e){function i(e,i,o){var a,s,l,c,u,d;return a=0,s=0,l=0,e/=255,i/=255,o/=255,u=t(e,t(i,o)),d=n(e,n(i,o)),u==d?(l=u,{h:0,s:0,v:100*l}):(c=e==u?i-o:o==u?e-i:o-e,a=e==u?3:o==u?1:5,a=60*(a-c/(d-u)),s=(d-u)/d,l=d,{h:r(a),s:r(100*s),v:r(100*l)})}function o(e,i,o){var a,s,l,c;if(e=(parseInt(e,10)||0)%360,i=parseInt(i,10)/100,o=parseInt(o,10)/100,i=n(0,t(i,1)),o=n(0,t(o,1)),0===i)return void(d=f=p=r(255*o));switch(a=e/60,s=o*i,l=s*(1-Math.abs(a%2-1)),c=o-s,Math.floor(a)){case 0:d=s,f=l,p=0;break;case 1:d=l,f=s,p=0;break;case 2:d=0,f=s,p=l;break;case 3:d=0,f=l,p=s;break;case 4:d=l,f=0,p=s;break;case 5:d=s,f=0,p=l;break;default:d=f=p=0}d=r(255*(d+c)),f=r(255*(f+c)),p=r(255*(p+c))}function a(){function e(e){return e=parseInt(e,10).toString(16),e.length>1?e:\"0\"+e}return\"#\"+e(d)+e(f)+e(p)}function s(){return{r:d,g:f,b:p}}function l(){return i(d,f,p)}function c(e){var t;return\"object\"==typeof e?\"r\"in e?(d=e.r,f=e.g,p=e.b):\"v\"in e&&o(e.h,e.s,e.v):(t=/rgb\\s*\\(\\s*([0-9]+)\\s*,\\s*([0-9]+)\\s*,\\s*([0-9]+)[^\\)]*\\)/gi.exec(e))?(d=parseInt(t[1],10),f=parseInt(t[2],10),p=parseInt(t[3],10)):(t=/#([0-F]{2})([0-F]{2})([0-F]{2})/gi.exec(e))?(d=parseInt(t[1],16),f=parseInt(t[2],16),p=parseInt(t[3],16)):(t=/#([0-F])([0-F])([0-F])/gi.exec(e))&&(d=parseInt(t[1]+t[1],16),f=parseInt(t[2]+t[2],16),p=parseInt(t[3]+t[3],16)),d=0>d?0:d>255?255:d,f=0>f?0:f>255?255:f,p=0>p?0:p>255?255:p,u}var u=this,d=0,f=0,p=0;e&&c(e),u.toRgb=s,u.toHsv=l,u.toHex=a,u.parse=c}var t=Math.min,n=Math.max,r=Math.round;return e}),r(He,[Ne,Q,K,Me],function(e,t,n,r){return e.extend({Defaults:{classes:\"widget colorpicker\"},init:function(e){this._super(e)},postRender:function(){function e(e,t){var r=n.getPos(e),i,o;return i=t.pageX-r.x,o=t.pageY-r.y,i=Math.max(0,Math.min(i/e.clientWidth,1)),o=Math.max(0,Math.min(o/e.clientHeight,1)),{x:i,y:o}}function i(e,t){var i=(360-e.h)/360;n.css(d,{top:100*i+\"%\"}),t||n.css(p,{left:e.s+\"%\",top:100-e.v+\"%\"}),f.style.background=new r({s:100,v:100,h:e.h}).toHex(),s.color().parse({s:e.s,v:e.v,h:e.h})}function o(t){var n;n=e(f,t),c.s=100*n.x,c.v=100*(1-n.y),i(c),s.fire(\"change\")}function a(t){var n;n=e(u,t),c=l.toHsv(),c.h=360*(1-n.y),i(c,!0),s.fire(\"change\")}var s=this,l=s.color(),c,u,d,f,p;u=s.getEl(\"h\"),d=s.getEl(\"hp\"),f=s.getEl(\"sv\"),p=s.getEl(\"svp\"),s._repaint=function(){c=l.toHsv(),i(c)},s._super(),s._svdraghelper=new t(s._id+\"-sv\",{start:o,drag:o}),s._hdraghelper=new t(s._id+\"-h\",{start:a,drag:a}),s._repaint()},rgb:function(){return this.color().toRgb()},value:function(e){var t=this;return arguments.length?(t.color().parse(e),void(t._rendered&&t._repaint())):t.color().toHex()},color:function(){return this._color||(this._color=new r),this._color},renderHtml:function(){function e(){var e,t,n=\"\",i,a;for(i=\"filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=\",a=o.split(\",\"),e=0,t=a.length-1;t>e;e++)n+='
';return n}var t=this,n=t._id,r=t.classPrefix,i,o=\"#ff0000,#ff0080,#ff00ff,#8000ff,#0000ff,#0080ff,#00ffff,#00ff80,#00ff00,#80ff00,#ffff00,#ff8000,#ff0000\",a=\"background: -ms-linear-gradient(top,\"+o+\");background: linear-gradient(to bottom,\"+o+\");\";\n\nreturn i='
'+e()+'
','
'+i+\"
\"}})}),r(Le,[Ne],function(e){return e.extend({init:function(e){var t=this;e.delimiter||(e.delimiter=\"\\xbb\"),t._super(e),t.addClass(\"path\"),t.canFocus=!0,t.on(\"click\",function(e){var n,r=e.target;(n=r.getAttribute(\"data-index\"))&&t.fire(\"select\",{value:t.data()[n],index:n})})},focus:function(){var e=this;return e.getEl().firstChild.focus(),e},data:function(e){var t=this;return\"undefined\"!=typeof e?(t._data=e,t.update(),t):t._data},update:function(){this.innerHtml(this._getPathHtml())},postRender:function(){var e=this;e._super(),e.data(e.settings.data)},renderHtml:function(){var e=this;return'
'+e._getPathHtml()+\"
\"},_getPathHtml:function(){var e=this,t=e._data||[],n,r,i=\"\",o=e.classPrefix;for(n=0,r=t.length;r>n;n++)i+=(n>0?'
'+e.settings.delimiter+\"
\":\"\")+'
'+t[n].name+\"
\";return i||(i='
\\xa0
'),i}})}),r(Pe,[Le,he],function(e,t){return e.extend({postRender:function(){function e(e){if(1===e.nodeType){if(\"BR\"==e.nodeName||e.getAttribute(\"data-mce-bogus\"))return!0;if(\"bookmark\"===e.getAttribute(\"data-mce-type\"))return!0}return!1}var n=this,r=t.activeEditor;return r.settings.elementpath!==!1&&(n.on(\"select\",function(e){r.focus(),r.selection.select(this.data()[e.index].element),r.nodeChanged()}),r.on(\"nodeChange\",function(t){for(var i=[],o=t.parents,a=o.length;a--;)if(1==o[a].nodeType&&!e(o[a])){var s=r.fire(\"ResolveName\",{name:o[a].nodeName.toLowerCase(),target:o[a]});if(s.isDefaultPrevented()||i.push({name:s.name,element:o[a]}),s.isPropagationStopped())break}n.data(i)})),n._super()}})}),r(Oe,[J],function(e){return e.extend({Defaults:{layout:\"flex\",align:\"center\",defaults:{flex:1}},renderHtml:function(){var e=this,t=e._layout,n=e.classPrefix;return e.addClass(\"formitem\"),t.preRender(e),'
'+(e.settings.title?'
'+e.settings.title+\"
\":\"\")+'
'+(e.settings.html||\"\")+t.renderHtml(e)+\"
\"}})}),r(Ie,[J,Oe,d],function(e,t,n){return e.extend({Defaults:{containerCls:\"form\",layout:\"flex\",direction:\"column\",align:\"stretch\",flex:1,padding:20,labelGap:30,spacing:10,callbacks:{submit:function(){this.submit()}}},preRender:function(){var e=this,r=e.items();e.settings.formItemDefaults||(e.settings.formItemDefaults={layout:\"flex\",autoResize:\"overflow\",defaults:{flex:1}}),r.each(function(r){var i,o=r.settings.label;o&&(i=new t(n.extend({items:{type:\"label\",id:r._id+\"-l\",text:o,flex:0,forId:r._id,disabled:r.disabled()}},e.settings.formItemDefaults)),i.type=\"formitem\",r.aria(\"labelledby\",r._id+\"-l\"),\"undefined\"==typeof r.settings.flex&&(r.settings.flex=1),e.replace(r,i),i.add(r))})},recalcLabels:function(){var e=this,t=0,n=[],r,i,o;if(e.settings.labelGapCalc!==!1)for(o=\"children\"==e.settings.labelGapCalc?e.find(\"formitem\"):e.items(),o.filter(\"formitem\").each(function(e){var r=e.items()[0],i=r.getEl().clientWidth;t=i>t?i:t,n.push(r)}),i=e.settings.labelGap||0,r=n.length;r--;)n[r].settings.minWidth=t+i},visible:function(e){var t=this._super(e);return e===!0&&this._rendered&&this.recalcLabels(),t},submit:function(){return this.fire(\"submit\",{data:this.toJSON()})},postRender:function(){var e=this;e._super(),e.recalcLabels(),e.fromJSON(e.settings.data)}})}),r(Fe,[Ie],function(e){return e.extend({Defaults:{containerCls:\"fieldset\",layout:\"flex\",direction:\"column\",align:\"stretch\",flex:1,padding:\"25 15 5 15\",labelGap:30,spacing:10,border:1},renderHtml:function(){var e=this,t=e._layout,n=e.classPrefix;return e.preRender(),t.preRender(e),'
'+(e.settings.title?''+e.settings.title+\"\":\"\")+'
'+(e.settings.html||\"\")+t.renderHtml(e)+\"
\"}})}),r(ze,[Re,d],function(e,t){return e.extend({init:function(e){var n=this,r=tinymce.activeEditor,i=r.settings,o,a,s;e.spellcheck=!1,s=i.file_picker_types||i.file_browser_callback_types,s&&(s=t.makeMap(s,/[, ]/)),(!s||s[e.filetype])&&(a=i.file_picker_callback,!a||s&&!s[e.filetype]?(a=i.file_browser_callback,!a||s&&!s[e.filetype]||(o=function(){a(n.getEl(\"inp\").id,n.value(),e.filetype,window)})):o=function(){var i=n.fire(\"beforecall\").meta;i=t.extend({filetype:e.filetype},i),a.call(r,function(e,t){n.value(e).fire(\"change\",{meta:t})},n.value(),i)}),o&&(e.icon=\"browse\",e.onaction=o),n._super(e)}})}),r(We,[_e],function(e){return e.extend({recalc:function(e){var t=e.layoutRect(),n=e.paddingBox();e.items().filter(\":visible\").each(function(e){e.layoutRect({x:n.left,y:n.top,w:t.innerW-n.right-n.left,h:t.innerH-n.top-n.bottom}),e.recalc&&e.recalc()})}})}),r(Ve,[_e],function(e){return e.extend({recalc:function(e){var t,n,r,i,o,a,s,l,c,u,d,f,p,h,m,g,v=[],y,b,C,x,w,_,E,N,k,S,T,R,A,B,D,M,H,L,P,O,I,F,z=Math.max,W=Math.min;for(r=e.items().filter(\":visible\"),i=e.layoutRect(),o=e._paddingBox,a=e.settings,f=e.isRtl()?a.direction||\"row-reversed\":a.direction,s=a.align,l=e.isRtl()?a.pack||\"end\":a.pack,c=a.spacing||0,(\"row-reversed\"==f||\"column-reverse\"==f)&&(r=r.set(r.toArray().reverse()),f=f.split(\"-\")[0]),\"column\"==f?(k=\"y\",E=\"h\",N=\"minH\",S=\"maxH\",R=\"innerH\",T=\"top\",A=\"deltaH\",B=\"contentH\",P=\"left\",H=\"w\",D=\"x\",M=\"innerW\",L=\"minW\",O=\"right\",I=\"deltaW\",F=\"contentW\"):(k=\"x\",E=\"w\",N=\"minW\",S=\"maxW\",R=\"innerW\",T=\"left\",A=\"deltaW\",B=\"contentW\",P=\"top\",H=\"h\",D=\"y\",M=\"innerH\",L=\"minH\",O=\"bottom\",I=\"deltaH\",F=\"contentH\"),d=i[R]-o[T]-o[T],_=u=0,t=0,n=r.length;n>t;t++)p=r[t],h=p.layoutRect(),m=p.settings,g=m.flex,d-=n-1>t?c:0,g>0&&(u+=g,h[S]&&v.push(p),h.flex=g),d-=h[N],y=o[P]+h[L]+o[O],y>_&&(_=y);if(x={},0>d?x[N]=i[N]-d+i[A]:x[N]=i[R]-d+i[A],x[L]=_+i[I],x[B]=i[R]-d,x[F]=_,x.minW=W(x.minW,i.maxW),x.minH=W(x.minH,i.maxH),x.minW=z(x.minW,i.startMinWidth),x.minH=z(x.minH,i.startMinHeight),!i.autoResize||x.minW==i.minW&&x.minH==i.minH){for(C=d/u,t=0,n=v.length;n>t;t++)p=v[t],h=p.layoutRect(),b=h[S],y=h[N]+h.flex*C,y>b?(d-=h[S]-h[N],u-=h.flex,h.flex=0,h.maxFlexSize=b):h.maxFlexSize=0;for(C=d/u,w=o[T],x={},0===u&&(\"end\"==l?w=d+o[T]:\"center\"==l?(w=Math.round(i[R]/2-(i[R]-d)/2)+o[T],0>w&&(w=o[T])):\"justify\"==l&&(w=o[T],c=Math.floor(d/(r.length-1)))),x[D]=o[P],t=0,n=r.length;n>t;t++)p=r[t],h=p.layoutRect(),y=h.maxFlexSize||h[N],\"center\"===s?x[D]=Math.round(i[M]/2-h[H]/2):\"stretch\"===s?(x[H]=z(h[L]||0,i[M]-o[P]-o[O]),x[D]=o[P]):\"end\"===s&&(x[D]=i[M]-h[H]-o.top),h.flex>0&&(y+=h.flex*C),x[E]=y,x[k]=w,p.layoutRect(x),p.recalc&&p.recalc(),w+=y+c}else if(x.w=x.minW,x.h=x.minH,e.layoutRect(x),this.recalc(e),null===e._lastRect){var V=e.parent();V&&(V._lastRect=null,V.recalc())}}})}),r(Ue,[we],function(e){return e.extend({Defaults:{containerClass:\"flow-layout\",controlClass:\"flow-layout-item\",endClass:\"break\"},recalc:function(e){e.items().filter(\":visible\").each(function(e){e.recalc&&e.recalc()})}})}),r($e,[Y,Ne,re,d,he,u],function(e,t,n,r,i,o){function a(e){function t(t,n){return function(){var r=this;e.on(\"nodeChange\",function(i){var o=e.formatter,a=null;s(i.parents,function(e){return s(t,function(t){return n?o.matchNode(e,n,{value:t.value})&&(a=t.value):o.matchNode(e,t.value)&&(a=t.value),a?!1:void 0}),a?!1:void 0}),r.value(a)})}}function r(e){e=e.replace(/;$/,\"\").split(\";\");for(var t=e.length;t--;)e[t]=e[t].split(\"=\");return e}function i(){function t(e){var n=[];if(e)return s(e,function(e){var o={text:e.title,icon:e.icon};if(e.items)o.menu=t(e.items);else{var a=e.format||\"custom\"+r++;e.format||(e.name=a,i.push(e)),o.format=a,o.cmd=e.cmd}n.push(o)}),n}function n(){var n;return n=t(e.settings.style_formats_merge?e.settings.style_formats?o.concat(e.settings.style_formats):o:e.settings.style_formats||o)}var r=0,i=[],o=[{title:\"Headings\",items:[{title:\"Heading 1\",format:\"h1\"},{title:\"Heading 2\",format:\"h2\"},{title:\"Heading 3\",format:\"h3\"},{title:\"Heading 4\",format:\"h4\"},{title:\"Heading 5\",format:\"h5\"},{title:\"Heading 6\",format:\"h6\"}]},{title:\"Inline\",items:[{title:\"Bold\",icon:\"bold\",format:\"bold\"},{title:\"Italic\",icon:\"italic\",format:\"italic\"},{title:\"Underline\",icon:\"underline\",format:\"underline\"},{title:\"Strikethrough\",icon:\"strikethrough\",format:\"strikethrough\"},{title:\"Superscript\",icon:\"superscript\",format:\"superscript\"},{title:\"Subscript\",icon:\"subscript\",format:\"subscript\"},{title:\"Code\",icon:\"code\",format:\"code\"}]},{title:\"Blocks\",items:[{title:\"Paragraph\",format:\"p\"},{title:\"Blockquote\",format:\"blockquote\"},{title:\"Div\",format:\"div\"},{title:\"Pre\",format:\"pre\"}]},{title:\"Alignment\",items:[{title:\"Left\",icon:\"alignleft\",format:\"alignleft\"},{title:\"Center\",icon:\"aligncenter\",format:\"aligncenter\"},{title:\"Right\",icon:\"alignright\",format:\"alignright\"},{title:\"Justify\",icon:\"alignjustify\",format:\"alignjustify\"}]}];return e.on(\"init\",function(){s(i,function(t){e.formatter.register(t.name,t)})}),{type:\"menu\",items:n(),onPostRender:function(t){e.fire(\"renderFormatsMenu\",{control:t.control})},itemDefaults:{preview:!0,textStyle:function(){return this.settings.format?e.formatter.getCssText(this.settings.format):void 0},onPostRender:function(){var t=this;t.parent().on(\"show\",function(){var n,r;n=t.settings.format,n&&(t.disabled(!e.formatter.canApply(n)),t.active(e.formatter.match(n))),r=t.settings.cmd,r&&t.active(e.queryCommandState(r))})},onclick:function(){this.settings.format&&l(this.settings.format),this.settings.cmd&&e.execCommand(this.settings.cmd)}}}}function o(t){return function(){function n(){return e.undoManager?e.undoManager[t]():!1}var r=this;t=\"redo\"==t?\"hasRedo\":\"hasUndo\",r.disabled(!n()),e.on(\"Undo Redo AddUndo TypingUndo ClearUndos\",function(){r.disabled(!n())})}}function a(){var t=this;e.on(\"VisualAid\",function(e){t.active(e.hasVisual)}),t.active(e.hasVisual)}function l(t){t.control&&(t=t.control.value()),t&&e.execCommand(\"mceToggleFormat\",!1,t)}var c;c=i(),s({bold:\"Bold\",italic:\"Italic\",underline:\"Underline\",strikethrough:\"Strikethrough\",subscript:\"Subscript\",superscript:\"Superscript\"},function(t,n){e.addButton(n,{tooltip:t,onPostRender:function(){var t=this;e.formatter?e.formatter.formatChanged(n,function(e){t.active(e)}):e.on(\"init\",function(){e.formatter.formatChanged(n,function(e){t.active(e)})})},onclick:function(){l(n)}})}),s({outdent:[\"Decrease indent\",\"Outdent\"],indent:[\"Increase indent\",\"Indent\"],cut:[\"Cut\",\"Cut\"],copy:[\"Copy\",\"Copy\"],paste:[\"Paste\",\"Paste\"],help:[\"Help\",\"mceHelp\"],selectall:[\"Select all\",\"SelectAll\"],removeformat:[\"Clear formatting\",\"RemoveFormat\"],visualaid:[\"Visual aids\",\"mceToggleVisualAid\"],newdocument:[\"New document\",\"mceNewDocument\"]},function(t,n){e.addButton(n,{tooltip:t[0],cmd:t[1]})}),s({blockquote:[\"Blockquote\",\"mceBlockQuote\"],numlist:[\"Numbered list\",\"InsertOrderedList\"],bullist:[\"Bullet list\",\"InsertUnorderedList\"],subscript:[\"Subscript\",\"Subscript\"],superscript:[\"Superscript\",\"Superscript\"],alignleft:[\"Align left\",\"JustifyLeft\"],aligncenter:[\"Align center\",\"JustifyCenter\"],alignright:[\"Align right\",\"JustifyRight\"],alignjustify:[\"Justify\",\"JustifyFull\"]},function(t,n){e.addButton(n,{tooltip:t[0],cmd:t[1],onPostRender:function(){var t=this;e.formatter?e.formatter.formatChanged(n,function(e){t.active(e)}):e.on(\"init\",function(){e.formatter.formatChanged(n,function(e){t.active(e)})})}})}),e.addButton(\"undo\",{tooltip:\"Undo\",onPostRender:o(\"undo\"),cmd:\"undo\"}),e.addButton(\"redo\",{tooltip:\"Redo\",onPostRender:o(\"redo\"),cmd:\"redo\"}),e.addMenuItem(\"newdocument\",{text:\"New document\",icon:\"newdocument\",cmd:\"mceNewDocument\"}),e.addMenuItem(\"undo\",{text:\"Undo\",icon:\"undo\",shortcut:\"Meta+Z\",onPostRender:o(\"undo\"),cmd:\"undo\"}),e.addMenuItem(\"redo\",{text:\"Redo\",icon:\"redo\",shortcut:\"Meta+Y\",onPostRender:o(\"redo\"),cmd:\"redo\"}),e.addMenuItem(\"visualaid\",{text:\"Visual aids\",selectable:!0,onPostRender:a,cmd:\"mceToggleVisualAid\"}),s({cut:[\"Cut\",\"Cut\",\"Meta+X\"],copy:[\"Copy\",\"Copy\",\"Meta+C\"],paste:[\"Paste\",\"Paste\",\"Meta+V\"],selectall:[\"Select all\",\"SelectAll\",\"Meta+A\"],bold:[\"Bold\",\"Bold\",\"Meta+B\"],italic:[\"Italic\",\"Italic\",\"Meta+I\"],underline:[\"Underline\",\"Underline\"],strikethrough:[\"Strikethrough\",\"Strikethrough\"],subscript:[\"Subscript\",\"Subscript\"],superscript:[\"Superscript\",\"Superscript\"],removeformat:[\"Clear formatting\",\"RemoveFormat\"]},function(t,n){e.addMenuItem(n,{text:t[0],icon:n,shortcut:t[2],cmd:t[1]})}),e.on(\"mousedown\",function(){n.hideAll()}),e.addButton(\"styleselect\",{type:\"menubutton\",text:\"Formats\",menu:c}),e.addButton(\"formatselect\",function(){var n=[],i=r(e.settings.block_formats||\"Paragraph=p;Heading 1=h1;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6;Preformatted=pre\");return s(i,function(t){n.push({text:t[0],value:t[1],textStyle:function(){return e.formatter.getCssText(t[1])}})}),{type:\"listbox\",text:i[0][0],values:n,fixedWidth:!0,onselect:l,onPostRender:t(n)}}),e.addButton(\"fontselect\",function(){var n=\"Andale Mono=andale mono,monospace;Arial=arial,helvetica,sans-serif;Arial Black=arial black,sans-serif;Book Antiqua=book antiqua,palatino,serif;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,palatino,serif;Helvetica=helvetica,arial,sans-serif;Impact=impact,sans-serif;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco,monospace;Times New Roman=times new roman,times,serif;Trebuchet MS=trebuchet ms,geneva,sans-serif;Verdana=verdana,geneva,sans-serif;Webdings=webdings;Wingdings=wingdings,zapf dingbats\",i=[],o=r(e.settings.font_formats||n);return s(o,function(e){i.push({text:{raw:e[0]},value:e[1],textStyle:-1==e[1].indexOf(\"dings\")?\"font-family:\"+e[1]:\"\"})}),{type:\"listbox\",text:\"Font Family\",tooltip:\"Font Family\",values:i,fixedWidth:!0,onPostRender:t(i,\"fontname\"),onselect:function(t){t.control.settings.value&&e.execCommand(\"FontName\",!1,t.control.settings.value)}}}),e.addButton(\"fontsizeselect\",function(){var n=[],r=\"8pt 10pt 12pt 14pt 18pt 24pt 36pt\",i=e.settings.fontsize_formats||r;return s(i.split(\" \"),function(e){var t=e,r=e,i=e.split(\"=\");i.length>1&&(t=i[0],r=i[1]),n.push({text:t,value:r})}),{type:\"listbox\",text:\"Font Sizes\",tooltip:\"Font Sizes\",values:n,fixedWidth:!0,onPostRender:t(n,\"fontsize\"),onclick:function(t){t.control.settings.value&&e.execCommand(\"FontSize\",!1,t.control.settings.value)}}}),e.addMenuItem(\"formats\",{text:\"Formats\",menu:c})}var s=r.each;i.on(\"AddEditor\",function(t){t.editor.rtl&&(e.rtl=!0),a(t.editor)}),e.translate=function(e){return i.translate(e)},t.tooltips=!o.iOS}),r(qe,[_e],function(e){return e.extend({recalc:function(e){var t=e.settings,n,r,i,o,a,s,l,c,u,d,f,p,h,m,g,v,y,b,C,x,w,_,E=[],N=[],k,S,T,R,A,B;t=e.settings,i=e.items().filter(\":visible\"),o=e.layoutRect(),r=t.columns||Math.ceil(Math.sqrt(i.length)),n=Math.ceil(i.length/r),y=t.spacingH||t.spacing||0,b=t.spacingV||t.spacing||0,C=t.alignH||t.align,x=t.alignV||t.align,g=e._paddingBox,A=\"reverseRows\"in t?t.reverseRows:e.isRtl(),C&&\"string\"==typeof C&&(C=[C]),x&&\"string\"==typeof x&&(x=[x]);for(d=0;r>d;d++)E.push(0);for(f=0;n>f;f++)N.push(0);for(f=0;n>f;f++)for(d=0;r>d&&(u=i[f*r+d],u);d++)c=u.layoutRect(),k=c.minW,S=c.minH,E[d]=k>E[d]?k:E[d],N[f]=S>N[f]?S:N[f];for(T=o.innerW-g.left-g.right,w=0,d=0;r>d;d++)w+=E[d]+(d>0?y:0),T-=(d>0?y:0)+E[d];for(R=o.innerH-g.top-g.bottom,_=0,f=0;n>f;f++)_+=N[f]+(f>0?b:0),R-=(f>0?b:0)+N[f];if(w+=g.left+g.right,_+=g.top+g.bottom,l={},l.minW=w+(o.w-o.innerW),l.minH=_+(o.h-o.innerH),l.contentW=l.minW-o.deltaW,l.contentH=l.minH-o.deltaH,l.minW=Math.min(l.minW,o.maxW),l.minH=Math.min(l.minH,o.maxH),l.minW=Math.max(l.minW,o.startMinWidth),l.minH=Math.max(l.minH,o.startMinHeight),!o.autoResize||l.minW==o.minW&&l.minH==o.minH){o.autoResize&&(l=e.layoutRect(l),l.contentW=l.minW-o.deltaW,l.contentH=l.minH-o.deltaH);var D;D=\"start\"==t.packV?0:R>0?Math.floor(R/n):0;var M=0,H=t.flexWidths;if(H)for(d=0;dd;d++)E[d]+=H?H[d]*L:L;for(h=g.top,f=0;n>f;f++){for(p=g.left,s=N[f]+D,d=0;r>d&&(B=A?f*r+r-1-d:f*r+d,u=i[B],u);d++)m=u.settings,c=u.layoutRect(),a=Math.max(E[d],c.startMinWidth),c.x=p,c.y=h,v=m.alignH||(C?C[d]||C[0]:null),\"center\"==v?c.x=p+a/2-c.w/2:\"right\"==v?c.x=p+a-c.w:\"stretch\"==v&&(c.w=a),v=m.alignV||(x?x[d]||x[0]:null),\"center\"==v?c.y=h+s/2-c.h/2:\"bottom\"==v?c.y=h+s-c.h:\"stretch\"==v&&(c.h=s),u.layoutRect(c),p+=a+y,u.recalc&&u.recalc();h+=s+b}}else if(l.w=l.minW,l.h=l.minH,e.layoutRect(l),this.recalc(e),null===e._lastRect){var P=e.parent();P&&(P._lastRect=null,P.recalc())}}})}),r(je,[Ne],function(e){return e.extend({renderHtml:function(){var e=this;return e.addClass(\"iframe\"),e.canFocus=!1,''},src:function(e){this.getEl().src=e},html:function(e,t){var n=this,r=this.getEl().contentWindow.document.body;return r?(r.innerHTML=e,t&&t()):setTimeout(function(){n.html(e)},0),this}})}),r(Ke,[Ne,K],function(e,t){return e.extend({init:function(e){var t=this;t._super(e),t.addClass(\"widget\"),t.addClass(\"label\"),t.canFocus=!1,e.multiline&&t.addClass(\"autoscroll\"),e.strong&&t.addClass(\"strong\")},initLayoutRect:function(){var e=this,n=e._super();if(e.settings.multiline){var r=t.getSize(e.getEl());r.width>n.maxW&&(n.minW=n.maxW,e.addClass(\"multiline\")),e.getEl().style.width=n.minW+\"px\",n.startMinH=n.h=n.minH=Math.min(n.maxH,t.getSize(e.getEl()).height)}return n},repaint:function(){var e=this;return e.settings.multiline||(e.getEl().style.lineHeight=e.layoutRect().h+\"px\"),e._super()},text:function(e){var t=this;return t._rendered&&e&&this.innerHtml(t.encode(e)),t._super(e)},renderHtml:function(){var e=this,t=e.settings.forId;return'\"}})}),r(Ye,[J],function(e){return e.extend({Defaults:{role:\"toolbar\",layout:\"flow\"},init:function(e){var t=this;t._super(e),t.addClass(\"toolbar\")},postRender:function(){var e=this;return e.items().addClass(\"toolbar-item\"),e._super()}})}),r(Ge,[Ye],function(e){return e.extend({Defaults:{role:\"menubar\",containerCls:\"menubar\",ariaRoot:!0,defaults:{type:\"menubutton\"}}})}),r(Xe,[ke,G,Ge],function(e,t,n){function r(e,t){for(;e;){if(t===e)return!0;e=e.parentNode}return!1}var i=e.extend({init:function(e){var t=this;t._renderOpen=!0,t._super(e),t.addClass(\"menubtn\"),e.fixedWidth&&t.addClass(\"fixed-width\"),t.aria(\"haspopup\",!0),t.hasPopup=!0},showMenu:function(){var e=this,n=e.settings,r;return e.menu&&e.menu.visible()?e.hideMenu():(e.menu||(r=n.menu||[],r.length?r={type:\"menu\",items:r}:r.type=r.type||\"menu\",e.menu=t.create(r).parent(e).renderTo(),e.fire(\"createmenu\"),e.menu.reflow(),e.menu.on(\"cancel\",function(t){t.control.parent()===e.menu&&(t.stopPropagation(),e.focus(),e.hideMenu())}),e.menu.on(\"select\",function(){e.focus()}),e.menu.on(\"show hide\",function(t){t.control==e.menu&&e.activeMenu(\"show\"==t.type),e.aria(\"expanded\",\"show\"==t.type)}).fire(\"show\")),e.menu.show(),e.menu.layoutRect({w:e.layoutRect().w}),void e.menu.moveRel(e.getEl(),e.isRtl()?[\"br-tr\",\"tr-br\"]:[\"bl-tl\",\"tl-bl\"]))},hideMenu:function(){var e=this;e.menu&&(e.menu.items().each(function(e){e.hideMenu&&e.hideMenu()}),e.menu.hide())},activeMenu:function(e){this.toggleClass(\"active\",e)},renderHtml:function(){var e=this,t=e._id,r=e.classPrefix,i=e.settings.icon,o;return o=e.settings.image,o?(i=\"none\",\"string\"!=typeof o&&(o=window.getSelection?o[0]:o[1]),o=\" style=\\\"background-image: url('\"+o+\"')\\\"\"):o=\"\",i=e.settings.icon?r+\"ico \"+r+\"i-\"+i:\"\",e.aria(\"role\",e.parent()instanceof n?\"menuitem\":\"button\"),'
'},postRender:function(){var e=this;return e.on(\"click\",function(t){t.control===e&&r(t.target,e.getEl())&&(e.showMenu(),t.aria&&e.menu.items()[0].focus())}),e.on(\"mouseenter\",function(t){var n=t.control,r=e.parent(),o;n&&r&&n instanceof i&&n.parent()==r&&(r.items().filter(\"MenuButton\").each(function(e){e.hideMenu&&e!=n&&(e.menu&&e.menu.visible()&&(o=!0),e.hideMenu())}),o&&(n.focus(),n.showMenu()))}),e._super()},text:function(e){var t=this,n,r;if(t._rendered)for(r=t.getEl(\"open\").getElementsByTagName(\"span\"),n=0;n0&&(o=r[0].text,n._value=r[0].value),e.menu=r),e.text=e.text||o||r[0].text,n._super(e),n.addClass(\"listbox\"),n.on(\"select\",function(t){var r=t.control;a&&(t.lastControl=a),e.multiple?r.active(!r.active()):n.value(t.control.settings.value),a=r})},value:function(e){function t(e,n){e.items().each(function(e){i=e.value()===n,i&&(o=o||e.text()),e.active(i),e.menu&&t(e.menu,n)})}function n(t){for(var r=0;r'+(\"-\"!==a?'\\xa0\":\"\")+(\"-\"!==a?''+a+\"\":\"\")+(c?'
'+c+\"
\":\"\")+(i.menu?'
':\"\")+\"
\"},postRender:function(){var e=this,t=e.settings,n=t.textStyle;if(\"function\"==typeof n&&(n=n.call(this)),n){var r=e.getEl(\"text\");r&&r.setAttribute(\"style\",n)}return e.on(\"mouseenter click\",function(n){n.control===e&&(t.menu||\"click\"!==n.type?(e.showMenu(),n.aria&&e.menu.focus(!0)):(e.fire(\"select\"),e.parent().hideAll()))}),e._super(),e},active:function(e){return\"undefined\"!=typeof e&&this.aria(\"checked\",e),this._super(e)},remove:function(){this._super(),this.menu&&this.menu.remove()}})}),r(Ze,[re,Qe,d],function(e,t,n){var r=e.extend({Defaults:{defaultType:\"menuitem\",border:1,layout:\"stack\",role:\"application\",bodyRole:\"menu\",ariaRoot:!0},init:function(e){var t=this;if(e.autohide=!0,e.constrainToViewport=!0,e.itemDefaults)for(var r=e.items,i=r.length;i--;)r[i]=n.extend({},e.itemDefaults,r[i]);t._super(e),t.addClass(\"menu\")},repaint:function(){return this.toggleClass(\"menu-align\",!0),this._super(),this.getEl().style.height=\"\",this.getEl(\"body\").style.height=\"\",this},cancel:function(){var e=this;e.hideAll(),e.fire(\"select\")},hideAll:function(){var e=this;return this.find(\"menuitem\").exec(\"hideMenu\"),e._super()},preRender:function(){var e=this;return e.items().each(function(t){var n=t.settings;return n.icon||n.selectable?(e._hasIcons=!0,!1):void 0}),e._super()}});return r}),r(et,[Te],function(e){return e.extend({Defaults:{classes:\"radio\",role:\"radio\"}})}),r(tt,[Ne,Q],function(e,t){return e.extend({renderHtml:function(){var e=this,t=e.classPrefix;return e.addClass(\"resizehandle\"),\"both\"==e.settings.direction&&e.addClass(\"resizehandle-both\"),e.canFocus=!1,'
'},postRender:function(){var e=this;e._super(),e.resizeDragHelper=new t(this._id,{start:function(){e.fire(\"ResizeStart\")},drag:function(t){\"both\"!=e.settings.direction&&(t.deltaX=0),e.fire(\"Resize\",t)},stop:function(){e.fire(\"ResizeEnd\")}})},remove:function(){return this.resizeDragHelper&&this.resizeDragHelper.destroy(),this._super()}})}),r(nt,[Ne],function(e){return e.extend({renderHtml:function(){var e=this;return e.addClass(\"spacer\"),e.canFocus=!1,'
'}})}),r(rt,[Xe,K],function(e,t){return e.extend({Defaults:{classes:\"widget btn splitbtn\",role:\"button\"},repaint:function(){var e=this,n=e.getEl(),r=e.layoutRect(),i,o;return e._super(),i=n.firstChild,o=n.lastChild,t.css(i,{width:r.w-t.getSize(o).width,height:r.h-2}),t.css(o,{height:r.h-2}),e},activeMenu:function(e){var n=this;t.toggleClass(n.getEl().lastChild,n.classPrefix+\"active\",e)},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r,i=e.settings.icon;return r=e.settings.image,r?(i=\"none\",\"string\"!=typeof r&&(r=window.getSelection?r[0]:r[1]),r=\" style=\\\"background-image: url('\"+r+\"')\\\"\"):r=\"\",i=e.settings.icon?n+\"ico \"+n+\"i-\"+i:\"\",'
'},postRender:function(){var e=this,t=e.settings.onclick;return e.on(\"click\",function(e){var n=e.target;if(e.control==this)for(;n;){if(e.aria&&\"down\"!=e.aria.key||\"BUTTON\"==n.nodeName&&-1==n.className.indexOf(\"open\"))return e.stopImmediatePropagation(),void t.call(this,e);n=n.parentNode}}),delete e.settings.onclick,e._super()}})}),r(it,[Ue],function(e){return e.extend({Defaults:{containerClass:\"stack-layout\",controlClass:\"stack-layout-item\",endClass:\"break\"}})}),r(ot,[ee,K],function(e,t){return e.extend({Defaults:{layout:\"absolute\",defaults:{type:\"panel\"}},activateTab:function(e){var n;this.activeTabId&&(n=this.getEl(this.activeTabId),t.removeClass(n,this.classPrefix+\"active\"),n.setAttribute(\"aria-selected\",\"false\")),this.activeTabId=\"t\"+e,n=this.getEl(\"t\"+e),n.setAttribute(\"aria-selected\",\"true\"),t.addClass(n,this.classPrefix+\"active\"),this.items()[e].show().fire(\"showtab\"),this.reflow(),this.items().each(function(t,n){e!=n&&t.hide()})},renderHtml:function(){var e=this,t=e._layout,n=\"\",r=e.classPrefix;return e.preRender(),t.preRender(e),e.items().each(function(t,i){var o=e._id+\"-t\"+i;t.aria(\"role\",\"tabpanel\"),t.aria(\"labelledby\",o),n+='
'+e.encode(t.settings.title)+\"
\"}),'
'+n+'
'+t.renderHtml(e)+\"
\"},postRender:function(){var e=this;e._super(),e.settings.activeTab=e.settings.activeTab||0,e.activateTab(e.settings.activeTab),this.on(\"click\",function(t){var n=t.target.parentNode;if(t.target.parentNode.id==e._id+\"-head\")for(var r=n.childNodes.length;r--;)n.childNodes[r]==t.target&&e.activateTab(r)})},initLayoutRect:function(){var e=this,n,r,i;r=t.getSize(e.getEl(\"head\")).width,r=0>r?0:r,i=0,e.items().each(function(e){r=Math.max(r,e.layoutRect().minW),i=Math.max(i,e.layoutRect().minH)}),e.items().each(function(e){e.settings.x=0,e.settings.y=0,e.settings.w=r,e.settings.h=i,e.layoutRect({x:0,y:0,w:r,h:i})});var o=t.getSize(e.getEl(\"head\")).height;return e.settings.minWidth=r,e.settings.minHeight=i+o,n=e._super(),n.deltaH+=o,n.innerH=n.h-n.deltaH,n}})}),r(at,[Ne,K],function(e,t){return e.extend({init:function(e){var t=this;t._super(e),t._value=e.value||\"\",t.addClass(\"textbox\"),e.multiline?t.addClass(\"multiline\"):t.on(\"keydown\",function(e){13==e.keyCode&&t.parents().reverse().each(function(t){return e.preventDefault(),t.hasEventListeners(\"submit\")&&t.toJSON?(t.fire(\"submit\",{data:t.toJSON()}),!1):void 0})})},disabled:function(e){var t=this;return t._rendered&&\"undefined\"!=typeof e&&(t.getEl().disabled=e),t._super(e)},value:function(e){var t=this;return\"undefined\"!=typeof e?(t._value=e,t._rendered&&(t.getEl().value=e),t):t._rendered?t.getEl().value:t._value},repaint:function(){var e=this,t,n,r,i=0,o=0,a;t=e.getEl().style,n=e._layoutRect,a=e._lastRepaintRect||{};var s=document;return!e.settings.multiline&&s.all&&(!s.documentMode||s.documentMode<=8)&&(t.lineHeight=n.h-o+\"px\"),r=e._borderBox,i=r.left+r.right+8,o=r.top+r.bottom+(e.settings.multiline?8:0),n.x!==a.x&&(t.left=n.x+\"px\",a.x=n.x),n.y!==a.y&&(t.top=n.y+\"px\",a.y=n.y),n.w!==a.w&&(t.width=n.w-i+\"px\",a.w=n.w),n.h!==a.h&&(t.height=n.h-o+\"px\",a.h=n.h),e._lastRepaintRect=a,e.fire(\"repaint\",{},!1),e},renderHtml:function(){var e=this,t=e._id,n=e.settings,r=e.encode(e._value,!1),i=\"\";return\"spellcheck\"in n&&(i+=' spellcheck=\"'+n.spellcheck+'\"'),n.maxLength&&(i+=' maxlength=\"'+n.maxLength+'\"'),n.size&&(i+=' size=\"'+n.size+'\"'),n.subtype&&(i+=' type=\"'+n.subtype+'\"'),e.disabled()&&(i+=' disabled=\"disabled\"'),n.multiline?'\":'\"},postRender:function(){var e=this;return t.on(e.getEl(),\"change\",function(t){e.fire(\"change\",t)}),e._super()},remove:function(){t.off(this.getEl()),this._super()}})}),r(st,[K,Y],function(e,t){return function(n,r){var i=this,o,a=t.classPrefix;i.show=function(t){return i.hide(),o=!0,window.setTimeout(function(){o&&n.appendChild(e.createFragment('
'));\n\n},t||0),i},i.hide=function(){var e=n.lastChild;return e&&-1!=e.className.indexOf(\"throbber\")&&e.parentNode.removeChild(e),o=!1,i}}}),a([l,c,u,d,f,p,h,m,g,y,b,C,x,_,E,N,k,S,T,R,A,B,D,M,H,L,O,I,F,z,W,V,U,$,q,j,K,Y,G,X,J,Q,Z,ee,te,ne,re,ie,oe,ae,se,le,ce,ue,de,fe,pe,he,me,ge,ve,ye,be,Ce,xe,we,_e,Ee,Ne,ke,Se,Te,Re,Ae,Be,De,Me,He,Le,Pe,Oe,Ie,Fe,ze,We,Ve,Ue,$e,qe,je,Ke,Ye,Ge,Xe,Je,Qe,Ze,et,tt,nt,rt,it,ot,at,st])\n\n\n// theme\ntinymce.ThemeManager.add(\"modern\",function(a){function b(){function b(b){var d,e=[];if(b)return l(b.split(/[ ,]/),function(b){function c(){var c=a.selection;\"bullist\"==f&&c.selectorChanged(\"ul > li\",function(a,c){for(var d,e=c.parents.length;e--&&(d=c.parents[e].nodeName,\"OL\"!=d&&\"UL\"!=d););b.active(a&&\"UL\"==d)}),\"numlist\"==f&&c.selectorChanged(\"ol > li\",function(a,c){for(var d,e=c.parents.length;e--&&(d=c.parents[e].nodeName,\"OL\"!=d&&\"UL\"!=d););b.active(a&&\"OL\"==d)}),b.settings.stateSelector&&c.selectorChanged(b.settings.stateSelector,function(a){b.active(a)},!0),b.settings.disabledStateSelector&&c.selectorChanged(b.settings.disabledStateSelector,function(a){b.disabled(a)})}var f;\"|\"==b?d=null:k.has(b)?(b={type:b},j.toolbar_items_size&&(b.size=j.toolbar_items_size),e.push(b),d=null):(d||(d={type:\"buttongroup\",items:[]},e.push(d)),a.buttons[b]&&(f=b,b=a.buttons[f],\"function\"==typeof b&&(b=b()),b.type=b.type||\"button\",j.toolbar_items_size&&(b.size=j.toolbar_items_size),b=k.create(b),d.items.push(b),a.initialized?c():a.on(\"init\",c)))}),c.push({type:\"toolbar\",layout:\"flow\",items:e}),!0}var c=[];if(tinymce.isArray(j.toolbar)){if(0===j.toolbar.length)return;tinymce.each(j.toolbar,function(a,b){j[\"toolbar\"+(b+1)]=a}),delete j.toolbar}for(var d=1;10>d&&b(j[\"toolbar\"+d]);d++);return c.length||j.toolbar===!1||b(j.toolbar||o),c.length?{type:\"panel\",layout:\"stack\",classes:\"toolbar-grp\",ariaRoot:!0,ariaRemember:!0,items:c}:void 0}function c(){function b(b){var c;return\"|\"==b?{text:\"|\"}:c=a.menuItems[b]}function c(c){var d,e,f,g,h;if(h=tinymce.makeMap((j.removed_menuitems||\"\").split(/[ ,]/)),j.menu?(e=j.menu[c],g=!0):e=n[c],e){d={text:e.title},f=[],l((e.items||\"\").split(/[ ,]/),function(a){var c=b(a);c&&!h[a]&&f.push(b(a))}),g||l(a.menuItems,function(a){a.context==c&&(\"before\"==a.separator&&f.push({text:\"|\"}),a.prependToContext?f.unshift(a):f.push(a),\"after\"==a.separator&&f.push({text:\"|\"}))});for(var i=0;i]+>[^<]+<\\/a>$/.test(b)||-1==b.indexOf(\"href=\")))return!1;if(a){var c,d=a.childNodes;if(0===d.length)return!1;for(c=d.length-1;c>=0;c--)if(3!=d[c].nodeType)return!1}return!0}var i,j,k,l,m,n,o,p,q,r,s,t,u={},v=a.selection,w=a.dom;i=v.getNode(),j=w.getParent(i,\"a[href]\"),m=h(),u.text=k=j?j.innerText||j.textContent:v.getContent({format:\"text\"}),u.href=j?w.getAttrib(j,\"href\"):\"\",j?u.target=w.getAttrib(j,\"target\"):a.settings.default_link_target&&(u.target=a.settings.default_link_target),(t=w.getAttrib(j,\"rel\"))&&(u.rel=t),(t=w.getAttrib(j,\"class\"))&&(u[\"class\"]=t),(t=w.getAttrib(j,\"title\"))&&(u.title=t),m&&(n={name:\"text\",type:\"textbox\",size:40,label:\"Text to display\",onchange:function(){u.text=this.value()}}),b&&(o={type:\"listbox\",label:\"Link list\",values:c(b,function(b){b.value=a.convertURL(b.value||b.url,\"href\")},[{text:\"None\",value:\"\"}]),onselect:d,value:a.convertURL(u.href,\"href\"),onPostRender:function(){o=this}}),a.settings.target_list!==!1&&(a.settings.target_list||(a.settings.target_list=[{text:\"None\",value:\"\"},{text:\"New window\",value:\"_blank\"}]),q={name:\"target\",type:\"listbox\",label:\"Target\",values:c(a.settings.target_list)}),a.settings.rel_list&&(p={name:\"rel\",type:\"listbox\",label:\"Rel\",values:c(a.settings.rel_list)}),a.settings.link_class_list&&(r={name:\"class\",type:\"listbox\",label:\"Class\",values:c(a.settings.link_class_list,function(b){b.value&&(b.textStyle=function(){return a.formatter.getCssText({inline:\"a\",classes:[b.value]})})})}),a.settings.link_title!==!1&&(s={name:\"title\",type:\"textbox\",label:\"Title\",value:u.title}),l=a.windowManager.open({title:\"Insert link\",data:u,body:[{name:\"href\",type:\"filepicker\",filetype:\"file\",size:40,autofocus:!0,label:\"Url\",onchange:g,onkeyup:f},n,s,e(u.href),o,p,q,r],onSubmit:function(b){function c(b,c){var d=a.selection.getRng();window.setTimeout(function(){a.windowManager.confirm(b,function(b){a.selection.setRng(d),c(b)})},0)}function d(){var b={href:e,target:u.target?u.target:null,rel:u.rel?u.rel:null,\"class\":u[\"class\"]?u[\"class\"]:null,title:u.title?u.title:null};j?(a.focus(),m&&u.text!=k&&(\"innerText\"in j?j.innerText=u.text:j.textContent=u.text),w.setAttribs(j,b),v.select(j),a.undoManager.add()):m?a.insertContent(w.createHTML(\"a\",b,w.encode(u.text))):a.execCommand(\"mceInsertLink\",!1,b)}var e;return u=tinymce.extend(u,b.data),(e=u.href)?e.indexOf(\"@\")>0&&-1==e.indexOf(\"//\")&&-1==e.indexOf(\"mailto:\")?void c(\"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?\",function(a){a&&(e=\"mailto:\"+e),d()}):a.settings.link_assume_external_targets&&!/^\\w+:/i.test(e)||!a.settings.link_assume_external_targets&&/^\\s*www\\./i.test(e)?void c(\"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?\",function(a){a&&(e=\"http://\"+e),d()}):void d():void a.execCommand(\"unlink\")}})}a.addButton(\"link\",{icon:\"link\",tooltip:\"Insert/edit link\",shortcut:\"Meta+K\",onclick:b(d),stateSelector:\"a[href]\"}),a.addButton(\"unlink\",{icon:\"unlink\",tooltip:\"Remove link\",cmd:\"unlink\",stateSelector:\"a[href]\"}),a.addShortcut(\"Meta+K\",\"\",b(d)),a.addCommand(\"mceLink\",b(d)),this.showDialog=d,a.addMenuItem(\"link\",{icon:\"link\",text:\"Insert/edit link\",shortcut:\"Meta+K\",onclick:b(d),stateSelector:\"a[href]\",context:\"insert\",prependToContext:!0})});\n\n// textcolor\ntinymce.PluginManager.add(\"textcolor\",function(a){function b(b){var c;return a.dom.getParents(a.selection.getStart(),function(a){var d;(d=a.style[\"forecolor\"==b?\"color\":\"background-color\"])&&(c=d)}),c}function c(){var b,c,d=[];for(c=a.settings.textcolor_map||[\"000000\",\"Black\",\"993300\",\"Burnt orange\",\"333300\",\"Dark olive\",\"003300\",\"Dark green\",\"003366\",\"Dark azure\",\"000080\",\"Navy Blue\",\"333399\",\"Indigo\",\"333333\",\"Very dark gray\",\"800000\",\"Maroon\",\"FF6600\",\"Orange\",\"808000\",\"Olive\",\"008000\",\"Green\",\"008080\",\"Teal\",\"0000FF\",\"Blue\",\"666699\",\"Grayish blue\",\"808080\",\"Gray\",\"FF0000\",\"Red\",\"FF9900\",\"Amber\",\"99CC00\",\"Yellow green\",\"339966\",\"Sea green\",\"33CCCC\",\"Turquoise\",\"3366FF\",\"Royal blue\",\"800080\",\"Purple\",\"999999\",\"Medium gray\",\"FF00FF\",\"Magenta\",\"FFCC00\",\"Gold\",\"FFFF00\",\"Yellow\",\"00FF00\",\"Lime\",\"00FFFF\",\"Aqua\",\"00CCFF\",\"Sky blue\",\"993366\",\"Red violet\",\"FFFFFF\",\"White\",\"FF99CC\",\"Pink\",\"FFCC99\",\"Peach\",\"FFFF99\",\"Light yellow\",\"CCFFCC\",\"Pale green\",\"CCFFFF\",\"Pale cyan\",\"99CCFF\",\"Light sky blue\",\"CC99FF\",\"Plum\"],b=0;b
'+(c?\"×\":\"\")+\"
\"}var d,e,f,g,h,k,l,m=this,n=m._id,o=0;for(d=c(),d.push({text:tinymce.translate(\"No color\"),color:\"transparent\"}),f='',g=d.length-1,k=0;j>k;k++){for(f+=\"\",h=0;i>h;h++)l=k*i+h,l>g?f+=\"\":(e=d[l],f+=b(e.color,e.text));f+=\"\"}if(a.settings.color_picker_callback){for(f+='\",f+=\"\",h=0;i>h;h++)f+=b(\"\",\"Custom color\");f+=\"\"}return f+=\"
\"}function e(b,c){a.undoManager.transact(function(){a.focus(),a.formatter.apply(b,{value:c}),a.nodeChanged()})}function f(b){a.undoManager.transact(function(){a.focus(),a.formatter.remove(b,{value:null},null,!0),a.nodeChanged()})}function g(c){function d(a){k.hidePanel(),k.color(a),e(k.settings.format,a)}function g(){k.hidePanel(),k.resetColor(),f(k.settings.format)}function h(a,b){a.style.background=b,a.setAttribute(\"data-mce-color\",b)}var j,k=this.parent();tinymce.DOM.getParent(c.target,\".mce-custom-color-btn\")&&(k.hidePanel(),a.settings.color_picker_callback.call(a,function(a){var b,c,e,f=k.panel.getEl().getElementsByTagName(\"table\")[0];for(b=tinymce.map(f.rows[f.rows.length-1].childNodes,function(a){return a.firstChild}),e=0;ee;e++)h(b[e],b[e+1].getAttribute(\"data-mce-color\"));h(c,a),d(a)},b(k.settings.format))),j=c.target.getAttribute(\"data-mce-color\"),j?(this.lastId&&document.getElementById(this.lastId).setAttribute(\"aria-selected\",!1),c.target.setAttribute(\"aria-selected\",!0),this.lastId=c.target.id,\"transparent\"==j?g():d(j)):null!==j&&k.hidePanel()}function h(){var a=this;a._color?e(a.settings.format,a._color):f(a.settings.format)}var i,j;j=a.settings.textcolor_rows||5,i=a.settings.textcolor_cols||8,a.addButton(\"forecolor\",{type:\"colorbutton\",tooltip:\"Text color\",format:\"forecolor\",panel:{role:\"application\",ariaRemember:!0,html:d,onclick:g},onclick:h}),a.addButton(\"backcolor\",{type:\"colorbutton\",tooltip:\"Background color\",format:\"hilitecolor\",panel:{role:\"application\",ariaRemember:!0,html:d,onclick:g},onclick:h})});\n\n// fullpage\ntinymce.PluginManager.add(\"fullpage\",function(a){function b(){var b=c();a.windowManager.open({title:\"Document properties\",data:b,defaults:{type:\"textbox\",size:40},body:[{name:\"title\",label:\"Title\"},{name:\"keywords\",label:\"Keywords\"},{name:\"description\",label:\"Description\"},{name:\"robots\",label:\"Robots\"},{name:\"author\",label:\"Author\"},{name:\"docencoding\",label:\"Encoding\"}],onSubmit:function(a){d(tinymce.extend(b,a.data))}})}function c(){function b(a,b){var c=a.attr(b);return c||\"\"}var c,d,f=e(),g={};return g.fontface=a.getParam(\"fullpage_default_fontface\",\"\"),g.fontsize=a.getParam(\"fullpage_default_fontsize\",\"\"),c=f.firstChild,7==c.type&&(g.xml_pi=!0,d=/encoding=\"([^\"]+)\"/.exec(c.value),d&&(g.docencoding=d[1])),c=f.getAll(\"#doctype\")[0],c&&(g.doctype=\"\"),c=f.getAll(\"title\")[0],c&&c.firstChild&&(g.title=c.firstChild.value),k(f.getAll(\"meta\"),function(a){var b,c=a.attr(\"name\"),d=a.attr(\"http-equiv\");c?g[c.toLowerCase()]=a.attr(\"content\"):\"Content-Type\"==d&&(b=/charset\\s*=\\s*(.*)\\s*/gi.exec(a.attr(\"content\")),b&&(g.docencoding=b[1]))}),c=f.getAll(\"html\")[0],c&&(g.langcode=b(c,\"lang\")||b(c,\"xml:lang\")),g.stylesheets=[],tinymce.each(f.getAll(\"link\"),function(a){\"stylesheet\"==a.attr(\"rel\")&&g.stylesheets.push(a.attr(\"href\"))}),c=f.getAll(\"body\")[0],c&&(g.langdir=b(c,\"dir\"),g.style=b(c,\"style\"),g.visited_color=b(c,\"vlink\"),g.link_color=b(c,\"link\"),g.active_color=b(c,\"alink\")),g}function d(b){function c(a,b,c){a.attr(b,c?c:void 0)}function d(a){g.firstChild?g.insert(a,g.firstChild):g.append(a)}var f,g,h,j,m,n=a.dom;f=e(),g=f.getAll(\"head\")[0],g||(j=f.getAll(\"html\")[0],g=new l(\"head\",1),j.firstChild?j.insert(g,j.firstChild,!0):j.append(g)),j=f.firstChild,b.xml_pi?(m='version=\"1.0\"',b.docencoding&&(m+=' encoding=\"'+b.docencoding+'\"'),7!=j.type&&(j=new l(\"xml\",7),f.insert(j,f.firstChild,!0)),j.value=m):j&&7==j.type&&j.remove(),j=f.getAll(\"#doctype\")[0],b.doctype?(j||(j=new l(\"#doctype\",10),b.xml_pi?f.insert(j,f.firstChild):d(j)),j.value=b.doctype.substring(9,b.doctype.length-1)):j&&j.remove(),j=null,k(f.getAll(\"meta\"),function(a){\"Content-Type\"==a.attr(\"http-equiv\")&&(j=a)}),b.docencoding?(j||(j=new l(\"meta\",1),j.attr(\"http-equiv\",\"Content-Type\"),j.shortEnded=!0,d(j)),j.attr(\"content\",\"text/html; charset=\"+b.docencoding)):j&&j.remove(),j=f.getAll(\"title\")[0],b.title?(j?j.empty():(j=new l(\"title\",1),d(j)),j.append(new l(\"#text\",3)).value=b.title):j&&j.remove(),k(\"keywords,description,author,copyright,robots\".split(\",\"),function(a){var c,e,g=f.getAll(\"meta\"),h=b[a];for(c=0;c\"))}function e(){return new tinymce.html.DomParser({validate:!1,root_name:\"#document\"}).parse(i)}function f(b){function c(a){return a.replace(/<\\/?[A-Z]+/g,function(a){return a.toLowerCase()})}var d,f,h,l,m=b.content,n=\"\",o=a.dom;if(!b.selection&&!(\"raw\"==b.format&&i||b.source_view&&a.getParam(\"fullpage_hide_in_source_view\"))){0!==m.length||b.source_view||(m=tinymce.trim(i)+\"\\n\"+tinymce.trim(m)+\"\\n\"+tinymce.trim(j)),m=m.replace(/<(\\/?)BODY/gi,\"<$1body\"),d=m.indexOf(\"\",d),i=c(m.substring(0,d+1)),f=m.indexOf(\"\\n\"),h=e(),k(h.getAll(\"style\"),function(a){a.firstChild&&(n+=a.firstChild.value)}),l=h.getAll(\"body\")[0],l&&o.setAttribs(a.getBody(),{style:l.attr(\"style\")||\"\",dir:l.attr(\"dir\")||\"\",vLink:l.attr(\"vlink\")||\"\",link:l.attr(\"link\")||\"\",aLink:l.attr(\"alink\")||\"\"}),o.remove(\"fullpage_styles\");var p=a.getDoc().getElementsByTagName(\"head\")[0];n&&(o.add(p,\"style\",{id:\"fullpage_styles\"},n),l=o.get(\"fullpage_styles\"),l.styleSheet&&(l.styleSheet.cssText=n));var q={};tinymce.each(p.getElementsByTagName(\"link\"),function(a){\"stylesheet\"==a.rel&&a.getAttribute(\"data-mce-fullpage\")&&(q[a.href]=a)}),tinymce.each(h.getAll(\"link\"),function(a){var b=a.attr(\"href\");q[b]||\"stylesheet\"!=a.attr(\"rel\")||o.add(p,\"link\",{rel:\"stylesheet\",text:\"text/css\",href:b,\"data-mce-fullpage\":\"1\"}),delete q[b]}),tinymce.each(q,function(a){a.parentNode.removeChild(a)})}}function g(){var b,c=\"\",d=\"\";return a.getParam(\"fullpage_default_xml_pi\")&&(c+='\\n'),c+=a.getParam(\"fullpage_default_doctype\",\"\"),c+=\"\\n\\n\\n\",(b=a.getParam(\"fullpage_default_title\"))&&(c+=\"\"+b+\"\\n\"),(b=a.getParam(\"fullpage_default_encoding\"))&&(c+='\\n'),(b=a.getParam(\"fullpage_default_font_family\"))&&(d+=\"font-family: \"+b+\";\"),(b=a.getParam(\"fullpage_default_font_size\"))&&(d+=\"font-size: \"+b+\";\"),(b=a.getParam(\"fullpage_default_text_color\"))&&(d+=\"color: \"+b+\";\"),c+=\"\\n\\n\"}function h(b){b.selection||b.source_view&&a.getParam(\"fullpage_hide_in_source_view\")||(b.content=tinymce.trim(i)+\"\\n\"+tinymce.trim(b.content)+\"\\n\"+tinymce.trim(j))}var i,j,k=tinymce.each,l=tinymce.html.Node;a.addCommand(\"mceFullPageProperties\",b),a.addButton(\"fullpage\",{title:\"Document properties\",cmd:\"mceFullPageProperties\"}),a.addMenuItem(\"fullpage\",{text:\"Document properties\",cmd:\"mceFullPageProperties\",context:\"file\"}),a.on(\"BeforeSetContent\",f),a.on(\"GetContent\",h)});\n\n}(this);\n\ndefine(\"tinymce\", [\"jquery\"], (function (global) {\n return function () {\n var ret, fn;\n fn = function () {\n this.tinyMCE.DOM.events.domLoaded = true;\n return this.tinyMCE;\n };\n ret = fn.apply(global, arguments);\n return ret || global.tinyMCE;\n };\n}(this)));\n\n","define('modules/common/toggle-switch-directive',['angular'], function (angular) {\n\n return angular.module('bl.toggle-switch', [])\n .directive('toggleSwitch', function () {\n return {\n restrict: 'E',\n scope: { value:'=', text1: '=', text2: '=', text3:'=', text4:'=', disableToggle: '=' },\n templateUrl: '/js/modules/common/toggle-switch.tpl.html'\n };\n });\n});\n","define('modules/contact/modals/request-payment-information-ctrl',['./../module', 'angular', 'underscore', 'moment'], function(module, angular, _, moment) {\n 'use strict';\n\n module.controller('RequestPaymentInformationCtrl', function($scope, $filter, $q, $modalInstance, $timeout, $state, $window, $stateParams, $translate, $interval, Account, AppLicense, EmailTemplate, SMSTemplate, TransactionPaymentsModalService, SMS, Enums, Email, User, MergeFields, ContactUpdateRequest, CompanySetting, alerts, modalService, companyProfile, emailTemplates, smsTemplates, twilioSettings, contact, posSettings, paymentPlans) {\n\n $scope.twilioSettings = twilioSettings;\n $scope.request = { sendEmail: false, sendSms: false, entityId: null, text3: $translate.instant('common.contact'), text4: $translate.instant('payment-plans.payment-plan'), updatePaymentPlan: false, allowedToSendEmail: true };\n $scope.email = {};\n $scope.sms = {};\n\n initPaymentPlans($scope);\n\n $scope.sent = {\n email: false,\n sms: false\n };\n\n $scope.hasAllStripeSettings = TransactionPaymentsModalService.hasAllStripeSettings(posSettings);\n $scope.hasAllChargeItProSettings = TransactionPaymentsModalService.hasAllChargeItProSettings(posSettings);\n $scope.hasAllFullSteamSettings = TransactionPaymentsModalService.hasAllFullSteamSettings(posSettings);\n var licenseHasPortalAccess = AppLicense.get()[\"clientPortalAccess\"];\n var licenseStatus = AppLicense.get()[\"status\"];\n $scope.request.allowedToSendEmail = licenseStatus === 'A';\n\n $scope.onlinePaymentAccess = licenseHasPortalAccess || $scope.hasAllFullSteamSettings || $scope.hasAllChargeItProSettings || $scope.hasAllStripeSettings;\n\n var paymentInfoRequestMergeFields = _.where(MergeFields, { paymentInfoRequest: true });\n\n buildTemplates(emailTemplates, smsTemplates);\n\n $scope.installPaymentInfoTemplates = function() {\n Account.installPaymentInfoTemplates(function() {\n var emailTemplatePromise = EmailTemplate.query({ filterObject: { status: Enums.statuses.active.value }});\n var smsTemplatePromise = SMSTemplate.query({ filterObject: { status: Enums.statuses.active.value }});\n\n $q.all([emailTemplatePromise, smsTemplatePromise]).then(function(resources) {\n if(resources && resources.length) {\n buildTemplates(resources[0], resources[1]);\n alerts.push('alerts.settings.account.successfully-installed-payment-info-templates');\n }\n });\n });\n };\n\n $scope.state = {\n isContactChosen: false\n };\n\n $scope.existingContact = {\n contactName: null\n };\n\n var chosenContact;\n\n $scope.chooseContact = function(contact) {\n if(contact) {\n $scope.state.isContactChosen = true;\n $scope.contact = {};\n\n $scope.existingContact.contactName = contact.firstName + \" \" + (contact.lastName || '');\n\n angular.extend($scope.contact, contact);\n\n chosenContact = angular.copy($scope.contact);\n }\n };\n\n $scope.unselectContact = function() {\n chosenContact = undefined;\n delete $scope.contact;\n\n $scope.existingContact.contactName = null;\n\n $scope.state.isContactChosen = false;\n $scope.request.sendEmail = false;\n $scope.request.sendSms = false;\n };\n\n $scope.chooseContact(contact);\n\n $scope.senders = [\n {\n email: companyProfile.emailAddress,\n name: companyProfile.name,\n id: companyProfile.id\n },\n {\n email: User.emailAddress,\n name: User.firstName + ' ' + User.lastName,\n id: User.id\n }\n ];\n\n $scope.email.sender = $scope.senders[0];\n\n $scope.selectEmailTemplate = function(template) {\n $scope.selectedEmailTemplate = template ? template : null;\n $scope.email.message = template && template.body ? template.body : '';\n $scope.email.subject = template && template.subject ? template.subject : '';\n $scope.email.contentType = template && template.contentType ? template.contentType : 'text/html';\n };\n\n $scope.selectSmsTemplate = function(template) {\n $scope.selectedSmsTemplate = template ? template : null;\n $scope.sms.message = template && template.body ? template.body : '';\n };\n\n $scope.selectPaymentPlan = function(plan) {\n $scope.selectedPaymentPlan = plan ? plan : null;\n $scope.request.entityId = $scope.selectedPaymentPlan;\n };\n\n $scope.requestForPaymentInfo = function() {\n if(licenseStatus !== 'A') {\n $scope.request.sendEmail = false;\n }\n\n if(!$scope.request.updatePaymentPlan) {\n $scope.request.entityId = null;\n }\n\n //if payment plan and no payment plan selected request entity\n if($scope.request.updatePaymentPlan && !$scope.request.entityId) {\n // Error message, plan required...\n modalService.showMessage('alerts.request-payment.plan-required', 'modal-service.error');\n return false;\n }\n\n if(!$scope.contact) {\n // Error message, contact required...\n modalService.showMessage('alerts.request-payment.contact-required', 'modal-service.error');\n return false;\n }\n\n if(!$scope.request.sendEmail && !$scope.request.sendSms) {\n // Error message, Delivery Method Required\n modalService.showMessage('alerts.request-payment.delivery-method-required', 'modal-service.error');\n return false;\n }\n\n if($scope.request.sendEmail && !$scope.selectedEmailTemplate) {\n // Error message to please select a email template...\n modalService.showMessage('alerts.request-payment.email-template-required', 'modal-service.error');\n return false;\n }\n\n if($scope.request.sendSms && !$scope.selectedSmsTemplate) {\n // Error message to please select a sms template...\n modalService.showMessage('alerts.request-payment.sms-template-required', 'modal-service.error');\n return false;\n }\n\n var request = {\n requestEntityId: $scope.request.entityId,\n contactId: $scope.contact.id\n };\n\n ContactUpdateRequest.validateBeforeCreatingPaymentRequest(request, function (existingRequest) {\n if(existingRequest && existingRequest.id) {\n modalService.showConfirmation('contact.messages.request-again?', function () {\n createRequestAndSend(request);\n });\n } else {\n createRequestAndSend(request);\n }\n }, function (data, status) {\n ContactUpdateRequest.defaultErrorHandler(data, status);\n });\n };\n\n function sendMessages() {\n var email;\n if ($scope.request.sendEmail) {\n email = {\n recipientId: $scope.contact.id,\n recipientType: Email.CONTACT_TYPE,\n subject: $scope.email.subject,\n message: $scope.email.message,\n cc: $scope.email.cc,\n contentType: $scope.email.contentType,\n senderEmail: $scope.email.sender.email,\n senderEmployeeId: User.id,\n senderName: $scope.email.sender.name,\n recipientEmail: $scope.contact.emailAddress,\n recipientName: $scope.contact.firstName + ' ' + $scope.contact.lastName,\n status: Enums.statuses.sent.value,\n createdByUser: User.username,\n salesAgreementId: $scope.selectedAgreement ? $scope.selectedAgreement.id : null\n };\n }\n\n var sms;\n var smss = [];\n if ($scope.request.sendSms) {\n sms = {\n message: $scope.sms.message,\n toPhoneNumber: $scope.contact.mobilePhoneNumber,\n employeeId: User.id,\n fromPhoneNumber: twilioSettings.phoneNumber,\n contactId: $scope.contact.id,\n deliverOn: new Date(),\n status: Enums.statuses.sent.value,\n createdByUser: User.username,\n salesAgreementId: $scope.selectedAgreement ? $scope.selectedAgreement.id : null\n };\n\n smss.push(sms);\n }\n\n if($scope.request.sendEmail && $scope.request.sendSms) {\n $scope.sending = true;\n\n // send email and sms, close modal\n $q.all([\n Email.send(email),\n SMS.sendMultiple(smss)\n ]).then(function (responses) {\n $scope.sending = false;\n\n if (responses[0]) {\n $scope.sent.email = true;\n $scope.request.sendEmail = false;\n alerts.pushSuccess('alerts.contact.success-your-email-is-being-sent');\n }\n\n if (responses[1].errors.length) {\n alerts.pushError({\n key: 'alerts.contact.failed-sent-sms',\n params: {message: responses[1].errors[0].message}\n });\n } else if (responses[1].optedErrors.length) {\n alerts.pushError({\n key: 'alerts.contact.failed-sent-sms',\n params: {message: responses[1].optedErrors[0].message}\n });\n } else {\n $scope.sent.sms = true;\n $scope.request.sendSms = false;\n alerts.pushSuccess({\n key: 'alerts.contact.successfully-sent-sms',\n params: {number: responses[1].successes.length}\n });\n }\n\n if ($scope.sent.email && $scope.sent.sms) {\n $scope.$close();\n }\n\n }).catch(function (error) {\n console.log(error);\n $scope.sending = false;\n });\n } else if($scope.request.sendEmail) {\n $scope.sending = true;\n\n // send email, close modal\n Email.send(email, function (emailResult) {\n $scope.sending = false;\n alerts.pushSuccess('alerts.contact.success-your-email-is-being-sent');\n $scope.$close();\n\n }, function (err) {\n Email.defaultErrorHandler(err);\n $scope.sending = false;\n });\n } else if($scope.request.sendSms) {\n $scope.sending = true;\n\n // send, close, pass result\n var sendSMS = SMS.sendMultiple(smss);\n\n sendSMS.then(function (twilioResult) {\n $scope.sending = false;\n\n if (twilioResult.errors.length) {\n alerts.pushError({\n key: 'alerts.contact.failed-sent-sms',\n params: {message: twilioResult.errors[0].message}\n });\n } else if (twilioResult.optedErrors.length) {\n alerts.pushError({\n key: 'alerts.contact.failed-sent-sms',\n params: {message: twilioResult.optedErrors[0].message}\n });\n } else {\n alerts.pushSuccess({\n key: 'alerts.contact.successfully-sent-sms',\n params: {number: twilioResult.successes.length}\n });\n\n $scope.$close();\n }\n }, function (err) {\n SMS.defaultErrorHandler(err);\n $scope.sending = false;\n });\n }\n }\n\n function createRequestAndSend(request) {\n ContactUpdateRequest.requestPaymentInformationForContact(request, function () {\n sendMessages();\n }, function () {\n $scope.sending = false;\n });\n }\n\n function buildTemplates(emailTemps, smsTemps) {\n $scope.emailTemplates = [];\n $scope.smsTemplates = [];\n\n if(emailTemps && emailTemps.length) {\n _.each(paymentInfoRequestMergeFields, function(mergeField) {\n _.each(emailTemps, function(template) {\n if(template && template.body) {\n if(includesValue(template.body, mergeField.key)) {\n if($scope.emailTemplates.indexOf(template) === -1) {\n $scope.emailTemplates.push(template);\n }\n }\n }\n });\n });\n }\n\n if(smsTemps && smsTemps.length) {\n _.each(paymentInfoRequestMergeFields, function(mergeField) {\n _.each(smsTemps, function(template) {\n if(template && template.body) {\n if(includesValue(template.body, mergeField.key)) {\n if($scope.smsTemplates.indexOf(template) === -1) {\n $scope.smsTemplates.push(template);\n }\n }\n }\n });\n });\n }\n }\n\n function includesValue(container, value) {\n var returnValue = false;\n var pos = container.indexOf(value);\n if(pos >= 0) {\n returnValue = true;\n }\n return returnValue;\n }\n\n function initPaymentPlans($scope) {\n paymentPlans = _(paymentPlans).filter(function(plan) {\n return plan.status !== Enums.statuses.complete.value;\n });\n\n $scope.paymentPlans = _(paymentPlans).map(function (plan) {\n var trx = $filter('transactionTypeCode')(plan.trxTypeId, plan.status);\n plan.trxDescription = $translate.instant(trx) + ' #' + plan.trxNumber;\n return plan;\n });\n\n if(paymentPlans.length === 1) {\n $scope.request.text4 += ' ' + $scope.paymentPlans[0].trxDescription;\n }\n }\n\n $scope.$watch('request.updatePaymentPlan', function (value) {\n if(value && $scope.paymentPlans && $scope.paymentPlans.length === 1) {\n $scope.request.entityId = $scope.paymentPlans[0].id;\n $scope.selectedPaymentPlan = $scope.request.entityId;\n } else {\n $scope.request.entityId = null;\n }\n });\n\n $scope.gotoContact = function() {\n $scope.$close();\n $state.go('contact.personal_info', { id: $scope.contact.id });\n };\n\n });\n});\n\n","define('modules/dashboard/attention-items-ctrl',['./module', 'moment'], function (module, moment) {\n 'use strict';\n\n module.controller('AttentionItemsCtrl', function ($scope, $q, $translate, $rootScope, eventsBus, WaitList, Appointment, Task, Transaction, ReceivingVoucher, PurchaseOrder, CompanySetting, UtilsHelper, Enums, security, PaymentPlan) {\n $scope.attentionItems = [];\n\n /**\n * Init\n */\n\n var poSettings = null;\n initAttentionItems();\n\n var initResources = function (resources, indexes) {\n var incompleteAppts = resources[0];\n var pastDueTasks = resources[1];\n var listPendingSales = resources[2];\n var listPendingSOPastDueEventDate = resources[3];\n var listPendingROPastDue = resources[4];\n var listPendingWaitList = resources[5];\n var listPendingPaymentPlans = resources[6];\n var listErrorPaymentPlans = resources[7];\n var listLatePurchaseOrders = indexes.po ? resources[indexes.po] : {};\n\n if(incompleteAppts.total) {\n $scope.attentionItems.push({\n text: 'appointment.incomplete-past',\n count: incompleteAppts.total,\n url: '#/appointments/incomplete-past'\n });\n }\n\n if(pastDueTasks.total) {\n $scope.attentionItems.push({\n text: 'task.past-due',\n count: pastDueTasks.total,\n url: '#/tasks/past-due'\n });\n }\n\n if(listPendingSales.total) {\n $scope.attentionItems.push({\n text: 'transaction.pending-sales',\n count: listPendingSales.total,\n url: '#/transactions?typeId=1&status=P'\n });\n }\n\n if(listPendingSOPastDueEventDate.total) {\n $scope.attentionItems.push({\n text: 'transaction.pending-so-event-date-past-due',\n count: listPendingSOPastDueEventDate.total,\n url: '#/transactions?typeId=2&status=P&eventDateBefore=' + moment().format('YYYY-MM-DD')\n });\n }\n\n if(listPendingROPastDue.total) {\n $scope.attentionItems.push({\n text: 'transaction.pending-receiving-vouchers',\n count: listPendingROPastDue.total,\n url: '#/receiving-vouchers?status=P'\n });\n }\n\n if(listLatePurchaseOrders && listLatePurchaseOrders.total) {\n $scope.attentionItems.push({\n text: 'purchase-order.late-purchase-orders',\n count: listLatePurchaseOrders.total,\n url: '#/purchase-orders/past-ship-date?shipDateBefore=' + moment().subtract(UtilsHelper.getDaysFromWeeks(poSettings, CompanySetting.PO_PENDING_PO_PAST_SHIPPING_WINDOW), 'days').format('YYYY-MM-DD')\n });\n }\n\n if(listPendingWaitList && listPendingWaitList.total) {\n $scope.attentionItems.push({\n text: 'wait-list.pending-for-today',\n count: listPendingWaitList.total,\n url: '#/wait-list?startDateTime=' + moment().startOf('day').format() + '&endDateTime=' + moment().endOf('day').format()\n });\n }\n\n if(listPendingPaymentPlans && listPendingPaymentPlans.total) {\n $scope.attentionItems.push({\n text: 'payment-plans.payment-plan-installment-due',\n count: listPendingPaymentPlans.total,\n url: '#/payment-plans?status=A&autoPayFlag=N&installmentDateBefore=' + moment().startOf('day').format('YYYY-MM-DD')\n });\n }\n\n if(listErrorPaymentPlans && listErrorPaymentPlans.total) {\n $scope.attentionItems.push({\n text: 'payment-plans.error-payment-plans',\n count: listErrorPaymentPlans.total,\n url: '#/payment-plans?status=' + Enums.statuses.pending.value + '&installmentStatus=' + Enums.statuses.error.value\n });\n }\n };\n\n function initAttentionItems() {\n CompanySetting.getPurchasingSettings(init, init);\n }\n\n function init(settings) {\n poSettings = settings;\n var indexes = { po: null };\n var incompleteApptsPromise = Appointment.incompletePastAppointments();\n var pastDueTasksPromise = Task.pastDueTasks();\n var listPendingSalesPromise = Transaction.listPendingSales();\n var listPendingSOPastDueEventDatePromise = Transaction.listPendingSOPastDueEventDate();\n var listPendingROPastDuePromise = ReceivingVoucher.listPendingROPastDue();\n var listLatePurchaseOrdersPromise = PurchaseOrder.pastShipDatePOs(settings);\n var listPendingWaitListTodayPromise = WaitList.query({ filterObject:{ status:Enums.statuses.pending.value, startDateTime: moment().startOf('day').format(), endDateTime: moment().endOf('day').format() }});\n var listPendingPaymentPlansPromise = PaymentPlan.query({ filterObject:{ autoPayFlag: \"N\", includePreviousAndNextInstallments: true, status: Enums.statuses.active.value, installmentDateBefore: moment().startOf('day').format('YYYY-MM-DD') }});\n var listErrorPaymentPlansPromise = PaymentPlan.query({ filterObject:{ status: Enums.statuses.pending.value, installmentStatus: Enums.statuses.error.value }});\n\n var promises = [incompleteApptsPromise, pastDueTasksPromise, listPendingSalesPromise, listPendingSOPastDueEventDatePromise, listPendingROPastDuePromise, listPendingWaitListTodayPromise, listPendingPaymentPlansPromise, listErrorPaymentPlansPromise];\n\n if(UtilsHelper.getDaysFromWeeks(poSettings, CompanySetting.PO_PENDING_PO_PAST_SHIPPING_WINDOW) !== 1) {\n indexes.po = promises.length;\n promises.push(listLatePurchaseOrdersPromise);\n }\n\n $q.all(promises).then(function(results) {\n initResources(results, indexes);\n });\n }\n\n });\n});\n\n","define('modules/resources/appointment-block',['angular', './backend-resource'], function (angular) {\n 'use strict';\n\n return angular.module('bl.resources.appointment-block', ['bl.resources.backend-resource'])\n .factory('AppointmentBlock', function (backendResource, DateTimeTzService, $http) {\n\n var resource = backendResource('appointmentBlocks', true);\n\n /**\n *\n * @param appointmentBlockId - the id of the block to find the appointment types for\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getAppointmentTypesForBlock = function (appointmentBlockId, successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getAppointmentTypesForBlock/' + appointmentBlockId, null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n *\n * @param appointmentBlockId - the id of the block to find the appointment types for\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getTypesForBlock = function (appointmentBlockId, successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getAppointmentTypesForBlock/' + appointmentBlockId, null);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n /**\n *\n * @param request\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.addTypesForBlock = function (request, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/addAppointmentTypesForBlock', request);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n *\n * @param dayOfWeekId - the id of the day that we want to delete the blocks for\n * @param fittingRoomId\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.removeBlocksForDayOfWeek = function (dayOfWeekId, fittingRoomId, successcb, errorcb) {\n var httpPromise = $http.delete(resource.url + '/deleteForDayOfWeek/' + dayOfWeekId + '/' + fittingRoomId);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n * @param fittingRoomId\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.deleteAllBlocksForFittingRoom = function (fittingRoomId, successcb, errorcb) {\n var httpPromise = $http.delete(resource.url + '/deleteAllBlocksForFittingRoom/' + fittingRoomId);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n * @param fittingRoomId\n * @param blockIds\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.bulkDelete = function (fittingRoomId, blockIds, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/bulkDelete/' + fittingRoomId, blockIds);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n /**\n * @param blockIds\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.bulkDeleteByIds = function (blockIds, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/bulkDeleteByIds/', blockIds);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n /**\n * @param blockIds\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getAppointmentBlockTypes = function (blockIds, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/getAppointmentBlockTypes', blockIds);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n /**\n * @param request\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.deleteAppointmentBlockType = function (request, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/deleteAppointmentBlockType', request);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n *\n * @param blockId\n * @param typeId\n * @param successcb\n * @param errorcb\n * @returns {*}\n */\n resource.getAppointmentBlockType = function (blockId, typeId, successcb, errorcb) {\n var httpPromise = $http.get(resource.url + '/getAppointmentBlockType/' + blockId + '/' + typeId);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n /**\n *\n * @param filterObj\n * @param successcb\n * @param errorcb\n * @returns {*} ListResultModel\n */\n resource.listResultModel = function(filterObj, successcb, errorcb) {\n var params = {};\n\n if(filterObj && filterObj.filterObject) {\n params = angular.isObject(filterObj.filterObject) ? JSON.stringify(filterObj.filterObject) : {};\n\n // if(params && params.startTime) {\n // params.startTime = DateTimeTzService.formatTime(params.startTime);\n // }\n\n // if(params && params.endTime) {\n // params.endTime = DateTimeTzService.formatTime(params.endTime);\n // }\n // 11 -> 11:00am 11:00\n }\n\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.post(resource.url + '/listResultModel?' + queryParameters.join('&'), params);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n return resource;\n });\n});\n\n","define('modules/settings/fitting-room/events/setup-event-blocks-ctrl',[\n 'angular',\n 'underscore',\n 'moment',\n '../../../common/enums-service',\n '../../../modal/modal-service',\n '../../../common/filters',\n '../../../resources/fitting-room',\n '../../../resources/appointment-block-event',\n '../../../calendar/fullcalendar-helper-service'\n], function (angular, _, moment) {\n 'use strict';\n\n return angular.module('bl.settings.fitting-room.setup-event-blocks', [\n 'bl.enums',\n 'bl.filters',\n 'bl.resources.appointment-block-event',\n 'bl.resources.fitting-room',\n 'bl.modal'\n ]).controller('FittingRoomEventBlockSetupCtrl', function ($scope, $controller, $modal, $translate, $locale, $q, User, alerts, FittingRoomService, FittingRoom, FittingRoomAppointmentType, AppointmentBlockEvent, fittingRoomEvent, fittingRooms, appt_types, Enums, modalService, FullcalendarHelper) {\n\n angular.extend(this, $controller('SearchBlockCtrl', {\n $scope: $scope,\n headers:[],\n modelView: 'blocks',\n Resource: AppointmentBlockEvent,\n fittingRoom: null,\n fittingRoomEvent: fittingRoomEvent,\n appt_types: appt_types,\n isModal: true,\n isEvent: true\n }));\n\n /**\n * Initialize Default Variables\n */\n\n $scope.isOpen = true;\n $scope.fittingRoomEvent = fittingRoomEvent;\n\n function fittingRoomEventDayOfWeek(event) {\n var dayOfWeeks = [];\n if(event.dayOfWeek) {\n dayOfWeeks.push(event.dayOfWeek);\n } else {\n var days = moment(event.endDate).diff(event.startDate, 'days') + 1;\n if(days >= 7) {\n dayOfWeeks = [1, 2, 3, 4, 5, 6, 7];\n } else {\n for(var i = 0; i < days; i++) {\n var date = moment(event.startDate).add(i, 'd').toDate();\n dayOfWeeks.push(moment(date).weekday() + 1);\n }\n }\n }\n\n return dayOfWeeks;\n }\n\n var rooms = mapFittingRooms(fittingRoomEvent, fittingRooms);\n\n var bookMethodTypes = {\n first: '' + $translate.instant('enums.booking-methods.first-available') + '',\n blocks: '' + $translate.instant('enums.booking-methods.blocks') + ''\n };\n\n rooms = _(rooms).map(function(room) {\n room.type = room.bookingMethodId === 1 ? bookMethodTypes.blocks : bookMethodTypes.first;\n return room;\n });\n\n $scope.fittingRooms = rooms;\n $scope.fitting_rooms = angular.copy(rooms);\n\n $scope.appt_types = angular.copy(appt_types);\n $scope.block = initNewBlock($scope.fittingRoomEvent, $scope.appt_types);\n $scope.eventDays = fittingRoomEventDayOfWeek(fittingRoomEvent);\n $scope.days = FullcalendarHelper.initializeDaysChecked();\n $scope.days = mapDays($scope.days, $scope.eventDays);\n\n $scope.initialValues = { dayOfWeek: '', includeAppointmentTypeDetails: true, appointmentTypes: [], fittingRooms: [], fittingRoomEventId: fittingRoomEvent.id };\n $scope.formValues = angular.copy($scope.initialValues);\n\n /**\n * Add Fitting Room Block Methods\n */\n\n $scope.onAddBlock = _.debounce(function() {\n var block = _.omit($scope.block, 'appointmentTypeId');\n var days = _($scope.days).where({ isChecked: true, isDisabled: false });\n\n var savedPromises = [];\n _(days).each(function(d) {\n _(block.fittingRooms).each(function(room) {\n var clonedBlock = _(block).clone();\n clonedBlock.dayOfWeek = d.day;\n clonedBlock.fittingRoomId = room.id;\n savedPromises.push(clonedBlock.$save());\n });\n });\n\n $q.all(savedPromises).then(initBlock);\n }, 800, true);\n\n var initBlock = function() {\n $scope.runSearch();\n $scope.block.startTime = $scope.block.endTime;\n $scope.onStartTimeChange();\n };\n\n function initNewBlock(fittingRoomEvent, types) {\n return new AppointmentBlockEvent({\n appointmentTypeId: types && types.length ? types[0].id: null,\n fittingRoomEventId: fittingRoomEvent && fittingRoomEvent.id\n });\n }\n\n function mapFittingRooms(event, rooms) {\n var array = [];\n _(event.items).each(function(item) {\n var room = _(rooms).findWhere({ id: item.fittingRoomId });\n if(room && room.id) {\n array.push(room);\n }\n });\n return array;\n }\n\n function mapDays(days, eventDays) {\n _(days).each(function(value, key) {\n days[key].isDisabled = !_.contains(eventDays, days[key].day);\n });\n\n return days;\n }\n\n $scope.onStartTimeChange = function() {\n FittingRoomService.blocks.setEndTime($scope.block, $scope.appt_types);\n };\n\n $scope.onAppointmentTypeChange = function(data) {\n console.log('setup ctrl', data);\n };\n\n $scope.isValid = function(block) {\n return FittingRoomService.blocks.isValid(block, $scope.days);\n };\n\n $scope.isChecked = function(days) {\n return _(days).where({ isChecked: true }).length > 0;\n };\n\n $scope.clearAll = function() {\n $scope.days = FullcalendarHelper.initializeDaysChecked();\n $scope.days = mapDays($scope.days, $scope.eventDays);\n };\n\n $scope.getDayOfWeek = function(day) {\n return $translate.instant('settings.day-of-week.' + (day - 1));\n };\n\n /**\n * Blocks Search Methods\n */\n\n $scope.runSearch = function() {\n search();\n };\n\n function search() {\n AppointmentBlockEvent.listResultModel($scope.buildReportsObject(), function(resultModel) {\n $scope.updateResults(resultModel);\n });\n }\n\n /**\n * Watchers\n */\n\n var ignoreFirst = true;\n $scope.$watch('block.appointmentTypes', function() {\n if(ignoreFirst) {\n ignoreFirst = false;\n return;\n }\n\n $scope.onStartTimeChange();\n });\n\n });\n});\n\n","define('modules/settings/fitting-room/blocks/add-block-modal-ctrl',['angular', 'underscore', 'moment', '../module'], function (angular, _, moment, module) {\n 'use strict';\n module.controller('AddBlockModalCtrl', function ($scope, $locale, $q, modalService, FittingRoomService, FullcalendarHelper, AppointmentBlock, AppointmentBlockEvent, fittingRoom, fittingRoomEvent, appt_types, modelView) {\n\n $scope.appt_types = angular.copy(appt_types);\n $scope.fittingRoom = fittingRoom;\n $scope.fittingRoomEvent = fittingRoomEvent;\n $scope.block = initNewBlock($scope.fittingRoom, $scope.fittingRoomEvent, $scope.appt_types);\n $scope.days = FullcalendarHelper.initializeDaysChecked();\n\n /**\n * Handlers\n */\n\n $scope.onAddBlock = _.debounce(function () {\n var block = _.omit($scope.block, 'appointmentTypeId');\n\n if(FittingRoomService.blocks.isStartEndTimeValid(block, false)) {\n modalService.showMessageStaticModal('settings.employee.message.enter-validate-start-and-end-times', 'settings.employee.message.ooops');\n return;\n }\n\n var days = _($scope.days).where({ isChecked: true });\n\n var savedPromises = [];\n _(days).each(function(d) {\n var clonedBlock = _(block).clone();\n clonedBlock.dayOfWeek = d.day;\n savedPromises.push(clonedBlock.$save());\n });\n\n $q.all(savedPromises).then(closeModal);\n }, 800, true);\n\n $scope.onStartTimeChange = function() {\n FittingRoomService.blocks.setEndTime($scope.block, $scope.appt_types);\n };\n\n $scope.isValid = function(block) {\n return FittingRoomService.blocks.isValid(block, $scope.days);\n };\n\n $scope.isChecked = function(days) {\n return _(days).where({ isChecked: true }).length > 0;\n };\n\n $scope.clearAll = function() {\n $scope.days = FullcalendarHelper.initializeDaysChecked();\n };\n\n /**\n * Helpers\n */\n\n function closeModal(results) {\n $scope.$close({ blocks: results });\n }\n\n function initNewBlock(fittingRoom, fittingRoomEvent, types) {\n if(fittingRoomEvent && fittingRoomEvent.id) {\n return new AppointmentBlockEvent({\n appointmentTypeId: types && types.length ? types[0].id: null,\n fittingRoomId: fittingRoom && fittingRoom.id,\n fittingRoomEventId: fittingRoomEvent.id\n });\n } else {\n return new AppointmentBlock({\n appointmentTypeId: types && types.length ? types[0].id: null,\n fittingRoomId: fittingRoom && fittingRoom.id\n });\n }\n }\n\n /**\n * Watchers\n */\n\n var ignoreFirst = true;\n $scope.$watch('block.appointmentTypes', function() {\n if(ignoreFirst) {\n ignoreFirst = false;\n return;\n }\n\n $scope.onStartTimeChange();\n });\n });\n});\n\n","define('modules/resources/reports',['angular', 'moment', './backend-resource'], function (angular, moment) {\n 'use strict';\n\n angular.module('bl.resources.reports', ['bl.resources.backend-resource', 'bl.security.service'])\n\n .factory('Reports', function (backendResource, $http, $window, security, PrintHelper) {\n\n var resource = backendResource('reports');\n\n function handleExportOrPrintPDF(print, url) {\n if(print) {\n PrintHelper.printPDF(url);\n } else {\n $window.open(url);\n }\n }\n\n function encodeReportsCriteria(obj) {\n var encodedString = '';\n for(var key in obj) {\n if(encodedString.length !== 0) {\n encodedString += '&';\n }\n\n encodedString += key + '=' + encodeURIComponent(obj[key]);\n }\n return encodedString;\n }\n\n function addPaginationElements(criteria, reportsObj) {\n // allows 0 value\n if (typeof reportsObj.page !== 'undefined') {\n criteria.page = reportsObj.page;\n }\n if (reportsObj.size) {\n criteria.size = reportsObj.size;\n }\n if (reportsObj.sortField) {\n criteria.sortField = reportsObj.sortField;\n }\n if (reportsObj.sortDirection) {\n criteria.sortDirection = reportsObj.sortDirection;\n }\n }\n\n function buildReportsCriteria(reportsObj) {\n var criteria = {};\n if (reportsObj) {\n addPaginationElements(criteria, reportsObj);\n if (reportsObj.criteria.retailerId) {\n criteria.retailerId = reportsObj.criteria.retailerId;\n }\n if (reportsObj.criteria.departmentId) {\n criteria.departmentId = reportsObj.criteria.departmentId;\n }\n if (reportsObj.criteria.taxCodeId) {\n criteria.taxCodeId = reportsObj.criteria.taxCodeId;\n }\n if (reportsObj.criteria.trxTypeId) {\n criteria.trxTypeId = reportsObj.criteria.trxTypeId;\n }\n if (reportsObj.criteria.vendorId) {\n criteria.vendorId = reportsObj.criteria.vendorId;\n }\n if (reportsObj.criteria.appointmentTypeId) {\n criteria.appointmentTypeId = reportsObj.criteria.appointmentTypeId;\n }\n if (reportsObj.criteria.appointmentTypeIds) {\n criteria.appointmentTypeIds = reportsObj.criteria.appointmentTypeIds;\n }\n if (reportsObj.criteria.vendorIds) {\n criteria.vendorIds = reportsObj.criteria.vendorIds;\n }\n if (reportsObj.criteria.departmentIds) {\n criteria.departmentIds = reportsObj.criteria.departmentIds;\n }\n if (reportsObj.criteria.employeeId !== undefined) {\n criteria.employeeId = reportsObj.criteria.employeeId;\n }\n if (reportsObj.criteria.taskTypeId) {\n criteria.taskTypeId = reportsObj.criteria.taskTypeId;\n }\n if (reportsObj.criteria.taskStatus) {\n criteria.taskStatus = reportsObj.criteria.taskStatus;\n }\n if (reportsObj.criteria.year) {\n criteria.year = reportsObj.criteria.year;\n }\n if (reportsObj.criteria.month !== undefined) {\n criteria.month = reportsObj.criteria.month;\n }\n if (reportsObj.criteria.startDate) {\n criteria.startDate = moment(reportsObj.criteria.startDate).format('YYYY-MM-DD');\n }\n if (reportsObj.criteria.endDate) {\n criteria.endDate = moment(reportsObj.criteria.endDate).format('YYYY-MM-DD');\n }\n if (reportsObj.criteria.status) {\n criteria.status = reportsObj.criteria.status;\n }\n if (reportsObj.criteria.name) {\n criteria.name = reportsObj.criteria.name;\n }\n if (reportsObj.criteria.eventTypeId) {\n criteria.eventTypeId = reportsObj.criteria.eventTypeId;\n }\n if (reportsObj.criteria.eventType) {\n criteria.eventType = reportsObj.criteria.eventType;\n }\n if (reportsObj.criteria.poStartDate) {\n criteria.poStartDate = moment(reportsObj.criteria.poStartDate).format('YYYY-MM-DD');\n }\n if (reportsObj.criteria.poEndDate) {\n criteria.poEndDate = moment(reportsObj.criteria.poEndDate).format('YYYY-MM-DD');\n }\n if (reportsObj.criteria.shipStartDate) {\n criteria.shipStartDate = moment(reportsObj.criteria.shipStartDate).format('YYYY-MM-DD');\n }\n if (reportsObj.criteria.shipEndDate) {\n criteria.shipEndDate = moment(reportsObj.criteria.shipEndDate).format('YYYY-MM-DD');\n }\n if (reportsObj.criteria.rvStartDate) {\n criteria.rvStartDate = moment(reportsObj.criteria.rvStartDate).format('YYYY-MM-DD');\n }\n if (reportsObj.criteria.rvEndDate) {\n criteria.rvEndDate = moment(reportsObj.criteria.rvEndDate).format('YYYY-MM-DD');\n }\n if (reportsObj.criteria.trxStartDate) {\n criteria.trxStartDate = moment(reportsObj.criteria.trxStartDate).format('YYYY-MM-DD');\n }\n if (reportsObj.criteria.trxEndDate) {\n criteria.trxEndDate = moment(reportsObj.criteria.trxEndDate).format('YYYY-MM-DD');\n }\n if(reportsObj.criteria.trxBalanceDueZeroDateStart) {\n criteria.trxBalanceDueZeroDateStart = moment(reportsObj.criteria.trxBalanceDueZeroDateStart).format('YYYY-MM-DD');\n }\n if(reportsObj.criteria.trxBalanceDueZeroDateEnd) {\n criteria.trxBalanceDueZeroDateEnd = moment(reportsObj.criteria.trxBalanceDueZeroDateEnd).format('YYYY-MM-DD');\n }\n if (reportsObj.criteria.itemStatus) {\n criteria.itemStatus = reportsObj.criteria.itemStatus;\n }\n if (reportsObj.criteria.trxStatus) {\n criteria.trxStatus = reportsObj.criteria.trxStatus;\n }\n if (reportsObj.criteria.completedStartDate) {\n criteria.completedStartDate = moment(reportsObj.criteria.completedStartDate).format('YYYY-MM-DD');\n }\n if (reportsObj.criteria.completedEndDate) {\n criteria.completedEndDate = moment(reportsObj.criteria.completedEndDate).format('YYYY-MM-DD');\n }\n if (reportsObj.criteria.methodId) {\n criteria.methodId = reportsObj.criteria.methodId;\n }\n if (reportsObj.criteria.methodIds) {\n criteria.methodIds = reportsObj.criteria.methodIds;\n }\n if (reportsObj.criteria.categoryId) {\n criteria.categoryId = reportsObj.criteria.categoryId;\n }\n if (reportsObj.criteria.methodCategoryId != -1) {\n criteria.methodCategoryId = reportsObj.criteria.methodCategoryId;\n }\n if (reportsObj.criteria.excludePickup) {\n criteria.excludePickup = reportsObj.criteria.excludePickup;\n }\n if (reportsObj.criteria.sampleFlag) {\n criteria.sampleFlag = reportsObj.criteria.sampleFlag;\n }\n if (reportsObj.criteria.orderType) {\n criteria.orderType = reportsObj.criteria.orderType;\n }\n if (reportsObj.criteria.physicalInventoryId) {\n criteria.physicalInventoryId = reportsObj.criteria.physicalInventoryId;\n }\n if (reportsObj.criteria.trxItemStatus) {\n criteria.trxItemStatus = reportsObj.criteria.trxItemStatus;\n }\n if (reportsObj.criteria.showVoidedPayments) {\n criteria.showVoidedPayments = reportsObj.criteria.showVoidedPayments;\n }\n if (reportsObj.criteria.registerId) {\n criteria.registerId = reportsObj.criteria.registerId;\n }\n if (reportsObj.criteria.templateId) {\n criteria.templateId = reportsObj.criteria.templateId;\n }\n if (reportsObj.criteria.attributeIds) {\n criteria.attributeIds = reportsObj.criteria.attributeIds;\n }\n if (reportsObj.criteria.hasItemBeenScanned) {\n criteria.hasItemBeenScanned = reportsObj.criteria.hasItemBeenScanned;\n }\n if (reportsObj.criteria.finishOption >= 0 && reportsObj.criteria.finishOption != null && reportsObj.criteria.finishOption !== undefined) {\n criteria.finishOption = reportsObj.criteria.finishOption;\n }\n if (reportsObj.criteria.finishOptionDepartmentId) {\n criteria.finishOptionDepartmentId = reportsObj.criteria.finishOptionDepartmentId;\n }\n if (reportsObj.criteria.evaluationType) {\n criteria.evaluationType = reportsObj.criteria.evaluationType;\n }\n if (reportsObj.criteria.hasSalePrice) {\n criteria.hasSalePrice = reportsObj.criteria.hasSalePrice;\n }\n if (reportsObj.criteria.receiveDate) {\n criteria.receiveDate = moment(reportsObj.criteria.receiveDate).format('YYYY-MM-DD');\n }\n if(reportsObj.criteria.syncRecordId) {\n criteria.syncRecordId = reportsObj.criteria.syncRecordId;\n }\n if (reportsObj.criteria.departmentBreakdown) {\n criteria.departmentBreakdown = reportsObj.criteria.departmentBreakdown;\n }\n if (reportsObj.criteria.dateType) {\n criteria.dateType = reportsObj.criteria.dateType;\n }\n if (reportsObj.criteria.triedOnFlag) {\n criteria.triedOnFlag = reportsObj.criteria.triedOnFlag;\n }\n if(reportsObj.criteria.showTipPaymentsOnly) {\n criteria.showTipPaymentsOnly = reportsObj.criteria.showTipPaymentsOnly;\n }\n if (reportsObj.criteria.fundedFlag) {\n criteria.fundedFlag = reportsObj.criteria.fundedFlag;\n }\n if (reportsObj.criteria.apptStatus) {\n criteria.apptStatus = reportsObj.criteria.apptStatus;\n }\n if(reportsObj.criteria.dashboard) {\n criteria.dashboard = reportsObj.criteria.dashboard;\n }\n if(reportsObj.criteria.paymentReceivedMethod) {\n criteria.paymentReceivedMethod = reportsObj.criteria.paymentReceivedMethod;\n }\n if(reportsObj.criteria.endOfDay) {\n criteria.endOfDay = reportsObj.criteria.endOfDay;\n }\n if(reportsObj.criteria.commissionLevelType) {\n criteria.commissionLevelType = reportsObj.criteria.commissionLevelType;\n }\n if(reportsObj.criteria.percentPaid >= 0 && reportsObj.criteria.percentPaid <= 100) {\n criteria.percentPaid = reportsObj.criteria.percentPaid;\n }\n if(reportsObj.criteria.paymentStatus) {\n criteria.paymentStatus = reportsObj.criteria.paymentStatus;\n }\n if (reportsObj.criteria.reason) {\n criteria.reason = reportsObj.criteria.reason;\n }\n if (reportsObj.criteria.type) {\n criteria.type = reportsObj.criteria.type;\n }\n if (reportsObj.criteria.requirePaging) {\n criteria.requirePaging = reportsObj.criteria.requirePaging;\n }\n }\n return criteria;\n }\n\n resource.fundingReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/blPayReports/fundingReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.newFundingReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/blPayReports/newFundingReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.newFundingReportExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/blPayReports/newFundingReport.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.fundingReportExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/blPayReports/fundingReport.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.appointmentStatusCountByType = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/endOfDayReports/appointmentStatusCountByType?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, false);\n };\n\n resource.endOfDayReportsOverView = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/endOfDayReports/endOfDayReportsOverView?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, false);\n };\n\n resource.autoReconcileOverView = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/endOfDayReports/autoReconcileOverView?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.tipItemJournal = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/blPayReports/tipItemJournal?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.tipItemJournalExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/blPayReports/tipItemJournal.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.platformFeeJournal = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/blPayReports/platformFeeJournal?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.platformFeeJournalExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/blPayReports/platformFeeJournal.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.preAuthPaymentJournal = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/blPayReports/preAuthPaymentJournal?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.preAuthPaymentJournalExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/blPayReports/preAuthPaymentJournal.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.tipReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/blPayReports/tipReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.tipReportExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/blPayReports/tipReport.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.blPayPaymentSearch = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/blPayReports/paymentSearch?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.blPayPaymentSearchExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/blPayReports/paymentSearch.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.nf525JetReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/nf525Reports/jetReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.nf525DailyReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/nf525Reports/dailyReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.nf525MonthlyReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/nf525Reports/monthlyReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.nf525FiscalYearReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/nf525Reports/fiscalYearReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.nf525TicketReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/nf525Reports/ticketReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.nf525TransactionReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/nf525Reports/transactionReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.nf525DuplicateReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/nf525Reports/duplicateReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.nf525InvoiceReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/nf525Reports/invoiceReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.nf525InvoiceSnapShotReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/nf525Reports/invoiceSnapShotReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.retrieveInvoiceDetails = function (documentId, success, error) {\n var httpPromise = $http.get(resource.url + \"/nf525Reports/retrieveInvoiceDetails/\" + documentId, null);\n return resource.thenFactoryMethod(httpPromise, success, error, false);\n };\n\n resource.qboSyncHistoryLog = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/auditLogs/qboSyncHistoryLog?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.qboSyncHistoryLogExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/auditLogs/qboSyncHistoryLog.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.smsHistoryLog = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/auditLogs/smsHistoryLog?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.smsHistoryLogExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/auditLogs/smsHistoryLog.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.emailHistoryLog = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/auditLogs/emailHistoryLog?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.emailHistoryLogExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/auditLogs/emailHistoryLog.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.registerHistoryLog = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/auditLogs/registerHistoryLog?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.registerHistoryLogExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/auditLogs/registerHistoryLog.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.cashDrawerHistoryLog = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/auditLogs/cashDrawerHistoryLog?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.cashDrawerHistoryLogExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/auditLogs/cashDrawerHistoryLog.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n \n resource.timesheet = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/associateReports/timeSheet?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.timesheetExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/associateReports/timeSheet.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.timePunchesByAssociate = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/associateReports/timePunchesByAssociate?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.timePunchesByAssociateExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/associateReports/timePunchesByAssociate.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.timeOffByAssociate = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/associateReports/timeOffByAssociate\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.timeOffByAssociateExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/associateReports/timeOffByAssociate.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.closingRatioAppointmentBased = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/associateReports/closingRatioAppointmentBased?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.closingRatioAppointmentBasedExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/associateReports/closingRatioAppointmentBased.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.closingRatioContactBased = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/associateReports/closingRatioContactBased?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.closingRatioContactBasedExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/associateReports/closingRatioContactBased.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.averageBudgetByMonth = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/contactReports/avgBudgetByMonth?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.averageBudgetByMonthExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/contactReports/avgBudgetByMonth.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.howHeardSummary = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/contactReports/howHeardSummary?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.howHeardSummaryExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/contactReports/howHeardSummary.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.howHeardEffectiveness = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/contactReports/howHeardEffectiveness?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.howHeardEffectivenessExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/contactReports/howHeardEffectiveness.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.salesPerHour = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/associateReports/salesPerHour?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.salesPerHourExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/associateReports/salesPerHour.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.salesPerformanceOverview = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/associateReports/salesPerformanceOverview?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, false);\n };\n\n resource.salesPerformance = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/associateReports/salesPerformance?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.salesPerformanceExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/associateReports/salesPerformance.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.commissionReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/associateReports/commissionReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.commissionReportExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/associateReports/commissionReport.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.commissionItemJournal = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/associateReports/commissionItemJournal?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.commissionItemJournalExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/associateReports/commissionItemJournal.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.eventDateSummary = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/contactReports/eventDateSummary?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.eventDateSummaryExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/contactReports/eventDateSummary.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.eventLocationSummary = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/contactReports/eventLocationSummary?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.eventLocationSummaryExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/contactReports/eventLocationSummary.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.appointmentCountByDay = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/activityReports/appointmentCountByDay?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.appointmentCountByDayExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/activityReports/appointmentCountByDay.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.appointmentCountByMonth = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/activityReports/appointmentCountByMonth?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.appointmentCountByMonthExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/activityReports/appointmentCountByMonth.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.appointmentCountBeforePurchase = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/activityReports/appointmentCountBeforePurchase?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.appointmentCountBeforePurchaseExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/activityReports/appointmentCountBeforePurchase.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.appointmentStatusCountByMonth = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/activityReports/appointmentStatusCountByMonth?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.appointmentStatusCountByMonthExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/activityReports/appointmentStatusCountByMonth.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.taskCountByMonth = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/activityReports/taskCountByMonth?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.taskCountByMonthExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/activityReports/taskCountByMonth.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.smartView = function (success, error) {\n var httpPromise = $http.get(resource.url + '/smartView/');\n return resource.thenFactoryMethod(httpPromise, success, error);\n };\n\n resource.smartViewExecute = function (success, error) {\n var httpPromise = $http.get(resource.url + '/smartView/execute');\n return resource.thenFactoryMethod(httpPromise, success, error);\n };\n\n /** Inventory Reports **/\n resource.itemsOnHand = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/merchandiseReports/itemsOnHand\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.itemsOnHandExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/merchandiseReports/itemsOnHand.' + type + '?token=' + token + \"&userName=\" + security.currentUser.username + \"&\" + crit + printParam);\n };\n\n resource.itemsOnOrder = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/merchandiseReports/itemsOnOrder?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.itemsOnOrderExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/merchandiseReports/itemsOnOrder.' + type + '?token=' + token + \"&userName=\" + security.currentUser.username + \"&\" + crit + printParam);\n };\n\n resource.itemsAwaitingPickup = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/merchandiseReports/itemsAwaitingPickup?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.itemsAwaitingPickupExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/merchandiseReports/itemsAwaitingPickup.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.itemsNotSold = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/merchandiseReports/itemsNotSold?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.itemsNotSoldExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/merchandiseReports/itemsNotSold.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.favoriteItemSummary = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/merchandiseReports/favoriteItemsSummary?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.favoriteItemSummaryExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/merchandiseReports/favoriteItemsSummary.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.alterationsPlanningReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/merchandiseReports/alterationsPlanningReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.alterationsPlanningReportExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/merchandiseReports/alterationsPlanningReport.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.operationsPlanningReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/merchandiseReports/operationsPlanningReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.operationsPlanningReportExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/merchandiseReports/operationsPlanningReport.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.physicalInventoryAdjustmentReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/merchandiseReports/physicalInventoryAdjustmentReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.physicalInventoryAdjustmentReportExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/merchandiseReports/physicalInventoryAdjustmentReport.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.preparationReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/merchandiseReports/preparationReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.preparationReportExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/merchandiseReports/preparationReport.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.salesReport = function (reportId, reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/salesReports/\" + reportId + \"?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.salesReportExport = function (reportId, reportsObj, type, print, userName) {\n var userParam = userName ? '&userName='+userName : '';\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/salesReports/'+reportId+'.' + type + '?token=' + token + \"&\" + crit + printParam + userParam);\n };\n\n /** Purchasing Reports **/\n resource.receivingReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/purchasingReports/receivingReport?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n\n resource.receivingReportExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/purchasingReports/receivingReport.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.receivingVoucherJournal = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/purchasingReports/receivingVoucherJournal?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.receivingVoucherJournalExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/purchasingReports/receivingVoucherJournal.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.purchaseOrderJournal = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/purchasingReports/purchaseOrderJournal?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.purchaseOrderJournalExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/purchasingReports/purchaseOrderJournal.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n resource.vatReport = function (reportsObj, success, error) {\n var httpPromise = $http.post(resource.url + \"/salesReports/vat?\", buildReportsCriteria(reportsObj));\n return resource.thenFactoryMethod(httpPromise, success, error, true);\n };\n resource.vatReportExport = function (reportsObj, type, print) {\n var printParam = print ? '&printMode=true' : '';\n\n var crit = encodeReportsCriteria(buildReportsCriteria(reportsObj));\n var token = encodeURIComponent(security.readCookie().token);\n handleExportOrPrintPDF(print, resource.url + '/salesReports/vat.' + type + '?token=' + token + \"&\" + crit + printParam);\n };\n\n\n return resource;\n });\n});\n\n","define('modules/notifications/index',[\n './notifications-service',\n './notifications-directive',\n './error-notification-ctrl'\n], function () {});\n\n","define('modules/contact-modal/wedding-registry-ctrl',['./../contact/module', 'angular', 'underscore', 'moment'], function (module, angular, _) {\n 'use strict';\n\n module.controller('ContactWeddingRegistryCtrl', function ($scope, $state, $modal, Enums, contact, event, posSettings, User, alerts, EventMember, EventItem, Sms, modalService, EmailService, TransactionPaymentsModalService) {\n $scope.enumStatuses = Enums.statuses;\n $scope.contact = contact;\n $scope.event = event;\n\n /**\n * Methods\n */\n\n $scope.getMemberItems = function (member) {\n if ($scope.eventItems) {\n var knowIds = [];\n var sortedItems = _.sortBy($scope.eventItems, function (item) {\n return item.createdDate;\n });\n\n return sortedItems.filter(function (item) {\n return item.eventMemberId == member.id\n // multiple eventItems can have same id, take onlyfirst\n && (knowIds.indexOf(item.id) == -1 && knowIds.push(item.id));\n });\n }\n };\n\n $scope.getSelectedItems = function () {\n var selectedItems = _.where($scope.eventItems, { selected: true });\n\n return selectedItems.map(function (item) {\n return _.omit(angular.copy(item), 'selected');\n });\n };\n\n $scope.getTrxType = function (trxTypeId) {\n return _.findWhere(Enums.trxTypes, { value: trxTypeId });\n };\n\n var typeState = {\n 1: 'transaction.sale',\n 2: 'transaction.specialOrder',\n 4: 'transaction.layaway'\n };\n\n $scope.createTrx = function (trxTypeId) {\n\n //validate the selected items\n var selectedItems = $scope.getSelectedItems();\n if (selectedItems.length === 0) {\n modalService.showMessage('contact.messages.select-at-least-one-item');\n return false;\n }\n\n //make sure that none of the event items have a transaction associated with them yet\n if (selectedItems.some(function (eventItem) {\n return eventItem.transactionId;\n })) {\n modalService.showMessage('contact.messages.selected-item-has-already-transaction-associated-unselect-it-and-try-again');\n return false;\n }\n\n //find the contactId of the event member so we can create the trx for them.\n var eventMemberId = null;\n var multipleEventMembers = false;\n _.each(selectedItems, function (eventItem) {\n\n if (eventMemberId && eventMemberId != eventItem.eventMemberId) {\n multipleEventMembers = true;\n } else {\n eventMemberId = eventItem.eventMemberId;\n }\n\n });\n\n if (!multipleEventMembers) {\n $scope.createTrxForMember(eventMemberId, trxTypeId);\n } else {\n //if there are multiple event members for 1 transaction, show a popup where the user can select the event contact\n $modal.open({\n templateUrl: 'js/modules/contact/modals/wedding-registry-multiple-member-select-modal.tpl.html',\n controller: 'WeddingRegistryMultipleMemberSelectModalCtrl',\n resolve: {\n eventMembers: function () {\n //add the bride to the event members\n var membersPlusBride = _.clone($scope.eventMembers);\n\n //add the bride\n membersPlusBride.push({\n id: $scope.contact.id,\n firstName: $scope.contact.firstName,\n lastName: $scope.contact.lastName,\n typeId: 'Event Contact'\n });\n\n return membersPlusBride;\n },\n trxTypeId: function () {\n return trxTypeId;\n },\n callback: function () {\n return $scope.createTrxForMember;\n }\n }\n });\n }\n };\n\n $scope.createTrxForMember = function (eventMemberId, trxTypeId) {\n var selectedItems = $scope.getSelectedItems();\n\n //there should only be 1, but let's make sure\n var eventMemberContactId = 0;\n if (eventMemberId === $scope.contact.id) {\n //if the event contact is the one the user wants to assign as the main contact on the trx\n eventMemberContactId = $scope.contact.id;\n } else {\n var eventMember = _.findWhere($scope.eventMembers, { id: eventMemberId });\n eventMemberContactId = eventMember.contactId;\n }\n\n EventItem.createTrx(trxTypeId, eventMemberContactId, $scope.contact.id, User.id, selectedItems, function (trx) {\n $state.go(typeState[trxTypeId], { id: trx.id, referrer: 'contact.registry', promptLeadAndItemAddOns: true });\n });\n };\n\n $scope.showSendModal = EmailService.showSendModal;\n\n $scope.createPOs = function () {\n var selectedItems = $scope.getSelectedItems();\n\n if (selectedItems.length === 0) {\n modalService.showMessage('contact.messages.select-at-least-one-item');\n return false;\n }\n\n //make sure that none of the event items have a transaction associated with them yet\n if (selectedItems.some(function (eventItem) {\n return !eventItem.transactionId;\n })) {\n modalService.showMessage('contact.messages.selected-item-does-not-have-transaction-associated-please-create-transaction-for-it');\n return false;\n }\n\n\n // make sure that none of the event items doesn't have a item status of 'W' <-- 'Awaiting Picking'\n if (selectedItems.some(function (eventItem) {\n return eventItem.trxLineItemStatus === 'W';\n })) {\n modalService.showMessage('contact.messages.selected-item-is-set-for-awaiting-pickup-please-change-status-for-it');\n return false;\n }\n\n EventItem.createPOs(User.id, 'true', _.pluck(selectedItems, 'trxLineItemId'), function (trxItems) {\n alerts.pushSuccess('alerts.contact.successfully-created-purchase-orders');\n _.each(trxItems, function (item) {\n var eventItem = _.findWhere($scope.eventItems, { id: item.eventItemId });\n if(!eventItem.purchaseOrderId) {\n eventItem.poLineItemConfNumber = item.poLineItemConfNumber;\n eventItem.poLineItemQuantity = item.poLineItemQuantity;\n eventItem.poLineItemSequenceNumber = item.poLineItemSequenceNumber;\n eventItem.purchaseOrderId = item.purchaseOrderId;\n eventItem.purchaseOrderItemId = item.purchaseOrderItemId;\n eventItem.purchaseOrderNumber = item.purchaseOrderNumber;\n eventItem.purchaseOrderShipDate = item.purchaseOrderShipDate;\n }\n });\n });\n };\n\n $scope.createQuote = function() {\n //validate the selected items\n var selectedItems = $scope.getSelectedItems();\n if (selectedItems.length === 0) {\n modalService.showMessage('contact.messages.select-at-least-one-item');\n return false;\n }\n\n //make sure that none of the event items have a transaction associated with them yet\n if (selectedItems.some(function (eventItem) {\n return eventItem.transactionId;\n })) {\n modalService.showMessage('contact.messages.selected-item-has-already-transaction-associated-unselect-it-and-try-again');\n return false;\n }\n\n //find the contactId of the event member so we can create the trx for them.\n var eventMemberId = null;\n var multipleEventMembers = false;\n _.each(selectedItems, function (eventItem) {\n\n if (eventMemberId && eventMemberId !== eventItem.eventMemberId) {\n multipleEventMembers = true;\n } else {\n eventMemberId = eventItem.eventMemberId;\n }\n\n });\n\n if(!multipleEventMembers) {\n $scope.createQuoteForMember(eventMemberId);\n\n } else {\n $modal.open({\n templateUrl: 'js/modules/contact/modals/wedding-registry-multiple-member-select-modal.tpl.html',\n controller: 'WeddingRegistryMultipleMemberSelectModalCtrl',\n resolve: {\n eventMembers: function () {\n //add the bride to the event members\n var membersPlusBride = _.clone($scope.eventMembers);\n\n //add the bride\n membersPlusBride.push({\n id: $scope.contact.id,\n firstName: $scope.contact.firstName,\n lastName: $scope.contact.lastName,\n typeId: 'Event Contact'\n });\n\n return membersPlusBride;\n },\n trxTypeId: function () {\n return null;\n },\n callback: function () {\n return $scope.createQuoteForMember;\n }\n }\n });\n }\n };\n\n $scope.createQuoteForMember = function(eventMemberId, typeId) {\n var selectedItems = $scope.getSelectedItems();\n\n //there should only be 1, but let's make sure\n var eventMemberContactId = 0;\n if (eventMemberId === $scope.contact.id) {\n //if the event contact is the one the user wants to assign as the main contact on the trx\n eventMemberContactId = $scope.contact.id;\n } else {\n var eventMember = _.findWhere($scope.eventMembers, { id: eventMemberId });\n eventMemberContactId = eventMember.contactId;\n }\n\n EventItem.createQuote(eventMemberContactId, $scope.contact.id, User.id, selectedItems, function (quote) {\n $state.go('quote.edit', { id: quote.id, referrer: 'contact.registry', promptLeadAndItemAddOns: true });\n });\n };\n\n $scope.registerItems = function () {\n $modal.open({\n templateUrl: 'js/modules/contact/modals/wedding-registry-modal.tpl.html',\n controller: 'WeddingRegistryModalCtrl',\n resolve: {\n eventMembers: function () {\n return $scope.eventMembers;\n },\n eventItems: function () {\n return $scope.eventItems;\n },\n posSettings: function () {\n return posSettings;\n }\n }\n });\n };\n\n $scope.openSplitPayments = function () {\n var selectedItems = _($scope.getSelectedItems()).filter(function (item) {\n return item.balanceDue > 0;\n });\n\n if (!selectedItems.length) {\n return modalService.showMessage('contact.messages.select-transactions-with-positive-balance-due');\n }\n\n var transactions = _(selectedItems).map(function (eventItem) {\n var transaction = _(eventItem).pick('trxNumber', 'balanceDue');\n transaction.contactName = eventItem.firstName + ' ' + eventItem.lastName;\n transaction.eventDate = eventItem.trxEventDate;\n transaction.typeId = eventItem.trxTypeId;\n transaction.id = eventItem.transactionId;\n return transaction;\n });\n\n //de-dupe the transactions\n transactions = _(transactions).uniq(function(transaction){\n return transaction.id;\n });\n\n TransactionPaymentsModalService\n .openSplitPayments(transactions)\n .result\n .then(function (results) {\n init();\n if(results) {\n openSplitPaymentsSuccessModal(results);\n }\n });\n };\n\n function openSplitPaymentsSuccessModal(transactions) {\n $modal.open({\n templateUrl: 'js/modules/transaction/details/modals/split-payments-confirmation-modal.tpl.html',\n controller: 'SplitPaymentsConfirmationModalCtrl',\n resolve: {\n transactions: function () {\n return transactions;\n },\n posSettings: function (CompanySetting) {\n return CompanySetting.getPOSSettings();\n }\n }\n });\n }\n\n $scope.sendTextMessage = function () {\n\n var selectedMembers = _.where($scope.eventMembers, { selected: true });\n\n if (!selectedMembers.length) {\n modalService.showMessage('contact.messages.select-at-least-one-contact', 'common.message.wooops');\n return false;\n }\n\n if (selectedMembers.length > 250) {\n modalService.showMessage('contact.messages.select-no-more-than-250', 'common.message.cannot-send-sms-messages');\n return false;\n }\n\n var selectedContacts = [];\n _.forEach(selectedMembers, function(selectedMember) {\n var contact = {\n id: selectedMember.contactId,\n mobilePhoneNumber: selectedMember.mobilePhoneNumber\n };\n\n selectedContacts.push(contact);\n\n });\n\n var successcb = function (result) {\n var modalScope = {\n errors: result.errors,\n successes: result.successes,\n optedErrors: result.optedErrors\n };\n\n $modal.open({\n templateUrl: 'js/modules/contact/modals/bulk-twilio-send-result-modal.tpl.html',\n controller: 'BulkTwilioSendResultModalCtrl',\n resolve: {\n modalScope: function () {\n return modalScope;\n }\n },\n backdrop:'static'\n });\n\n };\n\n Sms.showSendModal(selectedContacts, null, null, null, successcb);\n };\n\n $scope.selectAllMembers = function (selected) {\n $scope.eventMembers.forEach(function (member) {\n member.selected = selected;\n $scope.selectMemberItems(member);\n });\n };\n\n $scope.selectMemberItems = function (member) {\n $scope.getMemberItems(member).forEach(function (item) {\n item.selected = member.selected;\n });\n };\n\n $scope.removeMemberItem = function (eventItem) {\n $scope.eventItems = _($scope.eventItems).without(eventItem);\n eventItem.$remove();\n alerts.push('alerts.contact.successfully-removed-wedding-registry-item');\n };\n\n $scope.updateEventItem = function (item) {\n _.omit(item, 'selected').$update(function (updatedItem) {\n item.version = updatedItem.version;\n });\n };\n\n /**\n * Watchers\n */\n\n $scope.$watchCollection('eventItems', function (items) {\n $scope.itemsColorOptions = {};\n $scope.itemsColor2Options = {};\n $scope.itemsSizeOptions = {};\n\n if (items) {\n items.forEach(function (item) {\n // color, color2\n $scope.itemsColorOptions[item.id] = item.colorString ? item.colorString.replace(/ /g, '').split(',') : [];\n $scope.itemsColor2Options[item.id] = item.color2String ? item.color2String.replace(/ /g, '').split(',') : [];\n\n // size\n $scope.itemsSizeOptions[item.id] = item.sizeGroup && item.sizeGroup.sizes.map(function (size) {\n return size.size;\n });\n });\n }\n });\n\n /**\n * Init\n */\n\n function init() {\n EventItem.list({ eventId: $scope.event.id }, function (items) {\n $scope.eventItems = items;\n });\n\n EventMember.query({ filterObject: { eventId: $scope.event.id } }, function (members) {\n $scope.eventMembers = members;\n\n // Expand all members\n $scope.eventMembers.map(function (member) {\n member.expanded = true;\n member.selected = false;\n });\n });\n }\n\n init();\n });\n});\n\n","/* \n * Angular JS Multi Select\n * Creates a dropdown-like button with checkboxes. \n *\n * Project started on: Tue, 14 Jan 2014 - 5:18:02 PM\n * Current version: 2.0.2\n * \n * Released under the MIT License\n * --------------------------------------------------------------------------------\n * The MIT License (MIT)\n *\n * Copyright (c) 2014 Ignatius Steven (https://github.com/isteven)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy \n * of this software and associated documentation files (the \"Software\"), to deal \n * in the Software without restriction, including without limitation the rights \n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell \n * copies of the Software, and to permit persons to whom the Software is \n * furnished to do so, subject to the following conditions: \n *\n * The above copyright notice and this permission notice shall be included in all \n * copies or substantial portions of the Software.\n * \n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR \n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE \n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \n * SOFTWARE.\n * --------------------------------------------------------------------------------\n */\n\nangular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$sce', '$timeout', function ( $sce, $timeout ) {\n return {\n restrict: \n 'AE',\n\n replace: \n true,\n\n scope: \n { \n // models\n inputModel : '=',\n outputModel : '=',\n\n // settings based on attribute\n buttonLabel : '@',\n defaultLabel : '@',\n directiveId : '@',\n helperElements : '@', \n isDisabled : '=',\n itemLabel : '@',\n maxLabels : '@',\n orientation : '@',\n selectionMode : '@',\n isGroupSelectionDisabled: '@',\n\n // settings based on input model property \n tickProperty : '@',\n disableProperty : '@',\n groupProperty : '@',\n maxHeight : '@',\n\n // callbacks\n onClose : '&', \n onItemClick : '&',\n onOpen : '&' \n },\n\n template: \n '' + \n '' + \n '
' + \n '
' + \n '
' +\n '
' +\n ' ' +\n '' +\n '' +\n '
' +\n '
' +\n '' +\n ' ' +\n '
' +\n '
' +\n '
' +\n '
' + \n '
0\" ng-repeat=\"i in numberToArray( item[ spacingProperty ] ) track by $index\"> 
' + \n '
' +\n '' + \n '
' +\n '        ' + \n '' +\n '
' +\n '
' +\n '
' +\n '
' +\n '
',\n\n link: function ( $scope, element, attrs ) { \n\n $scope.backUp = [];\n $scope.varButtonLabel = ''; \n $scope.scrolled = false;\n $scope.spacingProperty = '';\n $scope.indexProperty = ''; \n $scope.checkBoxLayer = '';\n $scope.orientationH = false;\n $scope.orientationV = true;\n $scope.filteredModel = [];\n $scope.inputLabel = { labelFilter: '' };\n $scope.selectedItems = []; \n $scope.formElements = [];\n $scope.tabIndex = 0;\n $scope.clickedItem = null;\n prevTabIndex = 0;\n helperItems = [];\n helperItemsLength = 0;\n\n // If user specify a height, call this function\n $scope.setHeight = function() {\n if ( typeof $scope.maxHeight !== 'undefined' ) {\n return 'max-height: ' + $scope.maxHeight + '; overflow-y:scroll';\n }\n }\n\n // A little hack so that AngularJS ng-repeat can loop using start and end index like a normal loop\n // http://stackoverflow.com/questions/16824853/way-to-ng-repeat-defined-number-of-times-instead-of-repeating-over-array\n $scope.numberToArray = function( num ) {\n return new Array( num ); \n }\n\n $scope.updateFilter = function()\n {\n // we check by looping from end of array\n $scope.filteredModel = [];\n var i = 0;\n\n if ( typeof $scope.inputModel === 'undefined' ) {\n return []; \n }\n\n for( i = $scope.inputModel.length - 1; i >= 0; i-- ) {\n\n // if it's group end\n if ( typeof $scope.inputModel[ i ][ $scope.groupProperty ] !== 'undefined' && $scope.inputModel[ i ][ $scope.groupProperty ] === false ) {\n $scope.filteredModel.push( $scope.inputModel[ i ] );\n }\n \n // if it's data \n var gotData = false;\n if ( typeof $scope.inputModel[ i ][ $scope.groupProperty ] === 'undefined' ) { \n\n for (var key in $scope.inputModel[ i ] ) {\n // if filter string is in one of object property \n if ( typeof $scope.inputModel[ i ][ key ] !== 'boolean' && String( $scope.inputModel[ i ][ key ] ).toUpperCase().indexOf( $scope.inputLabel.labelFilter.toUpperCase() ) >= 0 ) {\n gotData = true;\n break;\n }\n } \n if ( gotData === true ) { \n // push\n $scope.filteredModel.push( $scope.inputModel[ i ] );\n }\n }\n\n // if it's group start\n if ( typeof $scope.inputModel[ i ][ $scope.groupProperty ] !== 'undefined' && $scope.inputModel[ i ][ $scope.groupProperty ] === true ) {\n\n if ( typeof $scope.filteredModel[ $scope.filteredModel.length - 1 ][ $scope.groupProperty ] !== 'undefined' && $scope.filteredModel[ $scope.filteredModel.length - 1 ][ $scope.groupProperty ] === false ) {\n $scope.filteredModel.pop();\n }\n else {\n $scope.filteredModel.push( $scope.inputModel[ i ] );\n }\n }\n } \n\n $scope.filteredModel.reverse(); \n $timeout( function() {\n $scope.getFormElements(); \n },0);\n };\n\n // List all the input elements.\n // This function will be called everytime the filter is updated. Not good for performance, but oh well..\n $scope.getFormElements = function() { \n $scope.formElements = [];\n for ( var i = 0; i < element[ 0 ].getElementsByTagName( 'FORM' )[ 0 ].elements.length ; i++ ) { \n $scope.formElements.push( element[ 0 ].getElementsByTagName( 'FORM' )[ 0 ].elements[ i ] );\n }\n } \n\n // check if an item has $scope.groupProperty (be it true or false)\n $scope.isGroupMarker = function( item , type ) {\n if ( typeof item[ $scope.groupProperty ] !== 'undefined' && item[ $scope.groupProperty ] === type ) return true; \n return false;\n }\n\n $scope.removeGroupEndMarker = function( item ) {\n if ( typeof item[ $scope.groupProperty ] !== 'undefined' && item[ $scope.groupProperty ] === false ) return false; \n return true;\n }\n \n\n // Show or hide a helper element \n $scope.displayHelper = function( elementString ) {\n\n if ( attrs.selectionMode && $scope.selectionMode.toUpperCase() === 'SINGLE' ) {\n\n switch( elementString.toUpperCase() ) {\n case 'ALL': \n return false; \n break;\n case 'NONE': \n return false;\n break;\n case 'RESET':\n if ( typeof attrs.helperElements === 'undefined' ) {\n return true; \n }\n else if ( attrs.helperElements && $scope.helperElements.toUpperCase().indexOf( 'RESET' ) >= 0 ) {\n return true;\n } \n break;\n case 'FILTER':\n if ( typeof attrs.helperElements === 'undefined' ) {\n return true; \n } \n if ( attrs.helperElements && $scope.helperElements.toUpperCase().indexOf( 'FILTER' ) >= 0 ) {\n return true;\n }\n break; \n default: \n break;\n } \n\n return false;\n }\n\n else {\n if ( typeof attrs.helperElements === 'undefined' ) {\n return true; \n }\n if ( attrs.helperElements && $scope.helperElements.toUpperCase().indexOf( elementString.toUpperCase() ) >= 0 ) {\n return true;\n }\n return false;\n } \n } \n\n // call this function when an item is clicked\n $scope.syncItems = function( item, e, ng_repeat_index ) { \n\n e.preventDefault();\n e.stopPropagation();\n\n // if it's globaly disabled, then don't do anything\n if ( typeof attrs.disableProperty !== 'undefined' && item[ $scope.disableProperty ] === true ) { \n return false;\n }\n\n // don't change disabled items\n if ( typeof attrs.isDisabled !== 'undefined' && $scope.isDisabled === true ) { \n return false;\n } \n\n // we don't care about end of group markers\n if ( typeof item[ $scope.groupProperty ] !== 'undefined' && item[ $scope.groupProperty ] === false ) {\n return false;\n } \n\n index = $scope.filteredModel.indexOf( item ); \n\n // process items if the start of group marker is clicked ( only for multiple selection! )\n // if, in a group, there are items which are not selected, then they all will be selected\n // if, in a group, all items are selected, then they all will be de-selected \n if ( typeof item[ $scope.groupProperty ] !== 'undefined' && item[ $scope.groupProperty ] === true ) { \n\n if ( (attrs.selectionMode && $scope.selectionMode.toUpperCase() === 'SINGLE') || $scope.isGroupSelectionDisabled ) {\n return false;\n }\n \n var i,j,k;\n var startIndex = 0;\n var endIndex = $scope.filteredModel.length - 1;\n var tempArr = [];\n var nestLevel = 0; \n\n for( i = index ; i < $scope.filteredModel.length ; i++) { \n\n if ( nestLevel === 0 && i > index ) \n {\n break;\n }\n \n // if group start\n if ( typeof $scope.filteredModel[ i ][ $scope.groupProperty ] !== 'undefined' && $scope.filteredModel[ i ][ $scope.groupProperty ] === true ) {\n \n // To cater multi level grouping\n if ( tempArr.length === 0 ) {\n startIndex = i + 1; \n } \n nestLevel = nestLevel + 1;\n } \n\n // if group end\n else if ( typeof $scope.filteredModel[ i ][ $scope.groupProperty ] !== 'undefined' && $scope.filteredModel[ i ][ $scope.groupProperty ] === false ) {\n\n nestLevel = nestLevel - 1; \n\n // cek if all are ticked or not \n if ( tempArr.length > 0 && nestLevel === 0 ) { \n\n var allTicked = true; \n\n endIndex = i;\n\n for ( j = 0; j < tempArr.length ; j++ ) { \n if ( typeof tempArr[ j ][ $scope.tickProperty ] !== 'undefined' && tempArr[ j ][ $scope.tickProperty ] === false ) {\n allTicked = false;\n break;\n }\n } \n\n if ( allTicked === true ) {\n for ( j = startIndex; j <= endIndex ; j++ ) {\n if ( typeof $scope.filteredModel[ j ][ $scope.groupProperty ] === 'undefined' ) {\n if ( typeof attrs.disableProperty === 'undefined' ) {\n $scope.filteredModel[ j ][ $scope.tickProperty ] = false;\n // we refresh input model as well\n inputModelIndex = $scope.filteredModel[ j ][ $scope.indexProperty ];\n $scope.inputModel[ inputModelIndex ][ $scope.tickProperty ] = false;\n }\n else if ( $scope.filteredModel[ j ][ $scope.disableProperty ] !== true ) {\n $scope.filteredModel[ j ][ $scope.tickProperty ] = false;\n // we refresh input model as well\n inputModelIndex = $scope.filteredModel[ j ][ $scope.indexProperty ];\n $scope.inputModel[ inputModelIndex ][ $scope.tickProperty ] = false;\n }\n }\n } \n }\n\n else {\n for ( j = startIndex; j <= endIndex ; j++ ) {\n if ( typeof $scope.filteredModel[ j ][ $scope.groupProperty ] === 'undefined' ) {\n if ( typeof attrs.disableProperty === 'undefined' ) {\n $scope.filteredModel[ j ][ $scope.tickProperty ] = true; \n // we refresh input model as well\n inputModelIndex = $scope.filteredModel[ j ][ $scope.indexProperty ];\n $scope.inputModel[ inputModelIndex ][ $scope.tickProperty ] = true;\n\n } \n else if ( $scope.filteredModel[ j ][ $scope.disableProperty ] !== true ) {\n $scope.filteredModel[ j ][ $scope.tickProperty ] = true;\n // we refresh input model as well\n inputModelIndex = $scope.filteredModel[ j ][ $scope.indexProperty ];\n $scope.inputModel[ inputModelIndex ][ $scope.tickProperty ] = true;\n }\n }\n } \n } \n }\n }\n \n // if data\n else { \n tempArr.push( $scope.filteredModel[ i ] ); \n }\n } \n }\n\n // single item click\n else {\n\n // If it's single selection mode\n if ( attrs.selectionMode && $scope.selectionMode.toUpperCase() === 'SINGLE' ) {\n \n // first, set everything to false\n for( i=0 ; i < $scope.filteredModel.length ; i++) { \n $scope.filteredModel[ i ][ $scope.tickProperty ] = false; \n } \n for( i=0 ; i < $scope.inputModel.length ; i++) { \n $scope.inputModel[ i ][ $scope.tickProperty ] = false; \n } \n \n // then set the clicked item to true\n $scope.filteredModel[ index ][ $scope.tickProperty ] = true;\n\n $scope.toggleCheckboxes( e ); \n } \n\n // Multiple\n else {\n $scope.filteredModel[ index ][ $scope.tickProperty ] = !$scope.filteredModel[ index ][ $scope.tickProperty ];\n }\n\n // we refresh input model as well\n inputModelIndex = $scope.filteredModel[ index ][ $scope.indexProperty ]; \n $scope.inputModel[ inputModelIndex ][ $scope.tickProperty ] = $scope.filteredModel[ index ][ $scope.tickProperty ]; \n } \n\n $scope.clickedItem = angular.copy( item ); \n\n // We update the index here\n prevTabIndex = $scope.tabIndex;\n $scope.tabIndex = ng_repeat_index + helperItemsLength;\n \n // Set focus on the hidden checkbox \n e.target.focus();\n\n // set & remove CSS style\n $scope.removeFocusStyle( prevTabIndex );\n $scope.setFocusStyle( $scope.tabIndex );\n } \n\n // update $scope.selectedItems\n // this variable is used in $scope.outputModel and to refresh the button label\n $scope.refreshSelectedItems = function() { \n $scope.selectedItems = [];\n angular.forEach( $scope.inputModel, function( value, key ) {\n if ( typeof value !== 'undefined' ) { \n if ( typeof value[ $scope.groupProperty ] === 'undefined' ) {\n if ( value[ $scope.tickProperty ] === true ) {\n $scope.selectedItems.push( value ); \n }\n }\n }\n }); \n }\n\n // refresh output model as well\n $scope.refreshOutputModel = function() { \n if ( typeof attrs.outputModel !== 'undefined' ) { \n $scope.outputModel = angular.copy( $scope.selectedItems ); \n angular.forEach( $scope.outputModel, function( value, key ) {\n // remove the index number and spacing number from output model\n delete value[ $scope.indexProperty ];\n delete value[ $scope.spacingProperty ]; \n });\n } \n }\n\n // refresh button label\n $scope.refreshButton = function() {\n\n $scope.varButtonLabel = ''; \n ctr = 0; \n\n // refresh button label...\n if ( $scope.selectedItems.length === 0 ) {\n // https://github.com/isteven/angular-multi-select/pull/19 \n $scope.varButtonLabel = ( typeof $scope.defaultLabel !== 'undefined' ) ? $scope.defaultLabel : 'None selected';\n }\n else { \n var tempMaxLabels = $scope.selectedItems.length;\n if ( typeof $scope.maxLabels !== 'undefined' && $scope.maxLabels !== '' ) {\n tempMaxLabels = $scope.maxLabels;\n }\n\n // if max amount of labels displayed..\n if ( $scope.selectedItems.length > tempMaxLabels ) {\n $scope.more = true;\n }\n else {\n $scope.more = false;\n } \n \n angular.forEach( $scope.selectedItems, function( value, key ) {\n if ( typeof value !== 'undefined' ) { \n if ( ctr < tempMaxLabels ) { \n $scope.varButtonLabel += ( $scope.varButtonLabel.length > 0 ? '
,
' : '
') + $scope.writeLabel( value, 'buttonLabel' );\n }\n ctr++;\n }\n }); \n\n if ( $scope.more === true ) {\n // https://github.com/isteven/angular-multi-select/pull/16\n if (tempMaxLabels > 0) {\n $scope.varButtonLabel += ', ... ';\n }\n $scope.varButtonLabel += '(Total: ' + $scope.selectedItems.length + ')'; \n }\n }\n $scope.varButtonLabel = $sce.trustAsHtml( $scope.varButtonLabel + '' ); \n }\n\n // Check if a checkbox is disabled or enabled. It will check the granular control (disableProperty) and global control (isDisabled)\n // Take note that the granular control has higher priority.\n $scope.itemIsDisabled = function( item ) {\n \n if ( typeof attrs.disableProperty !== 'undefined' && item[ $scope.disableProperty ] === true ) { \n return true;\n }\n else { \n if ( $scope.isDisabled === true ) { \n return true;\n }\n else {\n return false;\n }\n }\n \n }\n\n // A simple function to parse the item label settings\n $scope.writeLabel = function( item, type ) {\n var label = '';\n var temp = $scope[ type ].split( ' ' ); \n angular.forEach( temp, function( value2, key2 ) {\n if ( typeof value2 !== 'undefined' ) { \n angular.forEach( item, function( value1, key1 ) { \n if ( key1 == value2 ) {\n label += ' ' + value1; \n }\n }); \n }\n });\n if ( type.toUpperCase() === 'BUTTONLABEL' ) {\n return label;\n }\n return $sce.trustAsHtml( label );\n }\n\n // UI operations to show/hide checkboxes based on click event..\n $scope.toggleCheckboxes = function( e ) { \n\n // We grab the checkboxLayer\n $scope.checkBoxLayer = element.children()[1];\n\n // We grab the button\n clickedEl = element.children()[0];\n\n // Just to make sure.. had a bug where key events were recorded twice\n angular.element( document ).unbind( 'click', $scope.externalClickListener );\n angular.element( document ).unbind( 'keydown', $scope.keyboardListener ); \n\n // clear filter\n $scope.inputLabel.labelFilter = ''; \n $scope.updateFilter(); \n\n // close if ESC key is pressed.\n if ( e.keyCode === 27 ) {\n angular.element( $scope.checkBoxLayer ).removeClass( 'show' ); \n angular.element( clickedEl ).removeClass( 'buttonClicked' ); \n angular.element( document ).unbind( 'click', $scope.externalClickListener );\n angular.element( document ).unbind( 'keydown', $scope.keyboardListener ); \n\n // clear the focused element;\n $scope.removeFocusStyle( $scope.tabIndex );\n\n // close callback\n $scope.onClose( { data: element } );\n return true;\n } \n\n // The idea below was taken from another multi-select directive - https://github.com/amitava82/angular-multiselect \n // His version is awesome if you need a more simple multi-select approach.\n\n // close\n if ( angular.element( $scope.checkBoxLayer ).hasClass( 'show' )) { \n angular.element( $scope.checkBoxLayer ).removeClass( 'show' ); \n angular.element( clickedEl ).removeClass( 'buttonClicked' ); \n angular.element( document ).unbind( 'click', $scope.externalClickListener );\n angular.element( document ).unbind( 'keydown', $scope.keyboardListener ); \n\n // clear the focused element;\n $scope.removeFocusStyle( $scope.tabIndex );\n\n // close callback\n $scope.onClose( { data: element } );\n } \n // open\n else \n { \n helperItems = [];\n helperItemsLength = 0;\n\n angular.element( $scope.checkBoxLayer ).addClass( 'show' ); \n angular.element( clickedEl ).addClass( 'buttonClicked' ); \n angular.element( document ).bind( 'click', $scope.externalClickListener );\n angular.element( document ).bind( 'keydown', $scope.keyboardListener ); \n\n // to get the initial tab index, depending on how many helper elements we have. \n // priority is to always focus it on the input filter \n $scope.getFormElements();\n $scope.tabIndex = 0;\n\n var helperContainer = angular.element( element[ 0 ].querySelector( '.helperContainer' ) )[0]; \n \n if ( typeof helperContainer !== 'undefined' ) {\n for ( i = 0; i < helperContainer.getElementsByTagName( 'BUTTON' ).length ; i++ ) {\n helperItems[ i ] = helperContainer.getElementsByTagName( 'BUTTON' )[ i ];\n }\n helperItemsLength = helperItems.length + helperContainer.getElementsByTagName( 'INPUT' ).length;\n }\n \n // focus on the filter element on open. \n if ( element[ 0 ].querySelector( '.inputFilter' ) ) { \n element[ 0 ].querySelector( '.inputFilter' ).focus(); \n $scope.tabIndex = $scope.tabIndex + helperItemsLength - 2;\n }\n // if there's no filter then just focus on the first checkbox item\n else { \n $scope.formElements[ $scope.tabIndex ].focus(); \n } \n\n // open callback\n $scope.onOpen( { data: element } );\n } \n }\n \n // handle clicks outside the button / multi select layer\n $scope.externalClickListener = function( e ) { \n targetsArr = element.find( e.target.tagName );\n for (var i = 0; i < targetsArr.length; i++) { \n if ( e.target == targetsArr[i] ) {\n return;\n }\n }\n\n angular.element( $scope.checkBoxLayer.previousSibling ).removeClass( 'buttonClicked' ); \n angular.element( $scope.checkBoxLayer ).removeClass( 'show' );\n angular.element( document ).unbind( 'click', $scope.externalClickListener ); \n angular.element( document ).unbind( 'keydown', $scope.keyboardListener ); \n \n // close callback \n $timeout( function() {\n $scope.onClose( { data: element } );\n }, 0 );\n }\n \n // traverse up to find the button tag\n // http://stackoverflow.com/questions/7332179/how-to-recursively-search-all-parentnodes\n $scope.findUpTag = function ( el, tag, className ) {\n while ( el.parentNode ) { \n el = el.parentNode; \n if ( typeof el.tagName !== 'undefined' ) {\n if ( el.tagName.toUpperCase() === tag.toUpperCase() && el.className.indexOf( className ) > -1 ) {\n return el;\n }\n }\n }\n return null;\n }\n\n // select All / select None / reset buttons\n $scope.select = function( type, e ) {\n\n helperIndex = helperItems.indexOf( e.target );\n $scope.tabIndex = helperIndex;\n\n switch( type.toUpperCase() ) {\n case 'ALL':\n angular.forEach( $scope.filteredModel, function( value, key ) { \n if ( typeof value !== 'undefined' && value[ $scope.disableProperty ] !== true ) { \n if ( typeof value[ $scope.groupProperty ] === 'undefined' ) { \n value[ $scope.tickProperty ] = true;\n }\n }\n }); \n break;\n case 'NONE':\n angular.forEach( $scope.filteredModel, function( value, key ) {\n if ( typeof value !== 'undefined' && value[ $scope.disableProperty ] !== true ) { \n if ( typeof value[ $scope.groupProperty ] === 'undefined' ) { \n value[ $scope.tickProperty ] = false;\n }\n }\n }); \n break;\n case 'RESET': \n angular.forEach( $scope.filteredModel, function( value, key ) { \n if ( typeof value[ $scope.groupProperty ] === 'undefined' && typeof value !== 'undefined' && value[ $scope.disableProperty ] !== true ) { \n temp = value[ $scope.indexProperty ]; \n value[ $scope.tickProperty ] = $scope.backUp[ temp ][ $scope.tickProperty ];\n }\n }); \n break;\n case 'CLEAR':\n $scope.tabIndex = $scope.tabIndex + 1;\n break;\n case 'FILTER': \n $scope.tabIndex = helperItems.length - 1;\n break;\n default: \n } \n } \n\n // just to create a random variable name \n genRandomString = function( length ) { \n var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n var temp = '';\n for( var i=0; i < length; i++ ) {\n temp += possible.charAt( Math.floor( Math.random() * possible.length ));\n }\n return temp;\n }\n\n // count leading spaces\n $scope.prepareGrouping = function() {\n var spacing = 0; \n angular.forEach( $scope.filteredModel, function( value, key ) {\n value[ $scope.spacingProperty ] = spacing; \n if ( value[ $scope.groupProperty ] === true ) {\n spacing+=2;\n } \n else if ( value[ $scope.groupProperty ] === false ) {\n spacing-=2;\n } \n });\n }\n\n // prepare original index\n $scope.prepareIndex = function() {\n ctr = 0;\n angular.forEach( $scope.filteredModel, function( value, key ) {\n value[ $scope.indexProperty ] = ctr;\n ctr++;\n });\n }\n\n // navigate using up and down arrow\n $scope.keyboardListener = function( e ) { \n \n var key = e.keyCode ? e.keyCode : e.which; \n var isNavigationKey = false; \n\n // ESC key (close)\n if ( key === 27 ) {\n $scope.toggleCheckboxes( e );\n } \n \n // next element ( tab, down & right key ) \n else if ( key === 40 || key === 39 || ( !e.shiftKey && key == 9 ) ) { \n isNavigationKey = true;\n prevTabIndex = $scope.tabIndex; \n $scope.tabIndex++; \n if ( $scope.tabIndex > $scope.formElements.length - 1 ) {\n $scope.tabIndex = 0;\n prevTabIndex = $scope.formElements.length - 1; \n } \n while ( $scope.formElements[ $scope.tabIndex ].disabled === true ) { \n $scope.tabIndex++;\n if ( $scope.tabIndex > $scope.formElements.length - 1 ) {\n $scope.tabIndex = 0; \n } \n }\n }\n \n // prev element ( shift+tab, up & left key )\n else if ( key === 38 || key === 37 || ( e.shiftKey && key == 9 ) ) { \n isNavigationKey = true;\n prevTabIndex = $scope.tabIndex; \n $scope.tabIndex--; \n if ( $scope.tabIndex < 0 ) {\n $scope.tabIndex = $scope.formElements.length - 1;\n prevTabIndex = 0;\n } \n while ( $scope.formElements[ $scope.tabIndex ].disabled === true ) {\n $scope.tabIndex--;\n if ( $scope.tabIndex < 0 ) {\n $scope.tabIndex = $scope.formElements.length - 1;\n } \n } \n } \n\n if ( isNavigationKey === true ) { \n\n e.preventDefault();\n e.stopPropagation(); \n\n // set focus on the checkbox\n $scope.formElements[ $scope.tabIndex ].focus(); \n \n // css styling\n var actEl = document.activeElement; \n\n if ( actEl.type.toUpperCase() === 'CHECKBOX' ) { \n $scope.setFocusStyle( $scope.tabIndex );\n $scope.removeFocusStyle( prevTabIndex );\n } \n else {\n $scope.removeFocusStyle( prevTabIndex );\n $scope.removeFocusStyle( helperItemsLength );\n $scope.removeFocusStyle( $scope.formElements.length - 1 );\n } \n }\n\n isNavigationKey = false;\n }\n\n // set (add) CSS style on selected row\n $scope.setFocusStyle = function( tabIndex ) { \n angular.element( $scope.formElements[ tabIndex ] ).parent().parent().parent().addClass( 'multiSelectFocus' ); \n }\n\n // remove CSS style on selected row\n $scope.removeFocusStyle = function( tabIndex ) {\n angular.element( $scope.formElements[ tabIndex ] ).parent().parent().parent().removeClass( 'multiSelectFocus' );\n }\n\n ///////////////////////////////////////////////////////\n //\n // Logic starts here, initiated by watch 1 & watch 2.\n //\n ///////////////////////////////////////////////////////\n\n var tempStr = genRandomString( 5 );\n $scope.indexProperty = 'idx_' + tempStr;\n $scope.spacingProperty = 'spc_' + tempStr; \n\n // set orientation css \n if ( typeof attrs.orientation !== 'undefined' ) {\n if ( attrs.orientation.toUpperCase() === 'HORIZONTAL' ) { \n $scope.orientationH = true;\n $scope.orientationV = false;\n }\n else {\n $scope.orientationH = false;\n $scope.orientationV = true;\n }\n } \n \n // watch1, for changes in input model property\n // updates multi-select when user select/deselect a single checkbox programatically\n // https://github.com/isteven/angular-multi-select/issues/8\n $scope.$watch( 'inputModel' , function( newVal ) { \n if ( newVal ) {\n $scope.refreshSelectedItems(); \n $scope.refreshOutputModel();\n $scope.refreshButton(); \n if ( $scope.clickedItem !== null ) { \n $timeout( function() {\n $scope.onItemClick( { data: $scope.clickedItem } );\n $scope.clickedItem = null; \n }, 0 ); \n } \n }\n }, true);\n\n // watch2 for changes in input model as a whole\n // this on updates the multi-select when a user load a whole new input-model. We also update the $scope.backUp variable\n $scope.$watch( 'inputModel' , function( newVal ) { \n if ( newVal ) {\n $scope.backUp = angular.copy( $scope.inputModel ); \n $scope.updateFilter();\n $scope.prepareGrouping();\n $scope.prepareIndex(); \n $scope.refreshSelectedItems(); \n $scope.refreshOutputModel(); \n $scope.refreshButton(); \n }\n }); \n\n // watch for changes in directive state (disabled or enabled)\n $scope.$watch( 'isDisabled' , function( newVal ) { \n $scope.isDisabled = newVal; \n }); \n\n // this is for touch enabled devices. We don't want to hide checkboxes on scroll. \n angular.element( document ).bind( 'touchstart', function( e ) { \n $scope.$apply( function() {\n $scope.scrolled = false;\n }); \n });\n \n // also for touch enabled devices\n angular.element( document ).bind( 'touchmove', function( e ) { \n $scope.$apply( function() {\n $scope.scrolled = true; \n });\n });\n \n // for IE8, perhaps. Not sure if this is really executed.\n if ( !Array.prototype.indexOf ) {\n Array.prototype.indexOf = function(what, i) { \n i = i || 0;\n var L = this.length;\n while (i < L) {\n if(this[i] === what) return i;\n ++i;\n }\n return -1;\n };\n }\n } \n }\n}]);\n\n\ndefine(\"multi-select\", [\"angular\"], function(){});\n\n","define('modules/item/favorited-by/favorited-by-ctrl',['./module', 'underscore'], function (module, _) {\n 'use strict';\n\n return module.controller('ItemFavoritedByCtrl', function ($controller, $scope, $modal, security, favoriteHistory, Enums, Sms, EmailService, modalService, ItemInterestEmailSettings) {\n\n $scope.selectedResults = [];\n $scope.headers = [\n { title: 'common.contact-name' },\n { title: 'common.color' },\n { title: 'common.accent-color' },\n { title: 'common.size' },\n { title: 'common.modal.mobile-phone-number' },\n { title: 'common.modal.email' },\n { title: 'contact.favorites.tried-on' },\n { title: 'common.added-by' }\n ];\n\n $scope.colSpanCount = 8;\n\n if(security.hasPermission('MESSAGES')) {\n $scope.colSpanCount++;\n }\n\n $scope.showSendTextMessageModal = function (favorite) {\n var contactObj = {\n id: favorite.contactId,\n itemInterestId: favorite.id,\n mobilePhoneNumber: favorite.mobilePhoneNumber,\n favoriteItemImageUrl: favorite.itemPictureImageUrl\n };\n\n Sms.showSendModal(contactObj, null, null, null, null, {\n showOptions: true,\n includeItemImage: !!(favorite.itemPictureImageUrl),\n imageUrl: favorite.itemPictureImageUrl\n });\n };\n\n $scope.showSendEmailModal = function(favorite) {\n var contact = favorite.contact;\n EmailService.showSendModal(contact, null, null, null, null, [favorite],{\n showOptions: true,\n showFavorites: true,\n favoritesEmailSettings: ItemInterestEmailSettings\n }, true);\n };\n\n $scope.syncSelectedResults = function(obj) {\n var checkedItWasSelected = _($scope.selectedResults).findWhere({ id: obj.id });\n if (checkedItWasSelected) {\n $scope.selectedResults = _($scope.selectedResults).without(checkedItWasSelected);\n } else {\n $scope.selectedResults.push(obj);\n }\n };\n\n $scope.selectAll = false;\n $scope.toggleSelectAll = function (removeAll) {\n $scope.selectAll = !$scope.selectAll;\n if($scope.selectAll) {\n $scope.selectedResults = _.union($scope.selectedResults, $scope.favoriteHistory);\n } else {\n $scope.selectedResults = removeAll ? [] : _($scope.selectedResults).difference($scope.favoriteHistory);\n }\n\n //toggle all favorites\n $scope.favoriteHistory = _($scope.favoriteHistory).map(function(favorite) {\n favorite.checked = $scope.selectAll;\n return favorite;\n });\n };\n\n $scope.favoriteHistory = mapFavoriteHistory(favoriteHistory);\n\n function mapFavoriteHistory(favorites) {\n return _(favorites).map(function (favorite) {\n return _.extend(favorite, {\n contactName: favorite.contact ? favorite.contact.firstName + ' ' + (favorite.contact.lastName || '') : '',\n emailAddress: favorite.contact && favorite.contact.emailAddress ? favorite.contact.emailAddress : '',\n mobilePhoneNumber: favorite.contact && favorite.contact.mobilePhoneNumber ? favorite.contact.mobilePhoneNumber : '',\n smsOptIn: favorite.contact && favorite.contact.smsOptIn ? favorite.contact.smsOptIn : false,\n vip: favorite.contact && favorite.contact.vip ? favorite.contact.vip : false\n });\n });\n }\n\n $scope.sendTextMessage = function () {\n if(!$scope.selectedResults.length) {\n modalService.showMessage('contact.messages.select-at-least-one-contact', 'common.message.wooops');\n return false;\n }\n\n if($scope.selectedResults.length > 250) {\n modalService.showMessage('contact.messages.select-no-more-than-250', 'common.message.cannot-send-sms-messages');\n return false;\n }\n\n var selectedResultsSMS = [];\n\n _.each($scope.selectedResults, function (selectedResults) {\n var contactObj = {\n id: selectedResults.contactId,\n mobilePhoneNumber: selectedResults.mobilePhoneNumber,\n itemInterestId: selectedResults.id,\n favoriteItemImageUrl: selectedResults.itemPictureImageUrl\n };\n\n selectedResultsSMS.push(contactObj);\n });\n\n var successcb = function (result) {\n var modalScope = {\n errors: result.errors,\n successes: result.successes,\n optedErrors: result.optedErrors\n };\n\n $modal.open({\n templateUrl: 'js/modules/contact/modals/bulk-twilio-send-result-modal.tpl.html',\n controller: 'BulkTwilioSendResultModalCtrl',\n resolve: {\n modalScope: function () {\n return modalScope;\n }\n },\n backdrop:'static'\n });\n\n };\n\n Sms.showSendModal(selectedResultsSMS, null, null, null, successcb, {\n showOptions: true\n });\n };\n });\n});\n\n","define('modules/item/search/search-ctrl',['./../module', 'angular', 'underscore'], function (module, angular, _) {\n 'use strict';\n\n module.controller('ItemSearchCtrl', function (\n $scope,\n $controller,\n $locale,\n $modal,\n $translate,\n $timeout,\n $state,\n $rootScope,\n AppLicense,\n Enums,\n eventsBus,\n Item,\n SizeGroup,\n ColorGroup,\n Department,\n Vendor,\n ItemAddOn,\n PurchaseOrder,\n TaxCode,\n User,\n departments,\n vendors,\n taxCodes,\n ItemModal,\n alerts,\n modalService,\n ImportService,\n ItemLabelsModal,\n Permissions,\n security,\n clientPortalSettings,\n inventorySettings,\n attributeGroups\n ) {\n var headers = [\n {\n title: 'item.#',\n sortField: 'itemNumber'\n },\n {\n title: 'item.barcode',\n sortField: 'qbEditSequence',\n isHidden: $rootScope.legacySystem !== 'BBL'\n },\n {\n title: 'common.name',\n sortField: 'name'\n },\n {\n title: 'item.vendor-name',\n sortField: 'vendorItemName'\n },\n {\n title: 'common.color',\n sortField: 'color'\n },\n {\n title: 'common.size',\n sortField: 'size'\n },\n {\n title: 'item.menu.in-stock'\n },\n {\n title: 'item.qoh',\n sortField: 'quantityOnHand'\n },\n {\n title: 'common.price',\n sortField: 'regularPrice'\n },\n {\n title: 'item.order-cost',\n sortField: 'orderCost',\n isHidden: !security.hasPermission('ITEM_COST')\n },\n {\n title: 'common.vendor',\n sortField: 'vendorName'\n },\n {\n title: 'common.department',\n sortField: 'departmentCode'\n }\n ];\n\n angular.extend(this, $controller('SearchCtrl', { $scope: $scope, headers: headers }));\n\n // pagination settings wrapper\n var perPageOptions = [{ size: 10, label: 10 }, { size: 25, label: 25 }, { size: 50, label: 50 }, { size: 100, label: 100 }, { size: 500, label: 500 }];\n $scope.pagination.perPageOptions = perPageOptions;\n\n eventsBus.subscribe('item:add', function () {\n $scope.search();\n });\n\n var license = AppLicense.get();\n //always override the retailerId regardless of what was used in previous visits.\n if($scope.initialFormValues) {\n $scope.initialFormValues.retailerId = license.retailerId;\n }\n\n $scope.attributeGroups = attributeGroups;\n\n if(license.linkedAccounts.length > 1 && license.plan.multiStore) {\n $scope.linkedAccounts = angular.copy(license.linkedAccounts);\n $scope.linkedAccounts.unshift({ linkedRetailerId:\"ALL_LOCATIONS\", nickName: $translate.instant('reports.common.all-locations') });\n }\n\n $scope.showMoreActions = security.hasPermission('MULTI_TRANSFER_ITEMS') && security.hasPermission('DELETE_ITEM') && license.linkedAccounts.length > 1 && license.plan.multiStore;\n\n // default search values\n $scope.initialValues = {\n status: Enums.statuses.active.value,\n retailerId: license.retailerId,\n isLinkedToMarketplace: Enums.marketplaceFilterType.all.value,\n isItemVisibleOnLookbook: Enums.showingOnLookbookFilterType.all.value,\n isItemSmartMatched: Enums.smartMatchedIgnoredFilterType.all.value,\n hasSalePrice: Enums.salePriceFilterType[0].value\n };\n\n $scope.formValues = angular.copy($scope.initialValues);\n $scope.security = security;\n $scope.advancedSearch = false;\n\n var defaultSortType = _(inventorySettings).findWhere({ type: 'INVTRY_DEFAULT_SORT_FIELD' });\n\n if (defaultSortType && headers[defaultSortType.value] && headers[defaultSortType.value].sortField) {\n $scope.pagination.sortField = headers[defaultSortType.value].sortField;\n if ($scope.activeHeader) {\n $scope.activeHeader.active = false;\n }\n headers[defaultSortType.value].active = true;\n $scope.activeHeader = headers[defaultSortType.value];\n }\n\n var defaultSortDirection = _(inventorySettings).findWhere({ type: 'INVTRY_DEFAULT_SORT_DIRECTION' });\n\n if(defaultSortDirection && defaultSortDirection.value) {\n $scope.pagination.sortDirection = defaultSortDirection.value === 'D' ? 'desc' : 'asc';\n }\n\n //add the \"All\" options to the lists\n if (vendors && vendors.result) {\n $scope.vendors = angular.copy(vendors.result);\n $scope.vendors.unshift({ name: $translate.instant('common.all') });\n }\n\n if (departments && departments.result) {\n $scope.departments = angular.copy(departments.result);\n $scope.departments.unshift({ name: $translate.instant('common.all') });\n }\n\n if (taxCodes) {\n $scope.taxCodes = _.filter(angular.copy(taxCodes), function(taxCode) {\n return taxCode && taxCode.description !== 'BLeCommerceTax';\n });\n\n $scope.taxCodes.unshift({ description: $translate.instant('common.all') });\n $scope.taxCodesWithoutAll = _.filter(angular.copy(taxCodes), function(taxCode) {\n return taxCode && taxCode.description !== 'BLeCommerceTax';\n });\n }\n\n //setup data for search form\n $scope.itemTypes = Enums.itemTypes;\n $scope.types = {\n inventoryItem: $translate.instant('item.types.inventory'),\n nonInventoryItem: $translate.instant('item.types.non-inventory'),\n service: $translate.instant('item.service'),\n rental: $translate.instant('item.rental')\n };\n\n $scope.marketplaceFilterType =[\n Enums.marketplaceFilterType.all,\n Enums.marketplaceFilterType.linked,\n Enums.marketplaceFilterType.unlinked\n ];\n\n $scope.showingOnLookbookFilterType = [\n Enums.showingOnLookbookFilterType.all,\n Enums.showingOnLookbookFilterType.showing,\n Enums.showingOnLookbookFilterType.not_showing\n ];\n\n $scope.smartMatchedIgnoredFilterType = [\n Enums.smartMatchedIgnoredFilterType.all,\n Enums.smartMatchedIgnoredFilterType.ignored,\n Enums.smartMatchedIgnoredFilterType.not_ignored\n ];\n\n $scope.statuses = [\n Enums.statuses.all,\n Enums.statuses.active,\n Enums.statuses.discontinued,\n Enums.statuses.inactive\n ];\n\n $scope.salePriceFilterType = Enums.salePriceFilterType;\n\n // determine visibility of client portal feature\n var portalFeature = _(clientPortalSettings).findWhere({ type: 'CP_FEATURE_LOOKBOOK' });\n var portalFeatureEnabled = portalFeature ? portalFeature.value === 'Y' : true;\n var userHasPermission = security.hasPermission(\"EDIT_SHOW_ON_LOOKBOOK\");\n var licenseHasPortalAccess = AppLicense.get()[\"clientPortalAccess\"];\n $scope.lookbookUpdatesAvailable = licenseHasPortalAccess && portalFeatureEnabled && userHasPermission;\n\n $scope.translations = {\n reorderPoint: $translate.instant('item.re-order-point')\n };\n\n $scope.results = $scope.selectedResults = [];\n $scope.search = function () {\n var params = $scope.buildFilterObject();\n\n // Format attributes\n if ($scope.formValues.attributes) {\n params.filterObject.attributes = $scope.formValues.attributes.map(function (attr) {\n return {\n attributeId: typeof attr === 'object' ? attr.attributeId : attr\n };\n });\n } else {\n $scope.formValues.attributes = [];\n }\n\n $scope.onAttributeSelected = function (id) {\n $scope.formValues.attributes.push(id);\n };\n\n $scope.onAttributeUnselected = function (id) {\n var index = $scope.formValues.attributes.indexOf(id);\n $scope.formValues.attributes.splice(index, 1);\n };\n\n $scope.onAttributeRemoveAll = function () {\n $scope.formValues.attributes = [];\n };\n\n if ($scope.formValues.itemNumber && isNaN($scope.formValues.itemNumber)){\n return;\n }\n Item.query(params, function (resultModel) {\n if($scope.formValues.retailerId === \"ALL_LOCATIONS\") {\n var nameMap = {};\n _.each(resultModel.result, function (result) {\n if(result.retailerId) {\n\n if(!nameMap.hasOwnProperty(result.retailerId)) {\n nameMap[result.retailerId] = getCompanyNickName(result.retailerId);\n }\n\n result.locationName = nameMap[result.retailerId];\n }\n });\n }\n\n _.each(resultModel.result, function (result) {\n if(result.reorderPoint && result.reorderPoint >= 0) {\n result.reorderPointDescription = $scope.translations.reorderPoint + ': ' + result.reorderPoint;\n }\n });\n\n $scope.updateResults(resultModel);\n });\n };\n\n $scope.onVendorChange = function (vendorId) {\n\n //when the vendor changes, we need to reset the drop downs\n $scope.formValues.colorGroupId = null;\n $scope.formValues.sizeGroupId = null;\n\n var filterObject = { vendorId: vendorId ? vendorId : $scope.formValues.vendorId };\n if (filterObject.vendorId) {\n SizeGroup.query({ filterObject: filterObject, sortField: 'name' }, function (results) {\n $scope.sizeGroups = results;\n if (results && results.length) {\n $scope.size_groups = angular.copy(results);\n $scope.size_groups.unshift({ name: $translate.instant('common.all') });\n } else {\n $scope.size_groups = [];\n }\n });\n\n ColorGroup.query({ filterObject: filterObject, sortField: 'name' }, function (results) {\n $scope.colorGroups = results;\n if (results && results.length) {\n $scope.color_groups = angular.copy(results);\n $scope.color_groups.unshift({ name: $translate.instant('common.all') });\n } else {\n $scope.color_groups = [];\n }\n });\n\n ItemAddOn.listByVendorId(filterObject.vendorId, function(results) {\n $scope.vendorItemAddOns = results;\n });\n\n } else {\n $scope.colorGroups = [];\n $scope.color_groups = [];\n $scope.sizeGroups = [];\n $scope.size_groups = [];\n $scope.vendorItemAddOns = [];\n }\n };\n\n $scope.changeSearch = function () {\n $scope.advancedSearch = !$scope.advancedSearch;\n\n /**\n * Reset advanced search inputs if the user hides the advanced search inputs.\n */\n if(!$scope.advancedSearch) {\n $scope.formValues.isLinkedToMarketplace = Enums.marketplaceFilterType.all.value;\n $scope.formValues.isItemVisibleOnLookbook = Enums.showingOnLookbookFilterType.all.value;\n delete $scope.formValues.colorGroupId;\n delete $scope.formValues.sizeGroupId;\n delete $scope.formValues.attributes;\n delete $scope.formValues.description;\n delete $scope.formValues.taxCodeId;\n }\n };\n\n //load the vendor's color/size groups if the vendor is selected\n //initialFormValues is set in common/search-ctrl, which memorizes the previous search\n if ($scope.initialFormValues && $scope.initialFormValues.vendorId) {\n $scope.onVendorChange($scope.initialFormValues.vendorId);\n } else {\n $scope.colorGroups = [];\n $scope.color_groups = [];\n $scope.sizeGroups = [];\n $scope.size_groups = [];\n $scope.vendorItemAddOns = [];\n }\n\n $scope.showItemModal = ItemModal.openAdd;\n\n $scope.remove = function (item) {\n modalService.showConfirmation('item.message.are-you-sure-you-would-like-to-delete?', function () {\n item.$remove(function () {\n $scope.onResultRemoved(item);\n });\n });\n };\n\n $scope.onLocationChange = function() {\n\n $scope.results = [];\n\n //when the location changes, we need to reset the drop downs because they will need to be\n //re-initialized with the new retailerId for this location\n $scope.disableLinks = $scope.formValues.retailerId !== license.retailerId;\n\n //when the location changes, we need to reset the drop downs because they will need to be\n //re-initialized with the new retailerId for this location\n delete $scope.formValues.departmentId;\n delete $scope.formValues.vendorId;\n delete $scope.formValues.taxCodeId;\n\n if($scope.formValues.retailerId !== \"ALL_LOCATIONS\") {\n\n //show inputs that are location specific\n $scope.departmentCriteriaHidden = false;\n $scope.vendorCriteriaHidden = false;\n $scope.additionalOptionsHidden = false;\n\n var filter = { retailerId: $scope.formValues.retailerId, status: Enums.statuses.active.value };\n\n //now re-initialize the 3 lists for the new location selected\n Department.query({sortField: 'name', filterObject:filter}, function(departments) {\n if (departments && departments.result) {\n $scope.departments = angular.copy(departments.result);\n $scope.departments.unshift({ name: $translate.instant('common.all') });\n }\n });\n\n Vendor.query({sortField: 'name', filterObject:filter}, function(vendors) {\n if (vendors && vendors.result) {\n $scope.vendors = angular.copy(vendors.result);\n $scope.vendors.unshift({ name: $translate.instant('common.all') });\n }\n });\n\n TaxCode.query({filterObject:filter}, function(taxCodes) {\n if (taxCodes) {\n $scope.taxCodes = _.filter(angular.copy(taxCodes), function(taxCode) {\n return taxCode && taxCode.description !== 'BLeCommerceTax';\n });\n\n $scope.taxCodes.unshift({ description: $translate.instant('common.all') });\n $scope.taxCodesWithoutAll = _.filter(angular.copy(taxCodes), function(taxCode) {\n return taxCode && taxCode.description !== 'BLeCommerceTax';\n });\n }\n });\n\n\n } else {\n //hide inputs that are location specific\n $scope.departmentCriteriaHidden = true;\n $scope.vendorCriteriaHidden = true;\n $scope.additionalOptionsHidden = true;\n }\n\n };\n\n $scope.printLabels = function () {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n ItemLabelsModal.open($scope.selectedResults);\n };\n\n $scope.changeStatus = function (status) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-status',\n params: {\n number: $scope.selectedResults.length,\n status: $translate.instant(status.description)\n }\n });\n };\n\n modalService.showConfirmation({\n key: 'item.message.are-you-sure-you-would-like-to-change-the-status?',\n params: {\n number: $scope.selectedResults.length,\n status: $translate.instant(status.description)\n }\n }, function () {\n Item.bulkUpdateStatus(status.value, _($scope.selectedResults).pluck('id'), successcb);\n });\n\n };\n\n $scope.changeTaxCode = function (taxCode) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-tax-code',\n params: {\n number: $scope.selectedResults.length,\n taxCode: taxCode.description\n }\n });\n };\n\n modalService.showConfirmation({\n key: 'item.message.are-you-sure-you-would-like-to-change-the-tax-code?',\n params: {\n number: $scope.selectedResults.length,\n taxCode: taxCode.description\n }\n }, function () {\n Item.bulkUpdateTaxCode(taxCode.id, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.changeItemType = function (itemType) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-item-type',\n params: {\n number: $scope.selectedResults.length,\n itemType: $translate.instant(itemType.description)\n }\n });\n };\n\n modalService.showConfirmation({\n key: 'item.message.are-you-sure-you-would-like-to-change-the-item-type?',\n params: {\n number: $scope.selectedResults.length,\n itemType: $translate.instant(itemType.description)\n }\n }, function () {\n Item.bulkUpdateItemType(itemType.value, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.changePromptToRegister = function (value) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-prompt-to-register-setting',\n params: {\n number: $scope.selectedResults.length,\n value: (value ? $translate.instant('common.yes') : $translate.instant('common.no'))\n }\n });\n };\n\n modalService.showConfirmation({\n key: 'item.message.are-you-sure-you-would-like-to-change-the-prompt-to-register-setting?',\n params: {\n number: $scope.selectedResults.length,\n value: (value ? $translate.instant('common.yes') : $translate.instant('common.no'))\n }\n }, function () {\n Item.bulkUpdatePromptToRegister(value, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.changeAllowDiscount = function (value) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-do-not-allow-discounts-setting',\n params: {\n number: $scope.selectedResults.length,\n value: (value ? $translate.instant('common.yes') : $translate.instant('common.no'))\n }\n });\n };\n\n modalService.showConfirmation({\n key: 'item.message.are-you-sure-you-would-like-to-change-the-do-not-allow-discounts-setting?',\n params: {\n number: $scope.selectedResults.length,\n value: (value ? $translate.instant('common.yes') : $translate.instant('common.no'))\n }\n }, function () {\n Item.bulkUpdateDoNotAllowDiscounts(value, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.changeIsSample = function (value) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-is-sample-setting',\n params: {\n number: $scope.selectedResults.length,\n value: (value ? $translate.instant('common.yes') : $translate.instant('common.no'))\n }\n });\n };\n\n modalService.showConfirmation({\n key: 'item.message.are-you-sure-you-would-like-to-change-the-is-sample-setting?',\n params: {\n number: $scope.selectedResults.length,\n value: (value ? $translate.instant('common.yes') : $translate.instant('common.no'))\n }\n }, function () {\n Item.bulkUpdateSample(value, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.changeColorGroup = function (colorGroup) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-color-group',\n params: { number: $scope.selectedResults.length }\n });\n };\n\n var message = \"\";\n if (colorGroup.id !== 0) {\n message = {\n key: 'item.message.are-you-sure-you-would-like-to-change-the-color-group?',\n params: {\n number: $scope.selectedResults.length,\n colorGroup: colorGroup.name\n }\n };\n } else {\n message = {\n key: 'item.message.are-you-sure-you-would-like-to-remove-the-color-group?',\n params: { number: $scope.selectedResults.length }\n };\n }\n\n modalService.showConfirmation(message, function () {\n Item.bulkUpdateColorGroup(colorGroup.id, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.changeColor2Group = function (color2Group) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-accent-color-group',\n params: { number: $scope.selectedResults.length }\n });\n };\n\n var message = \"\";\n if (color2Group.id !== 0) {\n message = {\n key: 'item.message.are-you-sure-you-would-like-to-change-the-accent-color-group?',\n params: {\n number: $scope.selectedResults.length,\n colorGroup: color2Group.name\n }\n };\n } else {\n message = {\n key: 'item.message.are-you-sure-you-would-like-to-remove-the-accent-color-group?',\n params: { number: $scope.selectedResults.length }\n };\n }\n\n modalService.showConfirmation(message, function () {\n Item.bulkUpdateColor2Group(color2Group.id, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.changeSizeGroup = function (sizeGroup) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-size-group',\n params: { number: $scope.selectedResults.length }\n });\n };\n\n var message = \"\";\n if (sizeGroup.id !== 0) {\n message = {\n key: 'item.message.are-you-sure-you-would-like-to-change-the-size-group?',\n params: {\n number: $scope.selectedResults.length,\n sizeGroup: sizeGroup.name\n }\n };\n } else {\n message = {\n key: 'item.message.are-you-sure-you-would-like-to-remove-the-size-group?',\n params: { number: $scope.selectedResults.length }\n };\n }\n modalService.showConfirmation(message, function () {\n Item.bulkUpdateSizeGroup(sizeGroup.id, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.itemAddOn = function (addOn, addItem) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n if($scope.selectedResults.length > 500) {\n modalService.showMessage({ key: 'item.message.select-no-more-than-500', params: {\n action: $translate.instant(addItem ? 'common._adding' : 'common.removing')\n }}, 'common.message.wooops');\n return false;\n }\n\n var successcb = function (result) {\n $scope.search();\n alerts.pushSuccess({\n key: addItem ? 'alerts.item.successfully-added-item-add-ons' : 'alerts.item.successfully-removed-item-add-ons',\n params: {\n number: result.nbrRowsAffected,\n addOn: addOn.description\n }\n });\n };\n\n var message = {\n key: addItem ? 'item.message.are-you-sure-you-would-like-to-add-the-item-add-on?' : 'item.message.are-you-sure-you-would-like-to-remove-the-item-add-on?',\n params: {\n number: $scope.selectedResults.length,\n addOn: addOn.description\n }\n };\n\n\n modalService.showConfirmation(message, function () {\n Item.bulkAddOrRemoveItemAddOn(addOn.id, _($scope.selectedResults).pluck('id'), addItem, successcb);\n });\n };\n\n $scope.changeShowOnLookbook = function (value) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-lookbook-visibility',\n params: {\n number: $scope.selectedResults.length,\n value: (value ? $translate.instant('common.yes') : $translate.instant('common.no'))\n }\n });\n };\n\n modalService.showConfirmation({\n key: 'item.message.are-you-sure-you-would-like-to-change-the-lookbook-visibility?',\n params: {\n number: $scope.selectedResults.length,\n value: (value ? $translate.instant('common.yes') : $translate.instant('common.no'))\n }\n }, function () {\n Item.bulkUpdateShowOnLookbook(value, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.changeSalePrice = function () {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n ItemModal.openSalePriceModal($scope.selectedResults, function (result) {\n if(result.nbrRowsAffected !== $scope.selectedResults.length) {\n var nbrRowsFailed = $scope.selectedResults.length > 1 ? $scope.selectedResults.length - result.nbrRowsAffected : 1;\n\n alerts.pushError({\n key: 'alerts.item.failed-to-change-the-sale-price',\n params: {\n number: nbrRowsFailed,\n total: $scope.selectedResults.length\n }\n });\n } else {\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-sale-price',\n params: {\n number: $scope.selectedResults.length\n }\n });\n }\n\n $scope.search();\n });\n };\n\n $scope.removeSalePrice = function () {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-sale-price',\n params: {\n number: $scope.selectedResults.length\n }\n });\n };\n\n modalService.showConfirmation({\n key: 'item.message.are-you-sure-you-would-like-to-remove-the-sale-price?',\n params: {\n number: $scope.selectedResults.length\n }\n }, function () {\n Item.bulkUpdateRemoveSalePrice(_($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.removeMarketplaceLinkage = function () {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-marketplace-linkage',\n params: {\n number: $scope.selectedResults.length\n }\n });\n };\n\n modalService.showConfirmation({\n key: 'item.message.are-you-sure-you-would-like-to-remove-the-marketplace-linkage?',\n params: {\n number: $scope.selectedResults.length\n }\n }, function () {\n Item.bulkUnlinkMarketplaceIds(_($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.changeReorderPoint = function () {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n ItemModal.openReorderPointModal($scope.selectedResults, function (result) {\n if(result.nbrRowsAffected !== $scope.selectedResults.length) {\n var nbrRowsFailed = $scope.selectedResults.length > 1 ? $scope.selectedResults.length - result.nbrRowsAffected : 1;\n\n alerts.pushError({\n key: 'alerts.item.failed-to-change-the-reorder-point',\n params: {\n number: nbrRowsFailed,\n total: $scope.selectedResults.length\n }\n });\n } else {\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-reorder-point',\n params: {\n number: $scope.selectedResults.length\n }\n });\n }\n\n $scope.search();\n });\n };\n\n $scope.removeReorderPoint = function () {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-reorder-point',\n params: {\n number: $scope.selectedResults.length\n }\n });\n };\n\n modalService.showConfirmation({\n key: 'item.message.are-you-sure-you-would-like-to-remove-the-reorder-point?',\n params: {\n number: $scope.selectedResults.length\n }\n }, function () {\n Item.bulkUpdateRemoveReorderPoint( _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.smartMatchIgnore = function(value) {\n if(!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'alerts.item.successfully-changed-the-smart-match-ignore',\n params: {\n number: $scope.selectedResults.length,\n value: (value ? $translate.instant('common.yes') : $translate.instant('common.no'))\n }\n });\n };\n\n modalService.showConfirmation({\n key: 'item.message.are-you-sure-you-would-like-to-change-the-smart-match-ignore?',\n params: {\n number: $scope.selectedResults.length,\n value: (value ? $translate.instant('common.yes') : $translate.instant('common.no'))\n }\n }, function () {\n Item.bulkUpdateSmartMatchIgnore(value, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.createPOForItems = function (vendorId) {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n if (!vendorId) {\n modalService.showMessage('alerts.vendor.please-select-a-vendor-before-creating-a-stock-po');\n return false;\n }\n\n var vendor = _($scope.vendors).findWhere({ id: vendorId });\n\n if(!vendor) {\n modalService.showMessage('alerts.vendor.please-select-a-vendor-before-creating-a-stock-po');\n return false;\n }\n\n var successcb = function (po) {\n $state.go('purchase-order.edit', { id: po.id }, { location: 'replace' });\n };\n\n modalService.showConfirmation({\n key: 'item.message.are-you-sure-you-would-like-to-create-stock-po?',\n params: {\n number: $scope.selectedResults.length,\n vendor: (vendor.name)\n }\n }, function () {\n PurchaseOrder.createPOForItems(vendorId, User.id, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.exportToExcel = function () {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('item.message.please-select-at-least-1-item', 'common.message.wooops');\n return false;\n }\n\n modalService.showConfirmation({\n key: 'item.message.are-you-sure-you-would-like-to-export-to-excel?',\n params: { number: $scope.selectedResults.length }\n }, function () {\n Item.exportToExcel(_($scope.selectedResults).pluck('id'), $scope.buildFilterObject());\n });\n };\n\n $scope.import = function () {\n var usesVAT = $locale.usesVat;\n ImportService.openImportModal({\n modelDescription: $translate.instant('item.items'),\n Resource: Item,\n allowUpdates: true,\n templateUrlCreate: '/assets/docs/import_templates/items' + (usesVAT ? '_vat' : '') + '.csv',\n templateUrlUpdate: '/assets/docs/import_templates/items_update.csv'\n });\n };\n\n $scope.onItemTypeChanged = function () {\n _(_($scope.types).keys()).each(function (field) {\n if (field === $scope.itemType) {\n $scope.formValues[field] = true;\n } else {\n delete $scope.formValues[field];\n }\n });\n };\n\n $scope.getColSpan = function (defaultColSpanValue) {\n if(security.hasPermission('ITEM_COST')) {\n defaultColSpanValue++;\n }\n\n if($rootScope.legacySystem === 'BBL') {\n defaultColSpanValue++;\n }\n\n if(license.retailerId !== $scope.formValues.retailerId && $scope.formValues.retailerId !== 'ALL_LOCATIONS') {\n defaultColSpanValue--;\n }\n\n return defaultColSpanValue;\n };\n\n function getCompanyNickName(retailerId) {\n var location = _(license.linkedAccounts).findWhere({ linkedRetailerId: retailerId });\n return location && location.nickName;\n }\n\n $scope.isActiveRetailer = function (retailerId) {\n return retailerId === license.retailerId;\n };\n\n $scope.transfer = function (item) {\n if(!item) {\n return;\n }\n\n if(item.quantityOnHand <= 0 && (item.rental || item.inventoryItem)) {\n return modalService.showMessage(\"Item's quantity on hand must be greater than 0 to transfer.\");\n }\n\n //populate taxCode and department description by matching the ids against the drop downs\n var taxCode = _($scope.taxCodes).findWhere({ id:item.taxCodeId });\n\n if(taxCode) {\n item.taxCodeDescription = taxCode.description;\n }\n\n var department = _($scope.departments).findWhere({ id:item.departmentId });\n\n if(department) {\n item.departmentName = department.name;\n item.departmentCode = department.code;\n }\n\n var vendor = _($scope.vendors).findWhere({ id:item.vendorId });\n\n if(vendor) {\n item.vendorName = vendor.name;\n item.vendorCode = vendor.code;\n }\n\n $modal.open({\n templateUrl: 'js/modules/item/modals/copy-item-modal.tpl.html',\n controller: 'CopyItemModalController',\n resolve: {\n transferView: function() {\n return item.rental || item.inventoryItem ? 'new' : 'old';\n },\n itemToCopy: function () {\n return item;\n },\n itemPictures: function (ItemPicture) {\n return ItemPicture.query({ filterObject: { inventoryItemId: item.id } });\n },\n },\n windowClass: '__medium',\n backdrop: 'static',\n keyboard: false\n });\n };\n\n /**\n * Watchers\n */\n\n var initializing = true;\n\n $scope.$watch('formValues.vendorId', function(value) {\n if (initializing) {\n $timeout(function() { initializing = false; });\n } else {\n if(!value) {\n $scope.onVendorChange(value);\n }\n }\n });\n\n $scope.$watchGroup(['formValues.inventoryItem', 'formValues.nonInventoryItem', 'formValues.service', 'formValues.rental'], function (values) {\n switch (true) {\n case values[0]:\n $scope.itemType = 'inventoryItem';\n break;\n case values[1]:\n $scope.itemType = 'nonInventoryItem';\n break;\n case values[2]:\n $scope.itemType = 'service';\n break;\n case values[3]:\n $scope.itemType = 'rental';\n break;\n default:\n $scope.itemType = null;\n }\n });\n });\n});\n\n","define('modules/item/config',['./module'], function (module) {\n 'use strict';\n\n module.constant('LABEL_CONFIG', {\n DYMO: {\n SHIPPING: {\n INVENTORY_ITEM_BARCODE_AND_PRICE: \"\\n\" +\n \"\\n\" +\n \" Landscape\\n\" +\n \" Shipping\\n\" +\n \" 30323 Shipping\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" ITEM_NAME\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" ITEM_NAME\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" PRICE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Center\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" PRICE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS2\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS2\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS3\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS3\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS4\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS4\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" DESCRIPTION\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" DESCRIPTION\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" LG_COLOR\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" LG_COLOR\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" SIZE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" SIZE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_SIZES\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_SIZES\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" BARCODE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" True\\n\" +\n \" 1234567\\n\" +\n \" Code128Auto\\n\" +\n \" Medium\\n\" +\n \" Bottom\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" None\\n\" +\n \" 0\\n\" +\n \" Center\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" ORIGINAL_PRICE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Center\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" ORIGINAL_PRICE\\n\" +\n \"\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \"\\n\",\n INVENTORY_ITEM_NO_BARCODE_NO_PRICE: \"\\n\" +\n \"\\n\" +\n \" Landscape\\n\" +\n \" Shipping\\n\" +\n \" 30323 Shipping\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" ITEM_NAME\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" ITEM_NAME\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS2\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS2\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS3\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS3\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS4\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS4\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" DESCRIPTION\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" DESCRIPTION\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" LG_COLOR\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" LG_COLOR\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" SIZE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" SIZE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_SIZES\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_SIZES\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \"\\n\",\n INVENTORY_ITEM_BARCODE_ONLY: \"\\n\" +\n \"\\n\" +\n \" Landscape\\n\" +\n \" Shipping\\n\" +\n \" 30323 Shipping\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" ITEM_NAME\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" ITEM_NAME\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS2\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS2\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS3\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS3\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS4\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS4\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" DESCRIPTION\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" DESCRIPTION\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" LG_COLOR\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" LG_COLOR\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" SIZE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" SIZE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_SIZES\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_SIZES\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" BARCODE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" True\\n\" +\n \" 1234567\\n\" +\n \" Code128Auto\\n\" +\n \" Medium\\n\" +\n \" Bottom\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" None\\n\" +\n \" 0\\n\" +\n \" Center\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \"\\n\",\n INVENTORY_ITEM_PRICE_ONLY: \"\\n\" +\n \"\\n\" +\n \" Landscape\\n\" +\n \" Shipping\\n\" +\n \" 30323 Shipping\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" ITEM_NAME\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" ITEM_NAME\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS2\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS2\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS3\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS3\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS4\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_COLORS4\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" DESCRIPTION\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" DESCRIPTION\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" LG_COLOR\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" LG_COLOR\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" SIZE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" SIZE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_SIZES\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Left\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" AVA_SIZES\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" PRICE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Center\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" PRICE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" ORIGINAL_PRICE\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" Rotation0\\n\" +\n \" False\\n\" +\n \" False\\n\" +\n \" Center\\n\" +\n \" Middle\\n\" +\n \" None\\n\" +\n \" True\\n\" +\n \" False\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" ORIGINAL_PRICE\\n\" +\n \"\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \"\\n\"\n }\n }\n });\n});\n\n","define('modules/marketplace/download/matches-popover-directive',[\n './module',\n 'angular',\n 'text!./matches-popover-directive.tpl.html'\n], function (module, angular, popoverTpl) {\n 'use strict';\n\n module.directive('matchesPopover', function ($compile, $timeout) {\n return {\n restrict: 'A',\n scope: {\n item: '=matchesPopover'\n },\n link: function (scope, element) {\n var popover;\n\n element.click(function () {\n var compilerTpl = $compile('
' + popoverTpl + '
');\n\n // Open popover\n popover = element.popover({\n content: compilerTpl(scope),\n placement: 'bottom',\n trigger: 'manual',\n html: true,\n container: 'body',\n template: '

'\n });\n\n $timeout(function () {\n scope.showPopover();\n }, 0);\n\n });\n\n scope.showPopover = function () {\n popover.popover('show');\n angular.element(document).on('mousedown', hidePopover);\n };\n\n // Close on clicking outside\n function hidePopover(event) {\n var target = angular.element(event.target);\n var isInsidePopover = target.closest('.popover').length && !target.is('a');\n var isTriggerLink = target.is(element);\n\n if (!isInsidePopover && !isTriggerLink) {\n popover.popover('hide');\n angular.element(document).off('mousedown', hidePopover);\n }\n }\n }\n };\n });\n});\n\n","define('modules/prom-registry-modal/register-to-prom-ctrl',['./module', 'angular', 'underscore'], function (module, angular, _) {\n 'use strict';\n\n module.controller('RegisterToPromCtrl', function ($scope, $state, $controller, $modal, security, Contact, modalService, Enums, Item, RegisteredItem, transactionItem, readonly, settings, alerts, contact, successcb) {\n /**\n * Init models\n */\n\n $scope.hasTransactionItem = !!transactionItem;\n $scope.registeredItems = null;\n\n $scope.readonly = readonly || false;\n\n //determine how the user want's their items to be registered (either Item Name only or Item Name and Color\n var registerByItemNameAndColor;\n var registerByVendorItemName;\n var promRegistrationType = _(settings).findWhere({ type: 'PROM_REGISTRATION_TYPE' }) || {};\n switch (promRegistrationType.value) {\n case 'S':\n registerByItemNameAndColor = false;\n break;\n case 'SC':\n registerByItemNameAndColor = true;\n break;\n case 'V':\n registerByVendorItemName = true;\n registerByItemNameAndColor = false;\n break;\n case 'VC':\n registerByVendorItemName = true;\n registerByItemNameAndColor = true;\n break;\n default:\n registerByItemNameAndColor = true;\n }\n\n if (!$scope.hasTransactionItem) {\n $scope.item = {};\n $scope.$watch('item', function (item) {\n if (!item || !item.id) {\n $scope.registeredEventLocationsIds = [];\n return;\n }\n var filterObject = registerByVendorItemName ? { filterObject: { vendorItemName : item.vendorItemName } } : { filterObject: { itemName : item.name } };\n\n if (registerByItemNameAndColor) {\n filterObject.filterObject.itemColor = item.color;\n }\n\n RegisteredItem.query(filterObject, function (registeredItems) {\n $scope.registeredEventLocationsIds = _(registeredItems.result).pluck('eventLocationId');\n }, null, '&validateItems=true');\n }, true);\n } else {\n var filterObject = registerByVendorItemName ? { filterObject: { vendorItemName : transactionItem.itemVendorItemName } } : { filterObject: { itemName : transactionItem.itemName } };\n\n if (registerByItemNameAndColor) {\n filterObject.filterObject.itemColor = transactionItem.itemColor;\n }\n\n RegisteredItem.query(filterObject, function (registeredItems) {\n $scope.registeredItems = registeredItems.result;\n $scope.registeredEventLocationsIds = _($scope.registeredItems).pluck('eventLocationId');\n }, null, '&validateItems=true');\n }\n\n $scope.filterObject = {\n status: Enums.statuses.active.value\n };\n $scope.eventTypes = _(Enums.eventTypes).values();\n $scope.filterObject.eventTypeId = Enums.eventTypes.prom.value;\n\n $scope.itemSelectorOptions = {\n settingsPopoverPlacement: 'bottom',\n onChooseItem: function (item) {\n $scope.item = item;\n },\n onAddNewItem: function (item) {\n $scope.item = item;\n }\n };\n\n /**\n * Methods\n */\n\n $scope.registerEventLocations = function () {\n // get all checked ELs\n var checkedEventLocations = _($scope.resources).where({ checked: true });\n\n if (!checkedEventLocations.length) {\n return;\n }\n\n // convert it to RIs\n var newRegisteredItems = _(checkedEventLocations).map(eventLocationToRegisterItem);\n\n var onDone = _.after(newRegisteredItems.length, function () {\n\n if(contact && security.hasPermission('CONTACTS')) {\n var locationsWithDates = _(checkedEventLocations).filter(function(location) {\n return location.date;\n });\n\n if (locationsWithDates && locationsWithDates.length) {\n if(locationsWithDates.length > 1 || locationsWithDates[0].date !== contact.eventDate) {\n modalService.showConfirmation('alerts.prom-registry.contact-event-date-different', function () {\n if(locationsWithDates.length > 1) {\n //open modal\n $modal.open({\n templateUrl: 'js/modules/prom-registry-modal/select-location-modal.tpl.html',\n controller: 'SelectLocationModalCtrl',\n resolve: {\n locations: function () {\n return locationsWithDates;\n }\n },\n windowClass: '__medium'\n }).result.then(function(result) {\n if(result) {\n updateContactsEeventDate(contact, result);\n }\n });\n } else {\n updateContactsEeventDate(contact, locationsWithDates[0]);\n }\n });\n }\n }\n }\n\n alerts.pushSuccess('alerts.prom-registry.successfully-registered-item');\n $scope.$close(true);\n });\n\n // POST each RI to the server\n _(newRegisteredItems).each(function (registeredItem) {\n var registeredItemResource = new RegisteredItem(registeredItem);\n registeredItemResource.$save(onDone);\n });\n };\n\n $scope.rejectNew = function (location) {\n return !location.isNew;\n };\n\n function updateContactsEeventDate(contact, location) {\n Contact.updateEventDate(contact.id ,location.date, function (updatedContact) {\n successcb && successcb(updatedContact);\n });\n }\n\n /**\n * Helpers\n */\n\n function eventLocationToRegisterItem(eventLocation) {\n var result;\n\n if ($scope.hasTransactionItem) {\n result = {\n itemId: transactionItem.inventoryItemId,\n itemColor: transactionItem.itemColor,\n itemSize: transactionItem.itemSize,\n transactionId: transactionItem.transactionId,\n eventLocationId: eventLocation.id\n };\n } else {\n result = {\n itemId: $scope.item.id,\n itemColor: $scope.item.color,\n itemSize: $scope.item.size,\n eventLocationId: eventLocation.id\n };\n }\n\n return result;\n }\n\n /**\n * Watchers\n */\n\n // reset checked event location on event type changing\n $scope.$watch('filterObject.eventTypeId', function () {\n _($scope.resources).each(function (eventLocation) {\n eventLocation.checked = null;\n });\n });\n\n // set form validity\n $scope.$watch('resources', function (eventLocations) {\n $scope.isFormInvalid = !_(eventLocations).where({ checked: true }).length;\n }, true);\n\n /**\n * Init\n */\n\n var dependencies = {\n $scope: _($scope).extend({\n prefilledModel: $scope.filterObject\n })\n };\n\n // get access to onAddClick()\n _(this).extend($controller('SettingsEventLocationCtrl', dependencies));\n\n $scope.openAddEventLocationModal = function () {\n $scope\n .onAddClick()\n .then(function (eventLocation) {\n var foundLocation = _($scope.resources).findWhere({ id: eventLocation.id });\n foundLocation.isNew = true;\n foundLocation.checked = true;\n\n // Scroll inner table scroll to top so user can see recently added locations\n angular.element('.event-locations-table').scrollTop(0);\n });\n };\n });\n});\n\n","define('modules/resources/purchase-order',['angular', 'moment', 'underscore', './backend-resource'], function (angular, moment, _) {\n 'use strict';\n\n return angular.module('bl.resources.purchase-order', ['bl.resources.backend-resource'])\n .factory('PurchaseOrder', function (backendResource, $http, $window, security, CompanySetting, UtilsHelper, PrintHelper) {\n\n var resource = backendResource('purchaseOrders');\n\n resource.associatedWithContact = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(resource.url + '/associatedWithContact/' +\n (filterObj.filterObject.contactId || 0) + '?' +\n queryParameters.join('&'));\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.createForTrxItems = function (employeeId, doCopyNotes, transactionItems, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/createForTrxItems/' + employeeId + '/' + doCopyNotes, transactionItems);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.containingItem = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(resource.url + '/containingItem/' +\n (filterObj.filterObject.startDate ? moment(filterObj.filterObject.startDate).format('YYYY-MM-DD') : 'null') + '/' +\n (filterObj.filterObject.endDate ? moment(filterObj.filterObject.endDate).format('YYYY-MM-DD') : 'null') + '?' +\n queryParameters.join('&') +\n '&vendorItemName=' + (filterObj.filterObject.vendorItemName || \"NONE\")\n );\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.unconfirmedPOs = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(resource.url + '/unconfirmedPOs/' +\n (filterObj.filterObject.vendorId || 0) + '?' +\n 'eventDateStart=' + (filterObj.filterObject.eventDateAfter ? moment(filterObj.filterObject.eventDateAfter).format('YYYY-MM-DD') : '') + '&' +\n 'eventDateEnd=' + (filterObj.filterObject.eventDateBefore ? moment(filterObj.filterObject.eventDateBefore).format('YYYY-MM-DD') : '') + '&' +\n queryParameters.join('&'));\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.unsubmittedPOs = function (filterObj, successcb, errorcb) {\n var queryParameters = resource.buildQueryParameters(filterObj);\n var httpPromise = $http.get(resource.url + '/unsubmittedPOs/' +\n (filterObj.filterObject.vendorId || 0) + '?' +\n 'eventDateStart=' + (filterObj.filterObject.eventDateAfter ? moment(filterObj.filterObject.eventDateAfter).format('YYYY-MM-DD') : '') + '&' +\n 'eventDateEnd=' + (filterObj.filterObject.eventDateBefore ? moment(filterObj.filterObject.eventDateBefore).format('YYYY-MM-DD') : '') + '&' +\n queryParameters.join('&'));\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.pastShipDatePOs = function (settings, successcb, errorcb) {\n var filterObj = {\n shipDateBefore: moment().subtract(UtilsHelper.getDaysFromWeeks(settings, CompanySetting.PO_PENDING_PO_PAST_SHIPPING_WINDOW), 'days').format('YYYY-MM-DD'),\n status: 'P'\n };\n\n var httpPromise = $http.post(resource.url + '/list', filterObj);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.readByNumber = function (number, successcb, errorcb) {\n number = String(number).replace(/[^\\d]/g, '');\n\n var httpPromise = $http.get(resource.url + '/readByNumber/' + number);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb);\n };\n\n resource.print = function (id) {\n var token = encodeURIComponent(security.readCookie().token);\n PrintHelper.printPDF(resource.url + '/' + id + '/po.pdf?token=' + token);\n };\n\n resource.addLineItem = function (purchaseOrderItem, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/' + purchaseOrderItem.purchaseOrderId + '/addLineItem', purchaseOrderItem);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb);\n };\n\n resource.updateLineItem = function (purchaseOrderItem, syncChangesToSO, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/' + purchaseOrderItem.purchaseOrderId + '/updateLineItem/' + syncChangesToSO, purchaseOrderItem);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb);\n };\n\n resource.deleteLineItem = function (purchaseOrderItem, employeeId, successcb, errorcb) {\n var httpPromise = $http.delete(resource.url + '/' + purchaseOrderItem.purchaseOrderId + '/deleteLineItem/' + purchaseOrderItem.id + '/' + employeeId);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb);\n };\n\n resource.deleteLineItemAddOn = function (addOnItem, employeeId, successcb, errorcb) {\n var httpPromise = $http.delete(resource.url + '/' + addOnItem.purchaseOrderId + '/deleteLineItemAddOn/' + addOnItem.id + '/' + employeeId);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb);\n };\n\n resource.deleteLineItems = function (purchaseOrderId, employeeId, ids, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/' + purchaseOrderId + '/deleteLineItems/' + employeeId, ids);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb);\n };\n\n resource.void = function (purchaseOrderId, employeeId, successcb, errorcb) {\n var httpPromise = $http.put(resource.url + '/' + purchaseOrderId + '/voidPurchaseOrder/' + employeeId);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb);\n };\n\n resource.bulkPrint = function (ids) {\n var param = \"\";\n for (var i = 0; i < ids.length; i++) {\n param += \"id=\" + ids[i] + \"&\";\n }\n\n var token = encodeURIComponent(security.readCookie().token);\n PrintHelper.printPDF(resource.url + '/printMultiple.pdf?token=' + token + \"&\" + param, true);\n };\n\n resource.previewForTrxs = function (ids, successcb, errorcb) {\n var payload = _(ids).map(function (id) {\n return { id: id };\n });\n\n var httpPromise = $http.post(resource.url + '/previewForTrxs', payload);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.listByIds = function (ids, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/listByIds', ids);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb);\n };\n\n resource.getTrxLineItemsFromPOItemIds = function (ids, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/getTrxLineItemsFromPOItemIds', ids);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, true);\n };\n\n resource.bulkUpdateEmployee = function (empId, idList, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/bulkUpdateEmployee/' + empId, idList);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.createPOForItems = function (vendorId, employeeId, idList, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/createPOForItems/' + vendorId + '/' + employeeId, idList);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.updateContactAssociatedWithPOItems = function (contactId, transactionId, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/updateContactAssociatedWithPOItems/' + contactId + '/' + transactionId, {});\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n resource.sendPurchaseOrder = function(request, successcb, errorcb) {\n var httpPromise = $http.post(resource.url + '/sendPurchaseOrder', request);\n return resource.thenFactoryMethod(httpPromise, successcb, errorcb, false);\n };\n\n return resource;\n });\n});\n\n","define('modules/purchase-order/purchase-order-ctrl',['./module', 'angular', 'underscore', 'moment'], function (module, angular, _, moment) {\n 'use strict';\n\n module.controller('PurchaseOrderController', function (\n $compile,\n $scope,\n $rootScope,\n $window,\n $state,\n $timeout,\n $translate,\n $locale,\n $filter,\n $modal,\n Permissions,\n eventsBus,\n Enums,\n modalService,\n EmailService,\n Email,\n purchaseOrder,\n ResourcesHelper,\n security,\n Item,\n ItemModal,\n ItemAddOn,\n ItemHelper,\n PurchaseOrder,\n PurchaseOrderItem,\n PurchaseOrderItemAddOn,\n ReceivingVoucher,\n Vendor,\n Contact,\n ContactModal,\n CompanySetting,\n alerts,\n employees,\n settings,\n User,\n itemSizesModal\n ) {\n /**\n * Init models\n */\n $scope.selectedResults = [];\n $scope.locale = $locale;\n $scope.sortType = 'sequenceNumber'; // set the default sort type\n $scope.sortReverse = false; // set the default sort order\n $scope.hooks = [];\n\n $scope.poItemHeaders = [\n {\n title: 'item.vendor-name',\n sortField:'itemVendorItemName',\n active: true\n },\n {\n title: 'common.color',\n css: { minWidth: 100 },\n sortField:'itemColor',\n active: false\n },\n {\n title: 'purchase-order.acc-color',\n css: { minWidth: 100 },\n sortField:'itemColor2',\n active: false\n },\n {\n title: 'common.size',\n css: { width: 75 },\n sortField:'itemSize',\n active: false\n },\n {\n title: 'item.qty',\n css: { width: 78 },\n sortField:'quantity',\n active: false\n },\n {\n title: 'contact.purchase.headers.qty-recv',\n sortField:'quantityReceived',\n active: false,\n css: { width: 75 }\n },\n {\n title: 'purchase-order.voucher-number',\n css: { width: 90 }\n },\n {\n title: 'item.order-cost',\n sortField:'cost',\n active: false,\n css: { width: 100 }\n },\n {\n title: $locale.vatLabelKey,\n sortField:'vat',\n active: false,\n css: { width: 100 },\n isHidden: !$scope.locale.usesVat\n },\n {\n title: 'item.ext-cost',\n sortField:'extCost',\n active: false,\n css: { width: 100 }\n }\n ];\n\n $scope.sortHeader = function (header) {\n if(header && header.active) {\n $scope.sortReverse = !$scope.sortReverse;\n }\n\n _.each($scope.poItemHeaders, function (poItemHeader) {\n poItemHeader.active = poItemHeader.sortField && poItemHeader.sortField === header.sortField ? true: false;\n });\n\n $scope.sortType = header.sortField;\n\n $scope.purchaseOrder.lineItems = $filter('orderBy')($scope.purchaseOrder.lineItems, $scope.sortType, $scope.sortReverse);\n\n $scope.updateSequence();\n };\n\n var ignoreRedirectWarning = false;\n $scope.employees = ResourcesHelper.adaptList('employees', employees);\n $scope.purchaseOrder = purchaseOrder;\n $scope.readonly = $scope.purchaseOrder.status === Enums.statuses.complete.value\n || $scope.purchaseOrder.status === Enums.statuses.voided.value\n || !security.hasPermission(\"EDIT_PURCHASE_ORDERS\");\n\n $scope.itemAddOnsPerm = {\n add: security.hasPermission(Permissions.ADD_PO_ITEM_ADD_ON),\n set: security.hasPermission(Permissions.SELECT_PO_ITEM_ADD_ON),\n editNotes: security.hasPermission(Permissions.EDIT_PO_ITEM_ADD_ON_NOTE),\n editDesc: security.hasPermission(Permissions.EDIT_PO_ITEM_ADD_ON_DESC),\n editCost: security.hasPermission(Permissions.EDIT_PO_ITEM_ADD_ON_COST),\n remove: security.hasPermission(Permissions.REMOVE_PO_ITEM_ADD_ON),\n addOnRequired: security.hasPermission(Permissions.PO_ITEM_ADD_ON_REQUIRED)\n };\n\n // Sort line items on init\n $scope.purchaseOrder.lineItems = _($scope.purchaseOrder.lineItems).sortBy('sequenceNumber');\n\n $scope.orderTypes = [\n Enums.purchaseOrderTypes.stock,\n Enums.purchaseOrderTypes.customer\n ];\n\n $scope.itemSelectorOptions = {\n searchField: 'vendorItemName',\n addNewItemSaveButtonLabel: $translate.instant('purchase-order.save-and-add'),\n additionalFilterObject: { 'vendorId': $scope.purchaseOrder.vendorId },\n prefillObject: { 'vendorId': $scope.purchaseOrder.vendorId },\n onAddNewItem: getAllItemValues,\n onChooseItem: getAllItemValues\n };\n\n function getAllItemValues(item) {\n ItemAddOn.listByItemId(item.id, function(itemAddOns) {\n item.itemAddOns = itemAddOns;\n onAddLineItem(item);\n });\n }\n\n function onAddLineItem(item) {\n var poItem = itemToPurchaseOrderItem(item);\n $scope.isNewPurchaseOrder = false;\n\n PurchaseOrder.addLineItem(poItem, function(purchaseOrder) {\n angular.extend($scope.purchaseOrder, purchaseOrder);\n if($scope.purchaseOrder.lineItems.length === 1) {\n $scope.purchaseOrder.vendorName = item.vendorName;\n $scope.purchaseOrder.vendorId = item.vendorId;\n $scope.savePurchaseOrder();\n }\n\n $scope.getAvailableAddOnsAndOpenModal(_(purchaseOrder.lineItems).last(), item, { showModalOnlyIfAddOnsAvailable: true, fetchItemAddOns: $scope.itemAddOnsPerm.set });\n });\n }\n\n function openAddOnModal(poItem, addOnsResult, options) {\n var allowedToClose = !$scope.itemAddOnsPerm.addOnRequired;\n\n if(options && options.userSelected) {\n allowedToClose = true;\n }\n\n $modal.open({\n templateUrl: 'js/modules/transaction/details/modals/add-item-add-ons.tpl.html',\n controller: 'AddItemAddOnsCtrl',\n windowClass: '__large',\n backdrop: 'static',\n keyboard: allowedToClose,\n resolve: {\n entityType: function() {\n return 'purchaseOrder';\n },\n entityItem: function () {\n return poItem;\n },\n addOnsResult: function () {\n return addOnsResult;\n },\n item: function () {\n return addOnsResult.item;\n },\n allowedToClose: function () {\n return allowedToClose;\n }\n }\n })\n .result\n .then(function (addOnsModalResult) {\n var poItemModifications = addOnsModalResult && addOnsModalResult.poItemModifications;\n if(poItemModifications && poItemModifications.lineItemAddOns && poItemModifications.lineItemAddOns.length) {\n $scope.savePurchaseOrderItem(_.extend(poItem, poItemModifications));\n }\n });\n }\n\n $scope.addItemAddOn = function(poItem) {\n if($scope.readonly || !$scope.itemAddOnsPerm.set) {\n return;\n }\n\n getAvailableAddItemsOnsAndOpenModal(poItem, null, { fetchItemAddOns: true, showModalOnlyIfAddOnsAvailable: false, userSelected: true });\n };\n\n $scope.getAvailableAddOnsAndOpenModal = function(purchaseOrderItem, item, options, callback) {\n var addOnRequest = {\n leadTimes: false,\n itemAddOns: options.fetchItemAddOns,\n purchaseOrder: $scope.purchaseOrder,\n purchaseOrderItem: purchaseOrderItem,\n item: item\n };\n\n PurchaseOrderItem.getAvailableAddOns(addOnRequest, function (addOnsResult) {\n if(addOnsResult.itemAddOns === null) {\n addOnsResult.itemAddOns = [];\n }\n\n var lineItemAddOns = _(purchaseOrderItem.lineItemAddOns).filter(function(addOn) {\n return addOn.addOnId !== 0 && addOn.addOnId !== null;\n });\n\n if(options.showModalOnlyIfAddOnsAvailable && addOnRequest && addOnRequest.itemAddOns && addOnsResult.itemAddOns.length > 0 && lineItemAddOns.length !== addOnsResult.itemAddOns.length) {\n openAddOnModal(purchaseOrderItem, addOnsResult, { userSelected: purchaseOrderItem.lineItemAddOns && purchaseOrderItem.lineItemAddOns.length });\n }\n });\n };\n\n $scope.switchToEdit = function(event, addOn, type, index) {\n if(event) {\n event.preventDefault();\n }\n\n addOn[type + 'OldValue'] = addOn[type];\n addOn.show = {};\n addOn.show[type] = index;\n };\n\n $scope.switchToView = function (event, addOn, poItem, type, index) {\n if(!addOn.show) {\n return;\n }\n\n if(event) {\n event.preventDefault();\n }\n\n var oldValue = addOn[type + 'OldValue'];\n\n if(oldValue !== undefined && oldValue !== addOn[type]) {\n if($scope.validateAddOnItemValue(type, addOn, oldValue, poItem)) {\n if(type === 'cost') {\n if(!addOn.cost) {\n addOn.cost = 0;\n }\n\n $scope.onAddOnItemCostChange(poItem, addOn.cost, oldValue, index);\n } else if(type === 'description') {\n $scope.savePurchaseOrderItem(poItem, false, function () {\n alerts.pushSuccess('alerts.transaction.successfully-updated-add-on-item');\n });\n }\n } else {\n addOn[type] = oldValue;\n delete addOn[type + 'OldValue'];\n }\n }\n\n delete addOn.show;\n };\n\n $scope.onAddOnItemCostChange = function(poItem, newValue, oldValue) {\n newValue = +newValue;\n\n if(newValue > oldValue) {\n poItem.cost = poItem.cost + (newValue - oldValue);\n poItem.extCost = poItem.extCost + (newValue - oldValue);\n } else {\n poItem.cost = poItem.cost - (oldValue - newValue);\n poItem.extCost = poItem.extCost - (oldValue - newValue);\n }\n\n if ($scope.locale.usesVat && $scope.purchaseOrder.vendor) {\n var vatPercent = $scope.purchaseOrder.vendor.vatPercent ? parseFloat($scope.purchaseOrder.vendor.vatPercent) : 0;\n poItem.vat = poItem.cost * vatPercent / 100;\n }\n\n $scope.savePurchaseOrderItem(poItem, false, function () {\n alerts.pushSuccess('alerts.transaction.successfully-updated-add-on-item');\n });\n };\n\n $scope.sortableOptions = {\n tolerance: 'pointer',\n revert: 100,\n distance: 5,\n forcePlaceholderSize: true,\n handle: \".handle\",\n helper: function (e, ui) {\n ui.children().each(function () {\n $(this).width($(this).width());\n });\n\n return ui;\n },\n stop: function () {\n // Reindex line items\n _($scope.purchaseOrder.lineItems).each(function (line, index) {\n line.sequenceNumber = index;\n });\n\n $scope.savePurchaseOrder();\n }\n };\n\n /**\n * Methods\n */\n\n $scope.sendPurchaseOrder = function(hook) {\n modalService.showStaticConfirmation({ key: 'purchase-order.would-like-to-send-po?', params: { url: hook.value }}, function () {\n $scope.sendingPO = true;\n\n var request = { id: $scope.purchaseOrder.id, employeeId: User.id, endPointURL: hook.value };\n PurchaseOrder.sendPurchaseOrder(request, function(response) {\n $scope.sendingPO = false;\n\n if(response && response.status === 200) {\n hook.sent = true;\n alerts.push({ key: 'purchase-order.send-po-success', params: { url: hook.value }});\n if(!$scope.purchaseOrder.submittedDate) {\n modalService.showConfirmation('purchase-order.would-like-to-update-submitted-date?', function() {\n $scope.purchaseOrder.submittedDate = new Date();\n $scope.savePurchaseOrder();\n });\n }\n } else {\n alerts.pushError({ key: 'purchase-order.send-po-error', params: { url: hook.value }});\n hook.sent = false;\n }\n }, function (data, status) {\n PurchaseOrder.defaultErrorHandler(data, status);\n alerts.pushError({ key: 'purchase-order.send-po-error', params: { url: hook.value }});\n $scope.sendingPO = false;\n hook.sent = true;\n });\n });\n };\n\n //Update shipping date\n $scope.updateShippingDate = function(shipDateUpdated) {\n if(shipDateUpdated && (!$scope.purchaseOrder.lineItems || !$scope.purchaseOrder.lineItems.length)) {\n return;\n }\n\n if (!$scope.purchaseOrder.lineItems || !$scope.purchaseOrder.lineItems.length) {\n modalService.showMessage('purchase-order.po-items-required-before-updating-est-arrival-date', 'common.message.wooops');\n return false;\n }\n\n modalService.showConfirmation('purchase-order.would-like-to-update-estimated-ship-dates?', function () {\n var ids = _($scope.purchaseOrder.lineItems).pluck('id');\n\n $modal.open({\n templateUrl: 'js/modules/purchase-order/est-ship-date/edit-est-ship-date-modal.tpl.html',\n controller: \"EditEstShipDateModalCtrl\",\n resolve: {\n lineItems: function (PurchaseOrder) {\n return PurchaseOrder.getTrxLineItemsFromPOItemIds(ids);\n },\n poShippingDate: function () {\n return $scope.purchaseOrder.shipDate;\n },\n settings: function () {\n return settings;\n }\n },\n backdrop: 'static',\n windowClass: '__large'\n });\n });\n };\n\n $scope.updateSequence = function () {\n if($scope.queriesInProgress === 0) {\n _($scope.purchaseOrder.lineItems).each(function (line, index) {\n line.sequenceNumber = index;\n });\n\n $scope.savePurchaseOrder();\n }\n };\n\n $scope.recalculateVat = function (item) {\n if ($scope.locale.usesVat && $scope.purchaseOrder.vendor) {\n var vatPercent = $scope.purchaseOrder.vendor.vatPercent ? parseFloat($scope.purchaseOrder.vendor.vatPercent) : 0;\n item.vat = item.cost * vatPercent / 100;\n }\n };\n\n $scope.queriesInProgress = 0;\n\n $scope.savePurchaseOrderItem = function (poItem, syncChangesToSO, callback) {\n $scope.queriesInProgress += 1;\n var purchaseOrderItem = new PurchaseOrderItem(_(poItem).omit('checked'));\n purchaseOrderItem.modifiedDate = Date.now();\n purchaseOrderItem.modifiedByUser = User.username;\n\n PurchaseOrder.updateLineItem(purchaseOrderItem, syncChangesToSO || false, function (savedPurchaseOrder) {\n angular.extend($scope.purchaseOrder, _(savedPurchaseOrder).omit('lineItems'));\n _($scope.purchaseOrder.lineItems).each(function (item, index) {\n _(item).extend(savedPurchaseOrder.lineItems[index]);\n\n _(item.lineItemAddOns).each(function (addOn, i) {\n if(savedPurchaseOrder.lineItems[index].lineItemAddOns && savedPurchaseOrder.lineItems[index].lineItemAddOns.length && savedPurchaseOrder.lineItems[index].lineItemAddOns[i]) {\n addOn.version = savedPurchaseOrder.lineItems[index].lineItemAddOns[i].version;\n }\n });\n });\n\n if(callback) {\n callback();\n }\n\n }).finally(function () {\n // without timeout saving state will be \"jumpy\"\n $timeout(function () {\n $scope.queriesInProgress -= 1;\n }, 1000);\n });\n };\n\n $scope.savePurchaseOrder = _.debounce(function (typeChanged) {\n $scope.queriesInProgress += 1;\n $scope.purchaseOrder.modifiedDate = Date.now();\n $scope.purchaseOrder.modifiedByUser = User.username;\n\n var employee = _.findWhere($scope.employees, { id: $scope.purchaseOrder.employeeId });\n $scope.purchaseOrder.employeeName = employee ? employee.fullName : $translate.instant('appointment.filter-panels.unassigned');\n\n var localPurchaseOrder = _($scope.purchaseOrder).clone();\n\n // Omit the checked property from each lineItem\n localPurchaseOrder.lineItems = _(localPurchaseOrder.lineItems).map(function (poItem) {\n return _(poItem).omit('checked');\n });\n\n localPurchaseOrder.$saveOrUpdate(function (savedPurchaseOrder) {\n $scope.isNewPurchaseOrder = false;\n\n if(typeChanged === 'shipDate') {\n var setting = _(settings).findWhere({ type: 'PO_PROMPT_EST_ARRIVAL_DATE_WHEN_SHIP_DATE_CHANGES' });\n\n if(setting && setting.value === 'Y') {\n $scope.updateShippingDate(true);\n }\n }\n\n angular.extend($scope.purchaseOrder, _(savedPurchaseOrder).omit(\n 'lineItems',\n 'orderDate',\n 'employeeId',\n 'cancelDate',\n 'submittedDate',\n 'shipDate',\n 'confirmationNumber',\n 'notes',\n 'discountAmount',\n 'fee'\n ));\n\n _($scope.purchaseOrder.lineItems).each(function (poItem, index) {\n poItem.version = savedPurchaseOrder.lineItems[index].version;\n\n _(poItem.lineItemAddOns).each(function (addOn, i) {\n if(savedPurchaseOrder.lineItems[index].lineItemAddOns && savedPurchaseOrder.lineItems[index].lineItemAddOns.length && savedPurchaseOrder.lineItems[index].lineItemAddOns[i]) {\n addOn.version = savedPurchaseOrder.lineItems[index].lineItemAddOns[i].version;\n }\n });\n });\n }).finally(function () {\n $scope.queriesInProgress -= 1;\n });\n }, 1000);\n\n $scope.completeOrder = function () {\n modalService.showConfirmation('purchase-order.would-like-to-complete?', function () {\n $scope.purchaseOrder.status = Enums.statuses.complete.value;\n\n _($scope.purchaseOrder.lineItems).each(function(lineItem) {\n lineItem.status = Enums.statuses.complete.value;\n });\n\n $scope.readonly = true;\n $scope.savePurchaseOrder();\n alerts.pushSuccess('alerts.purchase-order.successfully-completed');\n });\n };\n\n $scope.removeAddOnItem = function (addOnItem, purchaseOrderItem) {\n if($scope.readonly) {\n return;\n }\n\n modalService.showConfirmation('purchase-order.would-like-to-delete-add-on-item?', function () {\n for(var i = 0; i < $scope.purchaseOrder.lineItems.length; i++) {\n for(var j = 0; j < $scope.purchaseOrder.lineItems[i].lineItemAddOns.length; j++) {\n var addOn = $scope.purchaseOrder.lineItems[i].lineItemAddOns[j];\n\n if(addOn && addOn.id === addOnItem.id) {\n $scope.purchaseOrder.lineItems[i].lineItemAddOns = _($scope.purchaseOrder.lineItems[i].lineItemAddOns).without(addOnItem);\n break;\n }\n }\n }\n\n PurchaseOrder.deleteLineItemAddOn(addOnItem, User.id, function (purchaseOrder) {\n $scope.purchaseOrder.modifiedDate = Date.now();\n $scope.purchaseOrder.modifiedByUser = User.username;\n\n var savedPurchaseOrderItem = _(purchaseOrder.lineItems).findWhere({ id: purchaseOrderItem.id });\n // Update special field of current line item\n purchaseOrderItem.cost = savedPurchaseOrderItem.cost;\n purchaseOrderItem.extCost = savedPurchaseOrderItem.extCost;\n purchaseOrderItem.vat = savedPurchaseOrderItem.vat;\n\n angular.extend($scope.purchaseOrder, _(purchaseOrder).omit('lineItems'));\n _($scope.purchaseOrder.lineItems).each(function (item, index) {\n item.version = purchaseOrder.lineItems[index].version;\n\n _(item.lineItemAddOns).each(function (addOn, i) {\n if(purchaseOrder.lineItems[index].lineItemAddOns && purchaseOrder.lineItems[index].lineItemAddOns.length && purchaseOrder.lineItems[index].lineItemAddOns[i]) {\n addOn.version = purchaseOrder.lineItems[index].lineItemAddOns[i].version;\n }\n });\n });\n alerts.pushSuccess('alerts.purchase-order.successfully-deleted-item');\n });\n });\n };\n\n $scope.removeLineItem = function (purchaseOrderItem) {\n modalService.showConfirmation('purchase-order.would-like-to-delete-item?', function () {\n $scope.purchaseOrder.lineItems = _($scope.purchaseOrder.lineItems).without(purchaseOrderItem);\n\n PurchaseOrder.deleteLineItem(purchaseOrderItem, User.id, function (purchaseOrder) {\n $scope.purchaseOrder.modifiedDate = Date.now();\n $scope.purchaseOrder.modifiedByUser = User.username;\n angular.extend($scope.purchaseOrder, _(purchaseOrder).omit('lineItems'));\n _($scope.purchaseOrder.lineItems).each(function (item, index) {\n item.version = purchaseOrder.lineItems[index].version;\n\n _(item.lineItemAddOns).each(function (addOn, i) {\n if(purchaseOrder.lineItems[index].lineItemAddOns && purchaseOrder.lineItems[index].lineItemAddOns.length && purchaseOrder.lineItems[index].lineItemAddOns[i]) {\n addOn.version = purchaseOrder.lineItems[index].lineItemAddOns[i].version;\n }\n });\n });\n alerts.pushSuccess('alerts.purchase-order.successfully-deleted-item');\n });\n });\n };\n\n $scope.removeLineItems = function () {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('voucher.message.select-at-least-one-receiving', 'common.message.wooops');\n return false;\n }\n\n var selectedLength = $scope.selectedResults.length;\n\n modalService.showConfirmation({\n key:'purchase-order.would-like-to-delete-items?',\n params: { number: selectedLength }\n }, function () {\n PurchaseOrder.deleteLineItems($scope.purchaseOrder.id, User.id, _($scope.selectedResults).pluck('id'), function (purchaseOrder) {\n $scope.toggleSelectAll(true);\n $scope.purchaseOrder.modifiedDate = Date.now();\n $scope.purchaseOrder.modifiedByUser = User.username;\n angular.extend($scope.purchaseOrder, purchaseOrder);\n if($scope.purchaseOrder.lineItems && $scope.purchaseOrder.lineItems.length) {\n _($scope.purchaseOrder.lineItems).each(function (item, index) {\n item.version = purchaseOrder.lineItems[index].version;\n\n _(item.lineItemAddOns).each(function (addOn, i) {\n if(purchaseOrder.lineItems[index].lineItemAddOns && purchaseOrder.lineItems[index].lineItemAddOns.length && purchaseOrder.lineItems[index].lineItemAddOns[i]) {\n addOn.version = purchaseOrder.lineItems[index].lineItemAddOns[i].version;\n }\n });\n });\n }\n\n alerts.pushSuccess({ key:'alerts.purchase-order.successfully-deleted-items', params: { number: selectedLength }});\n });\n });\n };\n\n $scope.print = function () {\n PurchaseOrder.print($scope.purchaseOrder.id);\n };\n\n $scope.voidOrder = function () {\n modalService.showConfirmation('purchase-order.would-like-to-void?',\n function () {\n PurchaseOrder.void($scope.purchaseOrder.id, User.id, function (purchaseOrder) {\n $scope.readonly = true;\n $scope.purchaseOrder.modifiedByUser = purchaseOrder.modifiedByUser;\n $scope.purchaseOrder.modifiedDate = purchaseOrder.modifiedDate;\n $scope.purchaseOrder.status = purchaseOrder.status;\n alerts.pushSuccess('alerts.purchase-order.successfully-voided');\n });\n });\n };\n\n $scope.deleteOrder = function () {\n modalService.showConfirmation('purchase-order.would-like-to-delete-along-with-vouchers?', function () {\n $scope.purchaseOrder.$remove().then(function () {\n ignoreRedirectWarning = true;\n alerts.pushSuccess('alerts.purchase-order.has-been-deleted-successfully');\n $state.go('purchase-orders');\n });\n });\n };\n\n $scope.showSendEmailModalVendor = function () {\n Vendor.getById($scope.purchaseOrder.vendorId, function (vendor) {\n var modal = EmailService.showSendModal(vendor, null, Email.VENDOR_TYPE, null, $scope.purchaseOrder);\n if(modal) {\n modal.result.then(function(email) {\n if(!email) {\n return;\n }\n\n if(!$scope.purchaseOrder.submittedDate) {\n modalService.showConfirmation('purchase-order.would-like-to-update-submitted-date?', function() {\n $scope.purchaseOrder.submittedDate = new Date();\n $scope.savePurchaseOrder();\n });\n }\n });\n }\n });\n };\n\n $scope.receiveItems = function () {\n var selectedItems = ($scope.purchaseOrder.lineItems.length === 1 && [$scope.purchaseOrder.lineItems[0]]) || _($scope.purchaseOrder.lineItems).where({ checked: true });\n\n if (!$scope.purchaseOrder.vendorId) {\n return modalService.showMessage('purchase-order.assign-vendor-before');\n }\n\n if (selectedItems.length) {\n // Omit the checked property from each lineItem\n selectedItems = _(selectedItems).map(function (poItem) {\n return _(poItem).omit('checked');\n });\n\n ReceivingVoucher.createForPOItems($scope.purchaseOrder.vendorId, User.id, selectedItems, function (receivingVoucher) {\n alerts.push({\n key: 'alerts.purchase-order.successfully-created-voucher',\n params: { number: receivingVoucher.receivingVoucherNumber }\n });\n $state.go('receiving-voucher.edit', { id: receivingVoucher.id });\n });\n } else {\n modalService.showMessage('purchase-order.select-one-line-item');\n }\n };\n\n $scope.selectAll = false;\n $scope.toggleSelectAll = function (removeAll) {\n if(removeAll) {\n $scope.selectAll = false;\n } else {\n $scope.selectAll = !$scope.selectAll;\n }\n\n var checkedPOItems = [];\n _($scope.purchaseOrder.lineItems).each(function (poItem) {\n if (poItem.quantity > poItem.quantityReceived) {\n poItem.checked = $scope.selectAll;\n checkedPOItems.push(poItem);\n }\n });\n\n if ($scope.selectAll) {\n $scope.selectedResults = _.union($scope.selectedResults, checkedPOItems);\n } else {\n $scope.selectedResults = removeAll ? [] : _($scope.selectedResults).difference(checkedPOItems);\n }\n };\n\n $scope.validateAddOnItemValue = function(type, addOn, oldValue) {\n if(oldValue === addOn[type]) {\n return false;\n }\n\n if(type === 'cost') {\n if(addOn[type] < 0) {\n modalService.showMessage('alerts.add-ons.invalid-cost');\n return false;\n } else if(!addOn[type]) {\n addOn[type] = 0;\n }\n } else if(type === 'description') {\n if(addOn[type] === '') {\n modalService.showMessage('alerts.add-ons.invalid-description');\n return false;\n }\n }\n\n return true;\n };\n\n $scope.collapseRow = function(event, poItem) {\n if(event) {\n event.preventDefault();\n }\n\n poItem.collapsed = !poItem.collapsed;\n };\n\n $scope.syncSelectedResults = function (obj) {\n if(obj.quantity <= obj.quantityReceived) {\n return;\n }\n\n var checkedItWasSelected = _($scope.selectedResults).findWhere({ id: obj.id });\n if (checkedItWasSelected) {\n $scope.selectedResults = _($scope.selectedResults).without(checkedItWasSelected);\n } else {\n $scope.selectedResults.push(obj);\n }\n };\n\n $scope.gotoContact = function (poItem) {\n $state.go('contact.personal_info', { id: poItem.contactId });\n };\n\n $scope.showSendEmailModalContact = function (poItem) {\n Contact.getById(poItem.contactId, function (contact) {\n EmailService.showSendModal(contact, null, Email.CONTACT_TYPE, null, $scope.purchaseOrder);\n });\n };\n\n $scope.openWeddingRegistryModal = ContactModal.openWeddingRegistry;\n\n $scope.showSizeModal = function(poItem, sizeGroup) {\n itemSizesModal.view(poItem, sizeGroup, { id: poItem.contactId }, false, function(size) {\n if(size) {\n $scope.applySizeChange(poItem, poItem.itemSize, size);\n poItem.itemSize = size;\n\n if(poItem.transactionId) {\n modalService.showStaticConfirmation('purchase-order.would-like-to-change-associated-so?', function () {\n $scope.savePurchaseOrderItem(poItem, true);\n }, function() {\n $scope.savePurchaseOrderItem(poItem, false);\n });\n } else {\n $scope.savePurchaseOrderItem(poItem, false);\n }\n }\n });\n };\n\n /**\n * Helpers\n */\n\n /**\n * Convert Item to PurchaseOrderItem\n * @param {resource|object} item\n * @returns {object} purchaseOrderItem\n */\n function itemToPurchaseOrderItem(item) {\n var cost = item.orderCost;\n var lineItemAddOns = ItemHelper.buildLineItemAddOnsPO(item.itemAddOns, item, null, { default: true });\n\n return {\n // converting\n inventoryItemId: item.id,\n cost: cost,\n vat: item.vat,\n itemNumber: item.itemNumber,\n itemVendorItemName: item.vendorItemName,\n itemColor: item.color,\n itemColor2: item.color2,\n itemSize: item.size,\n itemDepartmentId: item.departmentId,\n lineItemAddOns: lineItemAddOns,\n\n // defaults\n quantity: 1,\n extCost: cost,\n purchaseOrderId: $scope.purchaseOrder.id,\n sequenceNumber: $scope.purchaseOrder.lineItems.length,\n status: Enums.statuses.pending.value,\n createdByUser: User.username,\n createdDate: new Date().valueOf()\n };\n }\n\n function getAvailableAddItemsOnsAndOpenModal(purchaseOrderItem, item, options) {\n if (options.fetchItemAddOns) {\n var addOnRequest = {\n leadTimes: false,\n itemAddOns: true,\n purchaseOrder: $scope.purchaseOrder,\n purchaseOrderItem: purchaseOrderItem,\n item: item\n };\n\n PurchaseOrderItem.getAvailableAddOns(addOnRequest, function (addOnsResult) {\n //if we asked to load item add-ons and we have some, show the modal\n if(addOnsResult.itemAddOns === null) {\n addOnsResult.itemAddOns = [];\n }\n\n if(!options.showModalOnlyIfAddOnsAvailable || (options.showModalOnlyIfAddOnsAvailable && addOnRequest && addOnsResult.itemAddOns.length > 0)) {\n openAddOnModal(purchaseOrderItem, addOnsResult, options);\n }\n });\n }\n }\n\n function closePopover(event) {\n if (!angular.element(event.target).parents('.popover').length && $popover) {\n $popover.popover('destroy');\n }\n }\n\n function getPOWebHooks() {\n CompanySetting.readyByTypeArray(CompanySetting.PO_SEND_PO_WEB_HOOKS, function(hooks) {\n $scope.hooks = hooks;\n }, function (data, status) {\n console.error(data, status);\n });\n }\n\n getPOWebHooks();\n\n /**\n * Handlers\n */\n\n $scope.$on('$stateChangeStart', function (event, toState, toParams) {\n if (ignoreRedirectWarning || $state.readonly) {\n return;\n }\n\n if ($scope.isNewPurchaseOrder) {\n event.preventDefault();\n\n modalService.showConfirmation('purchase-order.would-like-to-discard?', function () {\n $scope.purchaseOrder.$remove(function () {\n ignoreRedirectWarning = true;\n $state.go(toState, toParams, { location: 'replace' });\n });\n });\n }\n });\n\n /**\n * Watchers\n */\n\n var ignoreFirstTime = true;\n\n //vendorId changes are not triggered by the save-trigger, so we watch...\n $scope.$watch('purchaseOrder.vendorId', function () {\n if (!ignoreFirstTime) {\n\n if (!$scope.purchaseOrder.vendorId) {\n $scope.purchaseOrder.vendorName = \"\";\n }\n\n $scope.savePurchaseOrder();\n }\n\n ignoreFirstTime = false;\n });\n\n $scope.$watch('purchaseOrder.lineItems', function (poItems) {\n $scope.itemColorOptions = {};\n $scope.itemColor2Options = {};\n $scope.itemSizeOptions = {};\n\n poItems.forEach(function (poItem) {\n // color, color2\n $scope.itemColorOptions[poItem.id] = poItem.colorString ? poItem.colorString.replace(/ /g, '').split(',') : [];\n $scope.itemColor2Options[poItem.id] = poItem.color2String ? poItem.color2String.replace(/ /g, '').split(',') : [];\n\n // size\n $scope.itemSizeOptions[poItem.id] = poItem.sizeGroup && poItem.sizeGroup.sizes.map(function (size) {\n return size.size;\n });\n });\n });\n\n /**\n * Init\n */\n\n // get a PO item attached to passed DOM element by tracking parent tr element\n function getPoItem(element) {\n var poIndex = parseInt(angular.element(element).parents('tr').attr('data-index'), 10);\n return $scope.purchaseOrder.lineItems[poIndex];\n }\n\n function getPoItemAddOn(element) {\n var parentIndex = parseInt(angular.element(element).parents('tr').attr('data-parent-index'), 10);\n var childIndex = parseInt(angular.element(element).parents('tr').attr('data-child-index'), 10);\n return $scope.purchaseOrder.lineItems[parentIndex].lineItemAddOns[childIndex];\n }\n\n var $popover;\n var initialNote;\n var initialAddOnNote;\n var poItemNoteScope;\n\n angular.element('.purchaseOrder_items').on('click', '.purchaseOrder_item-notes', function (event) {\n event.stopPropagation();\n\n if ($popover) {\n $popover.popover('destroy');\n }\n\n if (poItemNoteScope) {\n poItemNoteScope.$destroy();\n }\n\n var poItem = getPoItem(this);\n\n poItemNoteScope = $rootScope.$new();\n poItemNoteScope.poItem = poItem;\n poItemNoteScope.readonly = $scope.readonly;\n\n var template = '';\n\n $popover = angular.element(this).popover({\n content: $compile(template)(poItemNoteScope),\n placement: 'right',\n trigger: 'manual',\n html: true\n }).popover('show');\n\n poItemNoteScope.$digest();\n\n initialNote = poItem.note;\n\n angular.element($window).on('click', closePopover);\n });\n\n // When popover is closed\n angular.element('.purchaseOrder_items').on('hidden.bs.popover', '.purchaseOrder_item-notes', function () {\n var poItem = getPoItem(this);\n\n if (initialNote !== poItem.note) {\n // save purchaseOrderItem\n $scope.savePurchaseOrderItem(poItem);\n }\n\n // disable close popover handler\n angular.element($window).off('click', closePopover);\n });\n\n angular.element('.purchaseOrder_items').on('click', '.purchaseOrder_item-add-on-notes', function (event) {\n event.stopPropagation();\n\n if ($popover) {\n $popover.popover('destroy');\n }\n\n if (poItemNoteScope) {\n poItemNoteScope.$destroy();\n }\n\n var addOn = getPoItemAddOn(this);\n\n poItemNoteScope = $rootScope.$new();\n poItemNoteScope.addOn = addOn;\n poItemNoteScope.readonly = $scope.readonly;\n poItemNoteScope.editNotes = $scope.itemAddOnsPerm.editNotes;\n\n var template = '';\n\n $popover = angular.element(this).popover({\n content: $compile(template)(poItemNoteScope),\n placement: 'right',\n trigger: 'manual',\n html: true\n }).popover('show');\n\n poItemNoteScope.$digest();\n\n initialAddOnNote = addOn.notes;\n\n angular.element($window).on('click', closePopover);\n });\n\n // When popover is closed\n angular.element('.purchaseOrder_items').on('hidden.bs.popover', '.purchaseOrder_item-add-on-notes', function () {\n var addOnItem = getPoItemAddOn(this);\n\n if(addOnItem && addOnItem.purchaseOrderItemId) {\n var poItem = _($scope.purchaseOrder.lineItems).findWhere({ id: addOnItem.purchaseOrderItemId });\n\n if (initialAddOnNote !== addOnItem.note && poItem && poItem.id) {\n $scope.savePurchaseOrderItem(poItem);\n }\n }\n\n // disable close popover handler\n angular.element($window).off('click', closePopover);\n });\n\n // Save purchaseOrderItem on any input changing\n angular.element('.purchaseOrder_items').on('change', 'input:not(.not-save-trigger), select:not(.not-save-trigger)', _.debounce(function (event) {\n var poItem = getPoItem(this);\n\n if (!poItem) {\n return;\n }\n\n // Apply upsize charge when size is updated and there is an upsize cost\n if (event.target.getAttribute('ng-model') === 'poItem.itemSize') {\n var oldSize = event.removed ? event.removed.text : \"\";\n var newSize = event.added ? event.added.text : \"\";\n $scope.applySizeChange(poItem, oldSize, newSize);\n }\n\n //if color, color2 or size is changed and the item is associated with an SO, ask\n //if the user wants to change the SO too.\n if ((event.target.getAttribute('ng-model') === 'poItem.itemColor'\n || event.target.getAttribute('ng-model') === 'poItem.itemColor2'\n || event.target.getAttribute('ng-model') === 'poItem.itemSize')\n && poItem.transactionId) {\n\n modalService.showStaticConfirmation('purchase-order.would-like-to-change-associated-so?', function () {\n $scope.savePurchaseOrderItem(poItem, true);\n }, function() {\n $scope.savePurchaseOrderItem(poItem, false);\n });\n } else {\n $scope.savePurchaseOrderItem(poItem, false);\n }\n\n }, 1000));\n\n // Save purchaseOrder on any input changing\n angular.element(document).off('change', '.save-trigger').on('change', '.save-trigger', function () {\n $scope.savePurchaseOrder();\n });\n\n\n $scope.applySizeChange = function (poItem, oldSize, newSize) {\n //check to see if there was an upcharge on the old size, if so, the upcharge will be removed before adding another one.\n //this helps fix the issue of having an inventory item that has the upcharge already added\n //into the price.\n\n //if there is no size group then there cannot be any upcharges, get outta here.\n if (!poItem.sizeGroup) {\n return;\n }\n\n var sizeUpchargeAppliedToOldSize = $scope.hasSizeUpcharge(poItem.sizeGroup.sizes, oldSize);\n\n //only change pricing if the old size is not the same as the new size\n if (oldSize != newSize) {\n if (!sizeUpchargeAppliedToOldSize) {\n //look up the upcharge and apply\n $scope.applySizeUpcharge(poItem, poItem.sizeGroup.sizes, newSize);\n } else {\n //if the upcharge was applied to the old size and then they changed it to something else\n //then we need to remove the old size upcharge and apply the other one;\n $scope.removeSizeUpcharge(poItem, poItem.sizeGroup.sizes, oldSize);\n $scope.applySizeUpcharge(poItem, poItem.sizeGroup.sizes, newSize);\n }\n }\n };\n\n $scope.hasSizeUpcharge = function (availableSizes, itemSize) {\n if (availableSizes && availableSizes.length > 0) {\n for (var i = 0; i < availableSizes.length; i++) {\n if (availableSizes[i].size === itemSize) {\n if (availableSizes[i].upchargeCost) {\n return true;\n } else {\n //no size charge, get out of the loop\n break;\n }\n }\n }\n }\n return false;\n };\n\n $scope.applySizeUpcharge = function (poItem, availableSizes, itemSize) {\n if (availableSizes && availableSizes.length) {\n for (var i = 0; i < availableSizes.length; i++) {\n if (availableSizes[i].size === itemSize) {\n if (availableSizes[i].upchargeCost) {\n\n //detect which type of upcharge to apply\n if(availableSizes[i].upchargeCostType === 0) {\n poItem.cost = poItem.cost + availableSizes[i].upchargeCost;\n } else if(availableSizes[i].upchargeCostType === 1) {\n var upchargePercent = availableSizes[i].upchargeCost/100;\n poItem.cost = poItem.cost + (upchargePercent * poItem.cost);\n poItem.cost = Number(poItem.cost.toFixed(2));\n } else {\n continue;\n }\n\n poItem.sizeUpchargeApplied = true;\n break;\n } else {\n //no size charge, get out of the loop\n break;\n }\n }\n }\n }\n };\n\n $scope.removeSizeUpcharge = function (poItem, availableSizes, itemSize) {\n if (availableSizes && availableSizes.length) {\n for (var i = 0; i < availableSizes.length; i++) {\n if (availableSizes[i].size === itemSize) {\n if (availableSizes[i].upchargeCost) {\n\n //detect which type of upcharge to apply\n if(availableSizes[i].upchargeCostType === 0) {\n poItem.cost = poItem.cost - availableSizes[i].upchargeCost;\n } else if(availableSizes[i].upchargeCostType === 1) {\n var upchargePercent = availableSizes[i].upchargeCost/100;\n poItem.cost = poItem.cost / (1 + upchargePercent);\n poItem.cost = Number(poItem.cost.toFixed(2));\n } else {\n continue;\n }\n\n poItem.sizeUpchargeApplied = false;\n break;\n } else {\n //no size charge, get out of the loop\n break;\n }\n }\n }\n }\n };\n\n $scope.triggerSmartFlow = function() {\n if($scope.wasConfirmed) {\n $scope.wasConfirmed = false;\n\n var purchaseOrder = {};\n angular.extend(purchaseOrder, $scope.purchaseOrder);\n _(purchaseOrder.lineItems).each(function (lineItem) {\n delete lineItem.checked;\n });\n\n eventsBus.publish(\"purchase-order:confirmed\", [purchaseOrder]);\n }\n };\n\n $timeout(function () {\n $scope.$broadcast('show-errors-check-validity');\n });\n\n $scope.$watch('purchaseOrder.confirmationNumber', function (newValue, oldValue) {\n if(!oldValue && newValue) {\n //it was blank before and we have a value now, so we are confirming\n $scope.wasConfirmed = true;\n }\n });\n\n });\n\n});\n\n","\ndefine('text!modules/item/item-search-typeahead-grid-directive/items-search-typeahead-grid.tpl.html',[],function () { return '
\\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
\\n \\n \\n \\n \\n
\\n {{ item.name }}\\n {{ item.vendorItemName }}\\n {{ item.name }}\\n {{ item.itemNumber }}\\n \\n {{ item.color }}\\n {{ item.size }}\\n = item.regularPrice\">{{ item.regularPrice | currency }}\\n 0 && item.salePrice < item.regularPrice\">\\n {{ item.regularPrice | currency }} \\n {{ item.salePrice | currency }}\\n \\n {{ item.vendorCode }}{{ item.departmentCode }}
\\n \\n {{ pagination.page }}\\n \\n
\\n\\n
\\n
\\n';});\n\n","define('modules/quote/details/quote-details-ctrl',['../module', 'angular', 'underscore', 'moment'], function (module, angular, _, moment) {\n 'use strict';\n\n module.controller('QuoteDetailsCtrl', function ($compile,\n $modal,\n $scope,\n $rootScope,\n $state,\n $stateParams,\n $timeout,\n $window,\n $locale,\n $location,\n $translate,\n $filter,\n AppLicense,\n alerts,\n eventsBus,\n Contact,\n EventMember,\n EventItem,\n EmailService,\n Sms,\n employees,\n Enums,\n Item,\n ItemModal,\n modalService,\n ResourcesHelper,\n quoteSettings,\n posSettings,\n clientPortalSettings,\n taxCodes,\n Quote,\n quote,\n ItemAddOn,\n ItemHelper,\n itemSizesModal,\n QuoteAddress,\n TaxJarSettings,\n QuoteItem,\n User,\n QuoteSignature,\n TransactionPaymentsModalService,\n FULLSTEAM,\n FullSteam,\n SmartFlow,\n security,\n Permissions,\n quoteAgreements,\n quoteTerminalContracts) {\n\n /*\n\n Init\n */\n var license = AppLicense.get();\n $scope.security = security;\n $scope.quote = quote;\n $scope.employees = ResourcesHelper.adaptList('employees', employees);\n $scope.taxCodes = _.filter(taxCodes, function(taxCode) {\n return taxCode && taxCode.description !== 'BLeCommerceTax';\n });\n $scope.locale = $locale;\n $scope.isNF525 = $locale.isNF525;\n $scope.isNF525AndNotTrialing = $locale.isNF525 === true && license.status !== 'T';\n $scope.currencySymbol = $locale.NUMBER_FORMATS.CURRENCY_SYM;\n $scope.isSmartFlowsEnabled = security.hasPlanPermission('smartFlows');\n $scope.hasAllFullSteamSettings = TransactionPaymentsModalService.hasAllFullSteamSettings(posSettings);\n $scope.hasAllChargeItProSettings = TransactionPaymentsModalService.hasAllChargeItProSettings(posSettings);\n $scope.hasAllStripeSettings = TransactionPaymentsModalService.hasAllStripeSettings(posSettings);\n $scope.convertedStatusValue = Enums.statuses.converted.value;\n $scope.pendingStatusValue = Enums.statuses.pending.value;\n $scope.voidedStatusValue = Enums.statuses.voided.value;\n\n var quoteTypeId = '5';\n\n $scope.readonly = $scope.quote.status === $scope.convertedStatusValue || $scope.quote.status === $scope.voidedStatusValue || (!security.hasPermission(\"EDIT_QUOTES\"));\n\n $scope.quoteAgreements = quoteAgreements;\n $scope.quoteTerminalContracts = quoteTerminalContracts;\n\n $scope.defaultQuoteAgreement = getDefaultQuoteAgreement(quoteSettings);\n\n $scope.perms = {\n convert: security.hasPermission(Permissions.CONVERT_QUOTES)\n };\n\n $scope.itemAddOnsPerm = {\n add: security.hasPermission(Permissions.ADD_QUOTE_ITEM_ADD_ON),\n set: security.hasPermission(Permissions.SELECT_QUOTE_ITEM_ADD_ON),\n editNotes: security.hasPermission(Permissions.EDIT_QUOTE_ITEM_ADD_ON_NOTE),\n editDesc: security.hasPermission(Permissions.EDIT_QUOTE_ITEM_ADD_ON_DESC),\n editPrice: security.hasPermission(Permissions.EDIT_QUOTE_ITEM_ADD_ON_PRICE),\n remove: security.hasPermission(Permissions.REMOVE_QUOTE_ITEM_ADD_ON),\n addOnRequired: security.hasPermission(Permissions.QUOTE_ITEM_ADD_ON_REQUIRED)\n };\n\n var setting = _(quoteSettings).findWhere({ type: 'QUOTE_ALT_PRINT' });\n $scope.doShowDescription = setting && setting.value === 'Y';\n\n setting = _(posSettings).findWhere({ type: 'POS_MANUAL_TAX_CALC' });\n $scope.enableManualTaxCalculation = setting && setting.value === 'Y';\n\n setting = _(posSettings).findWhere({ type: 'POS_COLOR_SIZE_VALID' });\n $scope.colorOrSizeAllowCustomVal = setting && setting.value === 'N';\n\n setting = _(posSettings).findWhere({ type: 'POS_COLOR_SIZE_REQUIRED' });\n $scope.colorAndSizeRequired = setting && setting.value === 'Y';\n\n setting = _(posSettings).findWhere({ type: 'POS_COLOR_SIZE_BLANK' });\n var colorAndSizeBlank = setting && setting.value === 'Y';\n\n setting = _(posSettings).findWhere({ type: 'USE_DIG_SIGN' });\n $scope.digitalSignatureEnabled = setting && setting.value === 'Y';\n\n setting = _(posSettings).findWhere({ type: 'POS_TRX_DISCOUNT' });\n $scope.trxDiscountEnabled = setting && setting.value === 'Y';\n\n var licenseHasDigitalSignatureFeature = license.plan['digitalSignature'];\n if(!licenseHasDigitalSignatureFeature) {\n $scope.digitalSignatureEnabled = false;\n }\n\n // determine visibility of client portal feature\n var portalFeature = _(clientPortalSettings).findWhere({ type: 'CP_FEATURE_DIGITAL_SIGNATURES' });\n var portalFeatureEnabled = portalFeature ? portalFeature.value === 'Y' : true;\n var userHasPermission = security.hasPermission(\"REQUEST_SIGNATURES\");\n var licenseHasPortalAccess = AppLicense.get()[\"clientPortalAccess\"];\n\n var onlinePaymentsEnabled = $scope.hasAllFullSteamSettings || $scope.hasAllChargeItProSettings || $scope.hasAllStripeSettings;\n $scope.requestSignatureAvailable = (onlinePaymentsEnabled && userHasPermission) || (licenseHasPortalAccess && portalFeatureEnabled && userHasPermission);\n\n var onAddLineItem = function (item, searchField, ignoreAddOns, addOnItemCallback) {\n var quoteItem = itemToQuoteItem(item);\n quoteItem.checkForUpCharge = !!(colorAndSizeBlank);\n\n $scope.savingInProgress = true;\n Quote.addLineItem(quoteItem, function (quote) {\n $scope.savingInProgress = false;\n $scope.isNewQuote = false;\n angular.extend($scope.quote, _(quote).omit('quoteLineItems'));\n _($scope.quote.quoteLineItems).each(function (quoteItem, index) {\n quoteItem.version = quote.quoteLineItems[index].version;\n\n _(quoteItem.quoteItemAddOns).each(function (addOn, i) {\n if(quote.quoteLineItems[index].quoteItemAddOns && quote.quoteLineItems[index].quoteItemAddOns.length && quote.quoteLineItems[index].quoteItemAddOns[i]) {\n addOn.version = quote.quoteLineItems[index].quoteItemAddOns[i].version;\n }\n });\n });\n\n if(quote.failedToRecalculateTax) {\n alerts.pushError('settings.tax-jar.message.failed-to-calculate-tax');\n }\n\n if (!$scope.quote.smartFlowsTriggeredDateTime && security.hasPlanPermission('smartFlows')) {\n var req = { triggerId: Enums.smartFlowTriggers.quote_created.id };\n req.loggedInEmployee = User;\n req.quote = $scope.quote;\n\n SmartFlow.getTriggeredFlowsForDisplay(req, function (flows) {\n if (flows && flows.length > 0) {\n $scope.quote.smartFlowsTriggeredDateTime = new Date().valueOf();\n }\n });\n }\n\n var addedItem = _(quote.quoteLineItems).last();\n $scope.quote.quoteLineItems.push(addedItem);\n $scope.quote.modifiedDate = Date.now();\n\n if(!ignoreAddOns) {\n $scope.getAvailableAddOnsAndOpenModal(addedItem, item, { showModalOnlyIfAddOnsAvailable: true, fetchItemAddOns: $scope.itemAddOnsPerm.set });\n }\n\n validateQuoteItems();\n\n if(addOnItemCallback) {\n addOnItemCallback();\n }\n });\n };\n\n $scope.itemSelectorOptions = {\n addNewItemSaveButtonLabel: $translate.instant('transaction.save-and-add-to') + $translate.instant('quote.quote'),\n onAddNewItem: getAllItemValues,\n onChooseItem: getAllItemValues\n };\n\n function getAllItemValues(item, field) {\n ItemAddOn.listByItemId(item.id, function(itemAddOns) {\n item.itemAddOns = itemAddOns;\n onAddLineItem(item, field);\n });\n }\n\n var ignoreRedirectWarning = false;\n\n /**\n * Methods\n */\n\n $scope.queriesInProgress = 0;\n\n $scope.saveQuoteItem = function (item, callback) {\n $scope.savingInProgress = true;\n $scope.queriesInProgress += 1;\n item.modifiedDate = Date.now();\n item.modifiedByUser = User.username;\n\n Quote.updateLineItem(item, function (savedQuote) {\n $scope.savingInProgress = false;\n\n angular.extend($scope.quote, _(savedQuote).omit(\n 'quoteLineItems',\n 'employeeId',\n 'shippingAndHandling',\n 'fee',\n 'notes'\n ));\n\n if(savedQuote.failedToRecalculateTax) {\n alerts.pushError('settings.tax-jar.message.failed-to-calculate-tax');\n }\n\n var savedQuoteItem = _(savedQuote.quoteLineItems).findWhere({ id: item.id });\n\n // Update special field of current line item\n item.adjustedPrice = savedQuoteItem.adjustedPrice;\n item.discountPercent = savedQuoteItem.discountPercent;\n\n item.shippingTax = savedQuoteItem.shippingTax;\n item.taxAmount = savedQuoteItem.taxAmount;\n\n // Update version of all line items\n _($scope.quote.quoteLineItems).each(function (quoteItem, index) {\n quoteItem.version = savedQuote.quoteLineItems[index].version;\n quoteItem.modifiedDate = savedQuote.quoteLineItems[index].modifiedDate;\n quoteItem.modifiedByUser = savedQuote.quoteLineItems[index].modifiedByUser;\n quoteItem.quoteItemAddOns = savedQuote.quoteLineItems[index].quoteItemAddOns;\n\n _(quoteItem.quoteItemAddOns).each(function (addOn, i) {\n if(savedQuote.quoteLineItems[index].quoteItemAddOns && savedQuote.quoteLineItems[index].quoteItemAddOns.length && savedQuote.quoteLineItems[index].quoteItemAddOns[i]) {\n addOn.version = savedQuote.quoteLineItems[index].quoteItemAddOns[i].version;\n addOn.modifiedDate = savedQuote.quoteLineItems[index].quoteItemAddOns[i].modifiedDate;\n addOn.modifiedByUser = savedQuote.quoteLineItems[index].quoteItemAddOns[i].modifiedByUser;\n }\n });\n });\n }, function (data, status) {\n Quote.defaultErrorHandler(data, status);\n $scope.savingInProgress = false;\n }).finally(function () {\n // without timeout saving state will be \"jumpy\"\n $timeout(function () {\n $scope.queriesInProgress -= 1;\n }, 1000);\n\n if(callback) {\n callback();\n }\n });\n };\n\n $scope.saveQuote = $scope.quote.save = _.debounce(function (callback) {\n $scope.queriesInProgress += 1;\n $scope.savingInProgress = true;\n $scope.quote.modifiedDate = Date.now();\n $scope.quote.modifiedByUser = User.username;\n\n //make sure the employeeName is set properly\n if($scope.quote.employeeId >= 0 && $scope.employees) {\n var employee = _($scope.employees).findWhere({ id: $scope.quote.employeeId });\n if(employee) {\n $scope.quote.employeeName = employee.fullName;\n }\n }\n\n Quote.put(_($scope.quote).omit('save'), function (savedQuote) {\n $scope.savingInProgress = false;\n $scope.isNewQuote = false;\n\n angular.extend($scope.quote, _(savedQuote).omit(\n 'quoteLineItems',\n 'employeeId',\n 'shippingAndHandling',\n 'fee',\n 'notes'\n ));\n _($scope.quote.quoteLineItems).each(function (item, index) {\n item.quantitySold = savedQuote.quoteLineItems[index].quantitySold;\n item.version = savedQuote.quoteLineItems[index].version;\n\n _(item.quoteItemAddOns).each(function (addOn, i) {\n if(savedQuote.quoteLineItems[index].quoteItemAddOns && savedQuote.quoteLineItems[index].quoteItemAddOns.length && savedQuote.quoteLineItems[index].quoteItemAddOns[i]) {\n addOn.version = savedQuote.quoteLineItems[index].quoteItemAddOns[i].version;\n }\n });\n });\n\n $scope.readonly = $scope.quote.status === $scope.convertedStatusValue || $scope.quote.status === $scope.voidedStatusValue;\n\n if (callback) {\n callback(savedQuote);\n }\n }, function (data, status) {\n Quote.defaultErrorHandler(data, status);\n $scope.savingInProgress = false;\n }).finally(function () {\n $scope.queriesInProgress -= 1;\n });\n }, 1000);\n\n $scope.loadSignatures = function () {\n setting = _(posSettings).findWhere({ type: 'SALES_AGREEMENT_REQ' });\n var isSignatureRequiredForThisType = setting && setting.value && setting.value.split(',').indexOf(quoteTypeId) !== -1;\n\n QuoteSignature.listAllForQuote(quote.id, function (signatures) {\n var activeAgreementSigned = false;\n //now mark each sales agreement as signed, if we have a signature for it\n _(signatures).each(function(signature) {\n if(signature.salesAgreementId && signature.quoteId) {\n var agreement = _($scope.quoteAgreements).findWhere({ id: signature.salesAgreementId });\n\n if(!agreement) {\n agreement = _($scope.quoteTerminalContracts).findWhere({ id: signature.salesAgreementId });\n }\n\n if(agreement) {\n agreement.signed = true;\n activeAgreementSigned = true;\n }\n }\n });\n\n $scope.markSignSalesAgreementGreen = activeAgreementSigned;\n $scope.markSignSalesAgreementRed = !$scope.markSignSalesAgreementGreen && isSignatureRequiredForThisType;\n });\n };\n\n $scope.signTerminalContract = function(customContract) {\n if(!$window.localStorage.fullsteamTerminalId) {\n openSetTerminalModal(customContract, null, false);\n } else {\n openTerminalContractModal(customContract, $scope.quote.id);\n }\n };\n\n function openTerminalContractModal(contract, quoteId, tempTerminal) {\n if((contract && contract.signed) || (tempTerminal && tempTerminal.terminalId) || isDeviceTypeValid($window.localStorage.fullsteamTerminalType, contract)) {\n $modal\n .open({\n templateUrl: 'js/modules/quote/details/modals/sign-terminal-contract.tpl.html',\n controller: 'SignTerminalQuoteContractCtrl',\n windowClass: '__protected __large',\n backdrop: 'static',\n resolve: {\n agreement: function () {\n return contract;\n },\n signatures: function (QuoteSignature) {\n return QuoteSignature.query({ filterObject: { quoteId: quote.id} });\n },\n tempTerminal: function () {\n return tempTerminal;\n }\n }\n })\n .result\n .then(function (savedSignature) {\n var agreement = $scope.defaultQuoteAgreement;\n if(contract) {\n agreement = contract;\n }\n\n if (savedSignature) {\n $scope.markSignSalesAgreementRed = false;\n $scope.markSignSalesAgreementGreen = true;\n\n //mark the sales agreement as signed\n if(agreement) {\n agreement.signed = true;\n }\n } else {\n //if the signature was deleted, reset the state of the signature button\n //mark the sales agreement as not signed\n if(agreement) {\n agreement.signed = false;\n }\n\n $scope.markSignSalesAgreementRed = false;\n $scope.markSignSalesAgreementGreen = false;\n\n //if we don't have any signed sales agreements, turn the button red now\n setting = _(posSettings).findWhere({ type: 'SALES_AGREEMENT_REQ' });\n var isSignatureRequiredForThisType = setting && setting.value && setting.value.split(',').indexOf(quoteTypeId) !== -1;\n\n if(!$scope.defaultQuoteAgreement.signed) {\n var otherSignedSalesAgreement = _($scope.quoteAgreements).findWhere({ signed: true });\n\n if(!otherSignedSalesAgreement && $scope.quoteTerminalContracts) {\n otherSignedSalesAgreement = _($scope.quoteTerminalContracts).findWhere({ signed: true });\n }\n\n if(!otherSignedSalesAgreement) {\n $scope.markSignSalesAgreementRed = isSignatureRequiredForThisType;\n $scope.markSignSalesAgreementGreen = false;\n } else {\n $scope.markSignSalesAgreementRed = false;\n $scope.markSignSalesAgreementGreen = true;\n }\n } else {\n $scope.markSignSalesAgreementRed = false;\n $scope.markSignSalesAgreementGreen = true;\n }\n }\n });\n }\n }\n\n function isDeviceTypeValid(device, agreement) {\n if(!device) {\n return true;\n }\n\n if(FULLSTEAM.DEVICES.MX915 !== device && FULLSTEAM.DEVICES.MX925 !== device && FULLSTEAM.DEVICES.L7000 !== device) {\n FullSteam.getTerminals(function (result) {\n var terminals = _((result && result.terminals)).filter(function (terminal) {\n return FULLSTEAM.DEVICES.MX915 === terminal.modelNumber || FULLSTEAM.DEVICES.MX925 === terminal.modelNumber || FULLSTEAM.DEVICES.L7000 === terminal.modelNumber;\n });\n\n if(terminals && terminals.length) {\n openSetTerminalModal(agreement, terminals, true);\n } else {\n modalService.showMessage('settings.custom-sales-agreement.devices-eligible');\n }\n\n }, function () {\n modalService.showMessage('settings.custom-sales-agreement.devices-eligible');\n });\n\n return false;\n }\n\n return true;\n }\n\n function openSetTerminalModal(agreement, terminals, selectingContractTerminal) {\n return $modal.open({\n templateUrl: 'js/modules/quote/details/modals/set-terminal-modal.tpl.html',\n controller: 'SetTerminalModalCtrl',\n resolve: {\n terminalResult: function () {\n if(terminals && terminals.length) {\n return { terminals: terminals };\n } else {\n return FullSteam.getTerminals();\n }\n },\n selectingContractTerminal: function () {\n return selectingContractTerminal;\n }\n }\n }).result.then(function(response) {\n if(response) {\n openTerminalContractModal(agreement, $scope.quote.id, response);\n } else {\n return modalService.showMessage('alerts.merchant-account.please-set-terminal-capture','settings.merchant-account.required-terminal');\n }\n });\n }\n\n $scope.signSalesAgreementModal = function (quoteAgreement) {\n if(!quoteAgreement && $scope.defaultQuoteAgreement) {\n quoteAgreement = $scope.defaultQuoteAgreement;\n }\n $modal\n .open({\n templateUrl: 'js/modules/quote/details/modals/sign-quote-agreement.tpl.html',\n controller: 'SignQuoteAgreementCtrl',\n windowClass: '__protected __large',\n backdrop: 'static',\n keyboard: false,\n resolve: {\n quoteSignatures: function(QuoteSignature) {\n return QuoteSignature.listAllForQuote(quote.id);\n },\n quoteSettings: function () {\n return quoteSettings;\n },\n awsPolicyAndSignature: function(Signature) {\n return Signature.getS3Policy();\n },\n customQuoteAgreements: function () {\n return $scope.quoteAgreements;\n },\n agreement: function () {\n return quoteAgreement;\n }\n }\n })\n .result\n .then(function (savedSignature) {\n var agreement = $scope.defaultQuoteAgreement;\n if(quoteAgreement) {\n agreement = quoteAgreement;\n }\n\n if (savedSignature) {\n $scope.markSignSalesAgreementRed = false;\n $scope.markSignSalesAgreementGreen = true;\n\n //mark the sales agreement as signed\n if(agreement) {\n agreement.signed = true;\n }\n } else {\n //if the signature was deleted, reset the state of the signature button\n //mark the sales agreement as not signed\n if(agreement) {\n agreement.signed = false;\n }\n\n $scope.markSignSalesAgreementRed = false;\n $scope.markSignSalesAgreementGreen = false;\n\n setting = _(posSettings).findWhere({ type: 'SALES_AGREEMENT_REQ' });\n var isSignatureRequiredForThisType = setting && setting.value && setting.value.split(',').indexOf(quoteTypeId) !== -1;\n\n\n if(!$scope.defaultQuoteAgreement || !$scope.defaultQuoteAgreement.signed) {\n var otherSignedSalesAgreement = _($scope.quoteAgreements).findWhere({ signed: true });\n\n if(!otherSignedSalesAgreement && $scope.quoteTerminalContracts) {\n otherSignedSalesAgreement = _($scope.quoteTerminalContracts).findWhere({ signed: true });\n }\n\n if(!otherSignedSalesAgreement) {\n $scope.markSignSalesAgreementRed = isSignatureRequiredForThisType;\n $scope.markSignSalesAgreementGreen = false;\n } else {\n $scope.markSignSalesAgreementRed = false;\n $scope.markSignSalesAgreementGreen = true;\n }\n } else {\n $scope.markSignSalesAgreementRed = false;\n $scope.markSignSalesAgreementGreen = true;\n }\n }\n });\n };\n\n $scope.requestSignature = function () {\n if (!$scope.quote.contactId) {\n modalService.showMessage('transaction.message.assign-contact-first');\n } else {\n $modal.open({\n templateUrl: 'js/modules/quote/details/modals/request-signature.tpl.html',\n controller: 'QuoteRequestSignatureCtrl',\n windowClass: '__small',\n resolve: {\n companyProfile: function (Company) {\n return Company.get();\n },\n posSettings: function (CompanySetting) {\n return CompanySetting.getPOSSettings();\n },\n quoteAgreements: function (CompanySetting) {\n return CompanySetting.getQuoteCustomAgreements();\n },\n smsTemplates: function (SMSTemplate) {\n return SMSTemplate.query({ filterObject: { status: Enums.statuses.active.value }});\n },\n emailTemplates: function (EmailTemplate) {\n return EmailTemplate.query({ filterObject: { status: Enums.statuses.active.value }});\n },\n twilioSettings: function (TwilioSettings) {\n return TwilioSettings.get();\n },\n contact: function (Contact) {\n return Contact.getById($scope.quote.contactId);\n },\n quote: function () {\n return $scope.quote;\n }\n }\n });\n }\n };\n\n $scope.removeLineItem = function (quoteItem) {\n if($scope.readonly) {\n return;\n }\n\n modalService.showConfirmation('purchase-order.would-like-to-delete-item?', function () {\n Quote.deleteLineItem(quoteItem, function (quote) {\n $scope.quote.quoteLineItems = _($scope.quote.quoteLineItems).without(quoteItem);\n $scope.quote.modifiedDate = Date.now();\n $scope.quote.modifiedByUser = User.username;\n angular.extend($scope.quote, _(quote).omit('quoteLineItems'));\n _($scope.quote.quoteLineItems).each(function (item, index) {\n item.version = quote.quoteLineItems[index].version;\n item.adjustedPrice = quote.quoteLineItems[index].adjustedPrice;\n\n _(item.quoteItemAddOns).each(function (addOn, i) {\n if(quote.quoteLineItems[index].quoteItemAddOns && quote.quoteLineItems[index].quoteItemAddOns.length && quote.quoteLineItems[index].quoteItemAddOns[i]) {\n addOn.version = quote.quoteLineItems[index].quoteItemAddOns[i].version;\n }\n });\n });\n alerts.pushSuccess('alerts.transaction.successfully-deleted-item');\n });\n });\n };\n\n $scope.removeAddOnItem = function (addOnItem, quoteItem) {\n if($scope.readonly) {\n return;\n }\n\n modalService.showConfirmation('purchase-order.would-like-to-delete-add-on-item?', function () {\n Quote.deleteLineItemAddOn(addOnItem, function (quote) {\n for(var i = 0; i < $scope.quote.quoteLineItems.length; i++) {\n for(var j = 0; j < $scope.quote.quoteLineItems[i].quoteItemAddOns.length; j++) {\n var addOn = $scope.quote.quoteLineItems[i].quoteItemAddOns[j];\n\n if(addOn && addOn.id === addOnItem.id) {\n $scope.quote.quoteLineItems[i].quoteItemAddOns = _($scope.quote.quoteLineItems[i].quoteItemAddOns).without(addOnItem);\n break;\n }\n }\n }\n\n $scope.quote.modifiedDate = Date.now();\n $scope.quote.modifiedByUser = User.username;\n\n var savedQuoteItem = _(quote.quoteLineItems).findWhere({ id: quoteItem.id });\n // Update special field of current line item\n quoteItem.adjustedPrice = savedQuoteItem.adjustedPrice;\n quoteItem.discountPercent = savedQuoteItem.discountPercent;\n quoteItem.shippingTax = savedQuoteItem.shippingTax;\n quoteItem.taxAmount = savedQuoteItem.taxAmount;\n quoteItem.price = savedQuoteItem.price;\n\n angular.extend($scope.quote, _(quote).omit('quoteLineItems'));\n _($scope.quote.quoteLineItems).each(function (item, index) {\n item.version = quote.quoteLineItems[index].version;\n item.modifiedDate = quote.quoteLineItems[index].modifiedDate;\n item.modifiedByUser = quote.quoteLineItems[index].modifiedByUser;\n\n _(item.quoteItemAddOns).each(function (addOn, i) {\n if(quote.quoteLineItems[index].quoteItemAddOns && quote.quoteLineItems[index].quoteItemAddOns.length && quote.quoteLineItems[index].quoteItemAddOns[i]) {\n addOn.version = quote.quoteLineItems[index].quoteItemAddOns[i].version;\n }\n });\n });\n alerts.pushSuccess('alerts.add-ons.successfully-deleted-item-add-on');\n });\n });\n };\n\n $scope.convertQuoteToTransaction = function(typeId) {\n var type = $scope.getTrxType(typeId);\n validateThenConvert(type.value, function () {\n modalService.showConfirmation({\n key: 'quote.messages.would-like-to-convert?',\n params: {\n type: $translate.instant(type.description)\n }}, function () {\n Quote.convertToTransaction($scope.quote, User.id, type.value, function (newlyCreatedTransaction) {\n ignoreRedirectWarning = true;\n $state.go(getTrxRoute(type.value), { id: newlyCreatedTransaction.id, promptLeadTimes: true });\n });\n });\n });\n };\n\n $scope.getAvailableAddOnsAndOpenModal = function(quoteItem, item, options, callback) {\n var addOnRequest = {\n leadTimes: false,\n itemAddOns: options.fetchItemAddOns,\n quote: $scope.quote,\n quoteItem: quoteItem,\n item: item\n };\n\n QuoteItem.getAvailableAddOns(addOnRequest, function(addOnsResult) {\n //if we asked to load lead times and we have some, show the modal\n if(addOnsResult.leadTimes === null) {\n addOnsResult.leadTimes = [];\n }\n\n if(addOnsResult.itemAddOns === null) {\n addOnsResult.itemAddOns = [];\n }\n\n var quoteItemAddOns = _(quoteItem.quoteItemAddOns).filter(function(addOn) {\n return addOn.addOnId !== 0 && addOn.addOnId !== null;\n });\n\n if(options.showModalOnlyIfAddOnsAvailable && addOnRequest && addOnRequest.itemAddOns && addOnsResult.itemAddOns.length > 0 && quoteItemAddOns.length !== addOnsResult.itemAddOns.length) {\n openAddOnModal(quoteItem, addOnsResult, { userSelected: quoteItem.quoteItemAddOns && quoteItem.quoteItemAddOns.length });\n }\n\n if(callback) {\n callback();\n }\n\n if(!options.showModalOnlyIfAddOnsAvailable || (options.showModalOnlyIfAddOnsAvailable && addOnRequest && addOnsResult.leadTimes.length > 0)) {\n openLeadTimesModal(quoteItem, addOnsResult, callback);\n } else {\n if (callback) {\n callback();\n }\n }\n });\n };\n\n $scope.shippingFieldChange = _.debounce(function(value) {\n if($rootScope.shippingModalOpen || value < 0 || value === null || value === undefined) {\n return;\n }\n\n var changeInShippingTax = false;\n var itemCount = 0;\n var shippingSum = 0;\n\n _($scope.quote.quoteLineItems).each(function(item) {\n if (item.shippingCost > 0) {\n changeInShippingTax = true;\n }\n\n itemCount++;\n shippingSum += item.shippingCost.valueOf();\n });\n\n if((value === 0 && changeInShippingTax) && (itemCount > 1 || itemCount === 1)) {\n updateShippingCostAndRecalculate();\n } else if(changeInShippingTax && value !== shippingSum && itemCount === 1) {\n updateShippingCostAndRecalculate();\n } else if(changeInShippingTax && value !== shippingSum && itemCount > 1) {\n modalService.showStaticConfirmationCustomButtons({\n message: 'modal-service.shipping-change.shipping-has-changed',\n btn_primary_text: 'modal-service.shipping-change.distribute-manually',\n btn_secondary_text: 'modal-service.shipping-change.distribute-evenly'\n },\n function() {\n $scope.openShipToCustomerModal();\n },\n function() {\n updateShippingCostAndRecalculate();\n });\n }\n }, 2500);\n\n $scope.openShipToCustomerModal = function () {\n if($rootScope.shippingModalOpen || $scope.savingInProgress) {\n return;\n }\n\n if(!$scope.quote.contactId) {\n return modalService.showMessage('transaction.ship-to-customer.please-assign-contact');\n }\n\n $rootScope.shippingModalOpen = true;\n\n $modal.open({\n templateUrl: 'js/modules/quote/details/modals/ship-to-customer-modal.tpl.html',\n controller: 'ShipToCustomerQuoteModalCtrl',\n resolve: {\n taxCodes: function (TaxCode) {\n return TaxCode.query({ filterObject: { status:Enums.statuses.active.value }});\n },\n quote: function () {\n return Quote.getById($scope.quote.id);\n },\n addresses: function () {\n return QuoteAddress.listAllForContact($scope.quote);\n },\n eventMembers: function () {\n if($scope.quote && $scope.quote.eventId) {\n return Quote.listEventMemberContactInformation($scope.quote.eventId, $scope.quote.eventContactId);\n } else {\n return null;\n }\n },\n settings: function () {\n return TaxJarSettings.get();\n }\n },\n windowClass: '__large',\n backdrop: 'static',\n keyboard: false\n }).result.then(function (response) {\n $rootScope.shippingModalOpen = false;\n\n if(response && response.quote) {\n\n var savedQuote = response.quote;\n\n if(savedQuote.failedToRecalculateTax) {\n alerts.pushError('settings.tax-jar.message.failed-to-calculate-tax');\n }\n\n angular.extend($scope.quote, _(savedQuote).omit(\n 'quoteLineItems',\n 'employeeId',\n 'fee',\n 'notes'\n ));\n\n updateLineItemsAfterUpdatingShippingInfo(savedQuote);\n }\n });\n };\n\n $scope.print = function (agreement) {\n Quote.print($scope.quote.id, agreement);\n };\n\n $scope.linkItemToWeddingRegistry = function (item) {\n if($scope.readonly) {\n return;\n }\n\n var eventId = $scope.quote.eventId;\n var contactId = $scope.quote.contactId;\n\n if (!eventId) {\n return modalService.showMessage('transaction.message.link-to-wedding-party');\n }\n\n EventMember.query({ filterObject: { eventId: eventId } }).then(function (members) {\n Contact.getById($scope.quote.eventContactId, function (eventContact) {\n var isNotMemberOfWedding = _(members)\n .chain()\n .pluck('contactId')\n .indexOf(contactId)\n .value() === -1;\n\n if (isNotMemberOfWedding) {\n var message = $translate.instant('transaction.message.would-like-add-to-wedding-party?', { contactName: $scope.quote.contactName, firstName: eventContact.firstName, lastName: eventContact.lastName });\n var contactName = $scope.quote.contactName;\n\n return $modal.open({\n templateUrl: 'js/modules/transaction/details/modals/add-member-to-wedding.tpl.html',\n controller: function ($scope, Enums) {\n $scope.message = message;\n $scope.contactName = contactName;\n var translatedEventMemberTypes = {};\n\n // Translate event members' descriptions\n _(Enums.eventMemberTypes).each(function (value, key) {\n value.description = $translate.instant(value.description);\n translatedEventMemberTypes[key] = value;\n });\n\n $scope.eventMemberTypes = _(translatedEventMemberTypes).values();\n $scope.eventMemberType = translatedEventMemberTypes.bridesmaid;\n }\n })\n .result\n .then(function (eventMemberType) {\n // Add contact to event\n var contact = $scope.quote.contact;\n var newEventMember = new EventMember({\n bestPhoneNumber: contact.bestPhoneNumber,\n bestPhoneNumberType: contact.bestPhoneNumberType,\n contactId: contact.id,\n emailAddress: contact.emailAddress,\n eventId: eventId,\n firstName: contact.firstName,\n lastName: contact.lastName,\n typeId: eventMemberType.value,\n roleDescription: eventMemberType.description,\n createdByUser: User.username,\n modifiedByUser: User.username\n });\n\n newEventMember.$save(function (savedEventMember) {\n // Register item\n var eventItemResource = new EventItem({\n createdByUser: User.username,\n modifiedByUser: User.username,\n eventMemberId: savedEventMember.id,\n inventoryItemId: item.inventoryItemId,\n itemColor: item.itemColor,\n itemColor2: item.itemColor2,\n itemSize: item.itemSize,\n itemName: item.itemName\n });\n\n eventItemResource.$save(function (savedEventItem) {\n QuoteItem.updateEventItemId(item.id, savedEventItem.id, function (updatedItem) {\n _(item).extend(updatedItem);\n alerts.pushSuccess('alerts.transaction.successfully-linked-to-wedding-registry');\n });\n });\n });\n });\n }\n\n $modal.open({\n templateUrl: 'js/modules/quote/details/modals/register-to-wedding.tpl.html',\n controller: 'RegisterQuoteItemToWeddingCtrl',\n resolve: {\n quote: _.constant($scope.quote),\n item: _.constant(item),\n eventId: _.constant(eventId),\n contactId: _.constant(contactId),\n eventContactName: _.constant(eventContact.firstName + ' ' + eventContact.lastName),\n contactName: _.constant($scope.quote.contactName),\n members: _.constant(members)\n }\n });\n });\n });\n };\n\n $scope.unlinkItemFromWeddingRegistry = function (item) {\n if($scope.readonly) {\n return;\n }\n\n QuoteItem.updateEventItemId(item.id, 0, function(updatedItem) {\n item.version = updatedItem.version;\n item.eventItemId = 0;\n alerts.pushSuccess('alerts.transaction.successfully-unlinked-from-wedding-registry');\n });\n };\n\n $scope.addItemAddOn = function(quoteItem) {\n if($scope.readonly || !$scope.itemAddOnsPerm.set) {\n return;\n }\n\n getAvailableAddItemsOnsAndOpenModal(quoteItem, null, { fetchItemAddOns: true, showModalOnlyIfAddOnsAvailable: false, userSelected: true });\n };\n\n $scope.buildTaxAmountTooltip = function(quoteItem) {\n var text = $translate.instant('transaction.total-tax') + ': ' + $filter('currency')(quoteItem.taxAmount) + '\\n';\n\n if(quoteItem.shippingTax) {\n text += $translate.instant('transaction.shipping-tax') + ': ' + $filter('currency')(quoteItem.shippingTax);\n }\n return text;\n };\n\n $scope.buildSalePriceTooltip = function (quoteItem) {\n if(!quoteItem || !quoteItem.itemSalePrice || !quoteItem.price || quoteItem.itemSalePrice <= 0 || quoteItem.itemSalePrice >= quoteItem.price) {\n return '';\n }\n\n return $translate.instant('item.on-sale') + ': ' + $filter('currency')(quoteItem.itemSalePrice);\n };\n\n $scope.validateAddOnItemValue = function(type, addOn, oldValue) {\n if(oldValue === addOn[type]) {\n return false;\n }\n\n if(type === 'price') {\n if(addOn[type] < 0) {\n modalService.showMessage('alerts.add-ons.invalid-price');\n return false;\n } else if(!addOn[type]) {\n addOn[type] = 0;\n }\n } else if(type === 'description') {\n if(addOn[type] === '') {\n modalService.showMessage('alerts.add-ons.invalid-description');\n return false;\n }\n }\n\n return true;\n };\n\n $scope.collapseRow = function(event, quoteItem) {\n if(event) {\n event.preventDefault();\n }\n\n quoteItem.collapsed = !quoteItem.collapsed;\n };\n\n $scope.switchToEdit = function(event, addOn, type, index) {\n if(event) {\n event.preventDefault();\n }\n\n addOn[type + 'OldValue'] = addOn[type];\n addOn.show = {};\n addOn.show[type] = index;\n };\n\n $scope.switchToView = function (event, addOn, quoteItem, type, index) {\n if(!addOn.show) {\n return;\n }\n\n if(event) {\n event.preventDefault();\n }\n\n var oldValue = addOn[type + 'OldValue'];\n\n if(oldValue !== undefined && oldValue !== addOn[type]) {\n if($scope.validateAddOnItemValue(type, addOn, oldValue, quoteItem)) {\n if(type === 'price') {\n if(!addOn.price) {\n addOn.price = 0;\n }\n\n $scope.onAddOnItemPriceChange(quoteItem, addOn.price, oldValue, index);\n } else if(type === 'description') {\n $scope.saveQuoteItem(quoteItem, function () {\n alerts.pushSuccess('alerts.transaction.successfully-updated-add-on-item');\n });\n }\n } else {\n addOn[type] = oldValue;\n delete addOn[type + 'OldValue'];\n }\n }\n\n delete addOn.show;\n };\n\n $scope.onAddOnItemPriceChange = function(quoteItem, newValue, oldValue) {\n newValue = +newValue;\n\n if(newValue > oldValue) {\n quoteItem.price = quoteItem.price + (newValue - oldValue);\n } else {\n quoteItem.price = quoteItem.price - (oldValue - newValue);\n }\n\n if(quoteItem.discountType === 0) {\n quoteItem.discountPercent = 0; //let the backend compute the new discount percent\n quoteItem.adjustedPrice = quoteItem.price - quoteItem.discountAmount;\n } else {\n quoteItem.discountAmount = null; //let the backend compute the new discount amount\n }\n\n $scope.saveQuoteItem(quoteItem, function () {\n alerts.pushSuccess('alerts.transaction.successfully-updated-add-on-item');\n });\n };\n\n $scope.applySizeChange = function (quoteItem, oldSize, newSize) {\n if (!quoteItem.sizeGroup) {\n return;\n }\n\n if(($scope.isColorRequired(quoteItem) || $scope.isSizeRequired(quoteItem)) && !newSize) {\n $scope.allowInvalidSave = true;\n }\n\n //check to see if there was an upcharge on the old size, if so, the upcharge will be removed before adding another one.\n //this helps fix the issue of having an inventory item that has the upcharge already added\n //into the price.\n var oldSizeObj = _(quoteItem.sizeGroup.sizes).findWhere({ size: oldSize });\n var newSizeObj = _(quoteItem.sizeGroup.sizes).findWhere({ size: newSize });\n\n if(!newSizeObj) {\n newSizeObj = { upchargePrice: 0, upchargePriceType: 0 };\n }\n\n //if their was no size chart for the old size, create a dummy object for comparison\n if(!oldSizeObj) {\n oldSizeObj = { upchargePrice: 0, upchargePriceType: 0 };\n }\n\n var sizeUpchargeAppliedToOldSize = oldSizeObj && oldSizeObj.upchargePrice;\n\n //only change pricing if the old size upcharge is not the same as the new size upcharge\n if (oldSizeObj && newSizeObj && (oldSizeObj.upchargePrice !== newSizeObj.upchargePrice || oldSizeObj.upchargePriceType !== newSizeObj.upchargePriceType)) {\n if (!sizeUpchargeAppliedToOldSize) {\n //look up the upcharge and apply\n $scope.applySizeUpcharge(quoteItem, quoteItem.sizeGroup.sizes, newSize);\n\n if(quoteItem.discountType === 0) {\n quoteItem.discountPercent = 0; //let the backend compute the new discount percent\n quoteItem.adjustedPrice = quoteItem.price - quoteItem.discountAmount;\n } else {\n quoteItem.discountAmount = null; //let the backend compute the new discount amount\n }\n\n } else {\n //if the upcharge was applied to the old size and then they changed it to something else\n //then we need to remove the old size upcharge and apply the other one;\n $scope.removeSizeUpcharge(quoteItem, quoteItem.sizeGroup.sizes, oldSize);\n $scope.applySizeUpcharge(quoteItem, quoteItem.sizeGroup.sizes, newSize);\n\n if(quoteItem.discountType === 0) {\n quoteItem.discountPercent = 0; //let the backend compute the new discount percent\n quoteItem.adjustedPrice = quoteItem.price - quoteItem.discountAmount;\n } else {\n quoteItem.discountAmount = null; //let the backend compute the new discount amount\n }\n\n }\n }\n };\n\n $scope.applySizeUpcharge = function (quoteItem, availableSizes, itemSize) {\n if (availableSizes && availableSizes.length) {\n for (var i = 0; i < availableSizes.length; i++) {\n if (availableSizes[i].size === itemSize) {\n if (availableSizes[i].upchargePrice) {\n\n //detect which type of upcharge to apply\n if(availableSizes[i].upchargePriceType === 0) {\n quoteItem.price = quoteItem.price + availableSizes[i].upchargePrice;\n } else if(availableSizes[i].upchargePriceType === 1) {\n var upchargePercent = availableSizes[i].upchargePrice/100;\n quoteItem.price = quoteItem.price + (upchargePercent * quoteItem.price);\n quoteItem.price = Number(quoteItem.price.toFixed(2));\n } else {\n continue;\n }\n\n quoteItem.sizeUpchargeApplied = true;\n break;\n } else {\n //no size charge, get out of the loop\n break;\n }\n }\n }\n }\n };\n\n $scope.removeSizeUpcharge = function (quoteItem, availableSizes, itemSize, updateSalePrice) {\n if (availableSizes && availableSizes.length) {\n for (var i = 0; i < availableSizes.length; i++) {\n if (availableSizes[i].size === itemSize) {\n if (availableSizes[i].upchargePrice) {\n\n //detect which type of upcharge to apply\n if(availableSizes[i].upchargePriceType === 0) {\n // When add an item to a transaction and we plan to remove the up size charge. Then go ahead and do it for sales price also if it exists.\n if(updateSalePrice && quoteItem.itemSalePrice && quoteItem.itemSalePrice > 0 && quoteItem.itemSalePrice < quoteItem.price) {\n quoteItem.adjustedPrice = quoteItem.itemSalePrice - availableSizes[i].upchargePrice;\n }\n\n quoteItem.price = quoteItem.price - availableSizes[i].upchargePrice;\n } else if(availableSizes[i].upchargePriceType === 1) {\n var upchargePercent = availableSizes[i].upchargePrice/100;\n\n // When add an item to a transaction and we plan to remove the up size charge. Then go ahead and do it for sales price also if it exists.\n if(updateSalePrice && quoteItem.itemSalePrice && quoteItem.itemSalePrice > 0 && quoteItem.itemSalePrice < quoteItem.price) {\n quoteItem.adjustedPrice = quoteItem.itemSalePrice / (1 + upchargePercent);\n quoteItem.adjustedPrice = Number(quoteItem.itemSalePrice.toFixed(2));\n }\n\n quoteItem.price = quoteItem.price / (1 + upchargePercent);\n quoteItem.price = Number(quoteItem.price.toFixed(2));\n } else {\n continue;\n }\n\n quoteItem.sizeUpchargeApplied = false;\n break;\n } else {\n //no size charge, get out of the loop\n break;\n }\n }\n }\n }\n };\n\n $scope.showSizeModal = function(quoteItem, sizeGroup) {\n itemSizesModal.view(quoteItem, sizeGroup, $scope.quote.contact, true, function(size) {\n if(size) {\n $scope.applySizeChange(quoteItem, quoteItem.itemSize, size);\n quoteItem.itemSize = size;\n $scope.saveQuoteItem(quoteItem);\n }\n });\n };\n\n $scope.moreActionsPermissions = function() {\n return security.hasPermission(Permissions.DUPLICATE_QUOTES) || security.hasPermission(Permissions.DELETE_QUOTES) || security.hasPermission(Permissions.VOID_QUOTES) || (security.hasPermission(Permissions.MESSAGES) && $scope.quote.contactId);\n };\n\n $scope.showSendEmailModal = function () {\n Contact.getById($scope.quote.contactId, function (contact) {\n EmailService.showSendModal(contact, null, null, null, null, null, buildCustomEmailOptions(), null, null, null, null, $scope.quote);\n });\n };\n\n $scope.showSendTextMessageModal = function() {\n Contact.getById($scope.quote.contactId, function (contact) {\n Sms.showSendModal(contact, null, null, null, null, null, $scope.quote);\n });\n };\n\n $scope.duplicateQuote = function () {\n modalService.showConfirmation('quote.messages.would-like-to-duplicate?', function () {\n Quote.duplicate($scope.quote, User, function (newQuote) {\n ignoreRedirectWarning = true;\n $state.go('quote.edit', { id: newQuote.id });\n\n alerts.pushSuccess('alerts.quote.successfully-duplicated-quote');\n });\n });\n };\n\n $scope.voidQuote = function () {\n modalService.showConfirmation('quote.messages.would-like-to-void?',\n function () {\n Quote.void($scope.quote.id, function (quote) {\n alerts.pushSuccess('alerts.transaction.successfully-voided-order');\n $scope.quote.status = $scope.voidedStatusValue;\n $scope.readonly = true;\n });\n });\n };\n\n $scope.deleteQuote = function () {\n modalService.showConfirmation('quote.messages.would-like-to-delete-quote?',\n function () {\n Quote.delete($scope.quote).then(function () {\n ignoreRedirectWarning = true;\n alerts.pushSuccess('alerts.quote.has-been-deleted-successfully');\n $state.go('quotes');\n });\n }\n );\n };\n\n $scope.processSmartFlows = function () {\n var successCallback = function () {\n $scope.quote.smartFlowsProcessedDateTime = new Date().valueOf();\n $scope.saveQuote();\n };\n\n var failureCallback = function () {\n $scope.quote.smartFlowsProcessedDateTime = new Date().valueOf();\n $scope.saveQuote();\n };\n\n if (!$scope.quote.contactId) {\n //if no contact is assigned, see if they have toggled on the Untracked Contact feature. If so, allow the flows to process with an empty contact\n if($scope.quote.contactName) {\n eventsBus.publish('quote:created', [$scope.quote, {}, { eventDate: null }, successCallback, failureCallback]);\n } else {\n modalService.showMessage('transaction.message.assign-contact-first');\n }\n } else {\n Contact.getById($scope.quote.contactId, function (contact) {\n eventsBus.publish('quote:created', [$scope.quote, contact, { eventDate: contact.eventDate }, successCallback, failureCallback]);\n });\n }\n };\n\n $scope.isColorRequired = function(quoteItem) {\n if(quoteItem.quantity !== 0 && !quoteItem.isNonInventoryItem && !quoteItem.isService) {\n if($scope.colorAndSizeRequired || (!$scope.colorOrSizeAllowCustomVal && $scope.itemsColorOptions[quoteItem.id].length)) {\n return true;\n }\n }\n return false;\n };\n\n $scope.isSizeRequired = function(quoteItem) {\n if(quoteItem.quantity !== 0 && !quoteItem.isNonInventoryItem && !quoteItem.isService) {\n if($scope.colorAndSizeRequired || (!$scope.colorOrSizeAllowCustomVal && $scope.itemsSizeOptions[quoteItem.id].length)) {\n return true;\n }\n }\n return false;\n };\n\n $scope.goToTransaction = function(typeId, trxId) {\n $state.go(getTrxRoute(typeId), { id: trxId });\n };\n\n $scope.getTrxType = function(trxTypeId) {\n return _.findWhere(Enums.trxTypes, { value: trxTypeId });\n };\n\n function getTrxRoute(typeId) {\n var trxRoutes = {\n 1: 'transaction.sale',\n 2: 'transaction.specialOrder',\n 3: 'transaction.return',\n 4: 'transaction.layaway'\n };\n\n return trxRoutes[typeId];\n }\n\n\n $scope.buildSalePriceTooltip = function (quoteItem) {\n if(!quoteItem || !quoteItem.itemSalePrice || !quoteItem.price || quoteItem.itemSalePrice <= 0 || quoteItem.itemSalePrice >= quoteItem.price) {\n return '';\n }\n\n return $translate.instant('item.on-sale') + ': ' + $filter('currency')(quoteItem.itemSalePrice);\n };\n\n /*\n * Helpers\n */\n\n function openLeadTimesModal(quoteItem, addOnsResult, callback) {\n $modal.open({\n templateUrl: 'js/modules/quote/details/modals/add-ons.tpl.html',\n controller: 'QuoteAddOnsCtrl',\n windowClass: '__large',\n resolve: {\n quoteItem: function () {\n return quoteItem;\n },\n addOnsResult: function () {\n return addOnsResult;\n }\n }\n })\n .result\n .then(function (addOnsModalResult) {\n if(!addOnsModalResult) {\n if(callback) {\n callback();\n }\n return;\n }\n\n var quoteItemModifications = addOnsModalResult.quoteItemModifications;\n var addOnItem = addOnsModalResult.addOnItem;\n\n if(quoteItemModifications) {\n var clonedQuoteItem = angular.copy(quoteItem);\n clonedQuoteItem - _.extend(clonedQuoteItem, quoteItemModifications);\n\n $scope.saveQuoteItem(clonedQuoteItem, function () {\n quoteItem.estimatedDeliveryDate = clonedQuoteItem.estimatedDeliveryDate;\n if(addOnItem) {\n onAddLineItem(addOnItem, null, true, callback);\n }\n });\n } else if(addOnItem) {\n onAddLineItem(addOnItem, null, true, callback);\n }\n });\n }\n\n function buildCustomEmailOptions() {\n var agreements = [{ ticked: true, icon: '', description: $translate.instant('modal-service.select-a-quote-agreement') }];\n var terminalIcon = '';\n var signedIcon = $translate.instant('common.modal.signed-pen-icon');\n\n _($scope.quoteAgreements).each(function(agreement) {\n agreements.push(_.extend(agreement, {\n icon: agreement.signed ? signedIcon : '',\n ticked: false\n }));\n });\n\n _($scope.quoteTerminalContracts).each(function(contract) {\n agreements.push(_.extend(contract, {\n icon: contract.signed ? terminalIcon + ' ' + signedIcon : terminalIcon,\n ticked: false\n }));\n });\n\n return {\n showOptions: true,\n showQuoteAgreements: true,\n quoteAgreements: agreements\n };\n }\n\n function getAvailableAddItemsOnsAndOpenModal(quoteItem, item, options) {\n if(options.fetchItemAddOns) {\n var addOnRequest = {\n leadTimes: false,\n itemAddOns: true,\n quote: $scope.quote,\n quoteItem: quoteItem,\n item: item\n };\n\n QuoteItem.getAvailableAddOns(addOnRequest, function (addOnsResult) {\n //if we asked to load lead times and we have some, show the modal\n if(addOnsResult.itemAddOns === null) {\n addOnsResult.itemAddOns = [];\n }\n\n if(!options.showModalOnlyIfAddOnsAvailable || (options.showModalOnlyIfAddOnsAvailable && addOnRequest && addOnsResult.itemAddOns.length > 0)) {\n openAddOnModal(quoteItem, addOnsResult, options);\n }\n });\n }\n }\n\n function openAddOnModal(quoteItem, addOnsResult, options) {\n var allowedToClose = !$scope.itemAddOnsPerm.addOnRequired;\n\n if(options && options.userSelected) {\n allowedToClose = true;\n }\n\n $modal.open({\n templateUrl: 'js/modules/quote/details/modals/add-item-add-ons.tpl.html',\n controller: 'AddQuoteItemAddOnsCtrl',\n windowClass: '__large',\n keyboard: allowedToClose,\n backdrop: 'static',\n resolve: {\n entityType: function() {\n return 'quote';\n },\n entityItem: function () {\n return quoteItem;\n },\n addOnsResult: function () {\n return addOnsResult;\n },\n item: function () {\n return addOnsResult.item;\n },\n allowedToClose: function () {\n return allowedToClose;\n }\n }\n })\n .result\n .then(function (addOnsModalResult) {\n var quoteItemModifications = addOnsModalResult && addOnsModalResult.quoteItemModifications;\n if(quoteItemModifications && quoteItemModifications.quoteItemAddOns && quoteItemModifications.quoteItemAddOns.length) {\n $scope.saveQuoteItem(_.extend(quoteItem, quoteItemModifications));\n }\n });\n }\n\n function getAddOnItems(lineItems, currentIndex, fetchItems) {\n var quoteLineItem = lineItems[currentIndex];\n\n if(quoteLineItem && quoteLineItem.inventoryItemId) {\n Item.getById(quoteLineItem.inventoryItemId, function(item) {\n $scope.getAvailableAddOnsAndOpenModal(quoteLineItem, item, {\n showModalOnlyIfAddOnsAvailable: true,\n fetchItemAddOns: fetchItems\n }, function() {\n currentIndex++;\n var nextLineItem = lineItems[currentIndex];\n if(nextLineItem) {\n getAddOnItems(lineItems, currentIndex, fetchItems);\n }\n });\n });\n }\n }\n\n function openCustomerAddressModal(quote) {\n $modal.open({\n templateUrl: 'js/modules/quote/details/modals/customer-address-modal.tpl.html',\n controller: 'QuoteCustomerAddressCtrl',\n resolve: {\n contact: function (Contact) {\n if(quote.contactId) {\n return Contact.getById(quote.contactId);\n } else {\n return null;\n }\n },\n quote: function () {\n return quote;\n }\n },\n windowClass: '__medium'\n }).result.then(function(updatedQuote) {\n $scope.quote = updatedQuote;\n\n if(quote && quote.contactId) {\n // Update contact's address\n Contact.updateAddressFieldsFromQuote(quote, function (contact) {\n if(contact && contact.id) {\n $scope.quote.contact = contact;\n }\n });\n }\n });\n }\n\n function isCustomerAddressInvalid(quote) {\n if(quote.contactId === 0) {\n if(!quote.shipToZip) {\n return true;\n }\n } else {\n if(!quote.shipToAddress1 || !quote.shipToZip || !quote.shipToCity ||!quote.nf525InvoiceCountry) {\n return true;\n }\n }\n\n return false;\n }\n\n function updateShippingCostAndRecalculate() {\n $scope.queriesInProgress += 1;\n $scope.recalculatingTax = true;\n\n Quote.updateLineItemsAndCalculateTaxes($scope.quote, true, function(response) {\n if(response && response.quote) {\n var savedQuote = response.quote;\n\n angular.extend($scope.quote, _(savedQuote).omit(\n 'quoteLineItems',\n 'employeeId',\n 'fee',\n 'notes'\n ));\n\n updateLineItemsAfterUpdatingShippingInfo(savedQuote);\n }\n }).finally(function () {\n // without timeout saving state will be \"jumpy\"\n $timeout(function () {\n $scope.queriesInProgress -= 1;\n }, 1000);\n });\n }\n\n function updateLineItemsAfterUpdatingShippingInfo(savedQuote) {\n // Update version of all line items after updating shipping information.\n _($scope.quote.quoteLineItems).each(function (quoteItem, index) {\n quoteItem.version = savedQuote.quoteLineItems[index].version;\n quoteItem.modifiedDate = savedQuote.quoteLineItems[index].modifiedDate;\n quoteItem.modifiedByUser = savedQuote.quoteLineItems[index].modifiedByUser;\n quoteItem.addressId = savedQuote.quoteLineItems[index].addressId;\n quoteItem.taxAmount = savedQuote.quoteLineItems[index].taxAmount;\n quoteItem.shippingTax = savedQuote.quoteLineItems[index].shippingTax;\n quoteItem.shippingCost = savedQuote.quoteLineItems[index].shippingCost;\n quoteItem.shippingTaxPercent = savedQuote.quoteLineItems[index].shippingTaxPercent;\n quoteItem.shippingTaxCodeId = savedQuote.quoteLineItems[index].shippingTaxCodeId;\n quoteItem.shippingTaxable = savedQuote.quoteLineItems[index].shippingTaxable;\n quoteItem.taxCodeId = savedQuote.quoteLineItems[index].taxCodeId;\n quoteItem.taxCodeDescription = savedQuote.quoteLineItems[index].taxCodeDescription;\n quoteItem.taxCodeIsComputed = savedQuote.quoteLineItems[index].taxCodeIsComputed;\n\n _(quoteItem.quoteItemAddOns).each(function (addOn, i) {\n if(savedQuote.quoteLineItems[index].quoteItemAddOns && savedQuote.quoteLineItems[index].quoteItemAddOns.length && savedQuote.quoteLineItems[index].quoteItemAddOns[i]) {\n addOn.version = savedQuote.quoteLineItems[index].quoteItemAddOns[i].version;\n }\n });\n });\n\n $rootScope.quoteHasShippingAddress = quoteHasShippingAddress($scope.quote.quoteLineItems);\n }\n\n function quoteHasShippingAddress(items) {\n return _(items).filter(function(item) { return item.addressId; }).length;\n }\n\n function quoteHasLineItems(items) {\n return !!(items && items.length > 0);\n }\n\n function validateQuoteItems() {\n $timeout(function () {\n $scope.$broadcast('show-errors-check-validity');\n });\n }\n\n function validateThenConvert(typeId, callback) {\n if(!$scope.quote.employeeId) {\n modalService.showMessage('quote.messages.assign-associate-before-converting');\n return;\n }\n\n if($scope.markSignSalesAgreementRed) {\n modalService.showMessage('quote.messages.obtain-signature-before-converting');\n return;\n }\n\n if(!$scope.quote.smartFlowsProcessedDateTime && $scope.quote.smartFlowsTriggeredDateTime && security.hasPlanPermission('smartFlows')) {\n modalService.showMessage('quote.messages.process-smart-flow-before-converting');\n return;\n }\n\n Quote.validateBeforeConvertToTrx($scope.quote, typeId, function(result) {\n if(result) {\n if(result.errors && result.errors.length) {\n modalService.showMessage(buildConvertErrors(result.errors), 'modal-service.error');\n } else if(callback) {\n callback();\n }\n }\n });\n }\n\n function buildConvertErrors(errors) {\n var errorMessage = '';\n\n if(errors && errors.length) {\n var heading = $translate.instant('modal-service.please-correct-following-errors');\n\n errorMessage += '' + heading + '

    ';\n _(errors).each(function(error) {\n if(error.errorMessages && error.errorMessages.length) {\n _(error.errorMessages).each(function(message) {\n errorMessage += '
  • ' + message + '
  • ';\n });\n }\n });\n\n errorMessage += '
';\n }\n\n return errorMessage;\n }\n\n function itemToQuoteItem(item) {\n var taxCode = _.findWhere($scope.taxCodes, { id: item.taxCodeId });\n var quoteItemAddOns = ItemHelper.buildLineItemAddOnsTrx(item.itemAddOns, item, null, { default: true });\n var addOnTotalPrice = _.reduce(quoteItemAddOns, function(memo, num){ return memo + num.price; }, 0);\n var addOnTotalCost = _.reduce(quoteItemAddOns, function(memo, num){ return memo + num.cost; }, 0);\n\n var taxPercent = 0;\n var includedTaxPercent = 0;\n if(taxCode) {\n if(taxCode.inclusive) {\n includedTaxPercent = taxCode.percent || 0;\n } else {\n taxPercent = taxCode.percent || 0;\n }\n }\n\n var regularPrice = item.regularPrice + addOnTotalPrice;\n var adjustedPrice = regularPrice;\n var discountAmount;\n if(item.salePrice && item.salePrice > 0 && item.salePrice < item.regularPrice) {\n adjustedPrice = item.salePrice + addOnTotalPrice;\n discountAmount = regularPrice - adjustedPrice;\n }\n\n return {\n // converting\n inventoryItemId: item.id,\n price: regularPrice,\n taxCodeId: item.taxCodeId,\n taxCodeDescription: taxCode && taxCode.description,\n taxCodeIsComputed: taxCode && taxCode.computed,\n taxPercent: taxPercent,\n includedTaxPercent: includedTaxPercent,\n adjustedPrice: adjustedPrice,\n discountAmount: discountAmount,\n isInventoryItem: item.inventoryItem,\n isNonInventoryItem: item.nonInventoryItem,\n isRental: item.rental,\n isService: item.service,\n itemNumber: item.itemNumber,\n itemName: item.name,\n itemDescription: item.description,\n itemColor: colorAndSizeBlank ? '' : item.color,\n itemColor2: colorAndSizeBlank ? '' : item.color2,\n itemSize: colorAndSizeBlank ? '' : item.size,\n itemSalePrice: item.salePrice,\n itemDepartmentId: item.departmentId,\n itemVendorItemName: item.vendorItemName,\n itemOrderCost: item.orderCost + addOnTotalCost,\n doNotAllowDiscounts: item.doNotAllowDiscounts,\n quoteItemAddOns: quoteItemAddOns,\n\n // defaults\n quantity: $scope.isReturn ? -1 : 1,\n quoteId: $scope.quote.id,\n sequenceNumber: $scope.quote.quoteLineItems.length,\n createdByUser: User.username,\n createdDate: new Date().valueOf(),\n shippingCost: 0,\n shippingTax: 0,\n shippingTaxable: false\n };\n }\n\n function getDefaultQuoteAgreement(quoteSettings) {\n var setting = _(quoteSettings).findWhere({ type: 'QUOTE_DEFAULT_AGREEMENT'});\n if(setting && setting.value && setting.value > 0) {\n return _($scope.quoteAgreements).findWhere({ id: parseInt(setting.value)});\n }\n return null;\n }\n\n\n // Note popover\n (function () {\n var $notePopover;\n var notePopoverScope;\n\n var closeNotePopover = function (event) {\n if (!angular.element(event.target).parents('.popover').length && $notePopover) {\n $notePopover.popover('destroy');\n }\n };\n\n // get a Receiving Voucher item attached to passed DOM element by tracking parent tr element\n var getQuote = function (element) {\n var index = parseInt(angular.element(element).parents('tr').attr('data-index'), 10);\n return $scope.quote.quoteLineItems[index];\n };\n\n var getAddOnItem = function (element) {\n var parentIndex = parseInt(angular.element(element).parents('tr').attr('data-parent-index'), 10);\n var childIndex = parseInt(angular.element(element).parents('tr').attr('data-child-index'), 10);\n return $scope.quote.quoteLineItems[parentIndex].quoteItemAddOns[childIndex];\n };\n\n angular.element('.transaction_items').on('click', '.transaction_item-notes', function (event) {\n event.stopPropagation();\n\n if ($notePopover) {\n $notePopover.popover('destroy');\n }\n\n if (notePopoverScope) {\n notePopoverScope.$destroy();\n }\n\n var quote = getQuote(this);\n notePopoverScope = $rootScope.$new();\n notePopoverScope.item = quote;\n notePopoverScope.readonly = $scope.readonly;\n\n var template = '';\n\n $notePopover = angular.element(this).popover({\n content: $compile(template)(notePopoverScope),\n placement: 'right',\n trigger: 'manual',\n html: true\n }).popover('show');\n\n notePopoverScope.$digest();\n\n angular.element($window).on('click', closeNotePopover);\n\n // When popover is closed\n angular.element('.transaction_items').off('hidden.bs.popover').on('hidden.bs.popover', '.transaction_item-notes', function () {\n // Disable close popover handler\n angular.element($window).off('click', closeNotePopover);\n });\n });\n\n // Save quote on any input changing\n angular.element(document).off('change', '.save-trigger').on('change', '.save-trigger', function (event) {\n if (event.target.getAttribute('ng-model') === 'quote.addtlDiscountPercent') {\n $scope.quote.addtlDiscountAmount = 0;\n $scope.quote.addtlDiscountType = 1; //Percent discount type\n } else if (event.target.getAttribute('ng-model') === 'quote.addtlDiscountAmount') {\n $scope.quote.addtlDiscountPercent = 0;\n $scope.quote.addtlDiscountType = 0; //Dollar discount type\n }\n $scope.saveQuote();\n });\n\n angular.element('.transaction_items').on('click', '.transaction_item-add-on-notes', function (event) {\n event.stopPropagation();\n\n if ($notePopover) {\n $notePopover.popover('destroy');\n }\n\n if (notePopoverScope) {\n notePopoverScope.$destroy();\n }\n\n var addOnItem = getAddOnItem(this);\n notePopoverScope = $rootScope.$new();\n notePopoverScope.addOn = addOnItem;\n notePopoverScope.readonly = $scope.readonly;\n notePopoverScope.editNotes = $scope.itemAddOnsPerm.editNotes;\n\n var template = '';\n\n $notePopover = angular.element(this).popover({\n content: $compile(template)(notePopoverScope),\n placement: 'right',\n trigger: 'manual',\n html: true\n }).popover('show');\n\n notePopoverScope.$digest();\n\n angular.element($window).on('click', closeNotePopover);\n\n // When popover is closed\n angular.element('.transaction_items').off('hidden.bs.popover').on('hidden.bs.popover', '.transaction_item-add-on-notes', function () {\n // Disable close popover handler\n angular.element($window).off('click', closeNotePopover);\n });\n });\n })();\n\n if($stateParams && $stateParams.referrer === 'contact.favorites' && $stateParams.promptItemAddOns && $scope.quote && $scope.quote.quoteLineItems && $scope.quote.quoteLineItems.length) {\n getAddOnItems($scope.quote.quoteLineItems, 0, true);\n }\n\n /**\n * Handlers\n */\n\n $scope.$on('$stateChangeStart', function (event, toState, toParams) {\n if (ignoreRedirectWarning || $scope.readonly) {\n return;\n }\n\n if ($scope.isNewQuote) {\n event.preventDefault();\n\n modalService.showConfirmation('quote.messages.would-like-to-discard?', function () {\n $scope.quote.$remove(function () {\n ignoreRedirectWarning = true;\n $state.go(toState, toParams, {location: 'replace'});\n });\n });\n } else if (!$scope.quote.smartFlowsProcessedDateTime && $scope.quote.smartFlowsTriggeredDateTime && security.hasPlanPermission('smartFlows')) {\n event.preventDefault();\n\n modalService.showMessage('transaction.message.process-smart-flow-before-leaving');\n\n } else if ($scope.markSignSalesAgreementRed) {\n event.preventDefault();\n\n modalService.showMessage('transaction.message.obtain-signature-before-leaving');\n\n } else if (!$scope.quote.employeeId) {\n event.preventDefault();\n\n modalService.showMessage('transaction.message.assign-associate-before-leaving');\n } else if ($scope.isNF525 && !$scope.quote.expirationDate) {\n event.preventDefault();\n modalService.showMessage('quote.messages.set-expiration-date-before-leaving');\n }\n });\n\n /**\n * Watchers\n */\n\n var ignoreFirstTime = true;\n\n $scope.$watchCollection('[quote.contactId, quote.contactName, quote.contactPhone, quote.contactPhoneType, quote.eventDate, quote.expirationDate]', function () {\n if (!ignoreFirstTime) {\n $scope.saveQuote();\n }\n\n ignoreFirstTime = false;\n });\n\n $scope.itemsColorOptions = {};\n $scope.itemsColor2Options = {};\n $scope.itemsSizeOptions = {};\n\n $scope.$watchCollection('quote.quoteLineItems', function (items) {\n // Determine if any lineItems has a pos address assign to it.\n $rootScope.quoteHasShippingAddress = quoteHasShippingAddress(items);\n $scope.quoteHasLineItems = quoteHasLineItems(items);\n\n _(items).each(function(item) {\n $scope.itemsColorOptions[item.id] = item.colorString ? item.colorString.trim().split(',') : [];\n $scope.itemsColor2Options[item.id] = item.color2String ? item.color2String.trim().split(',') : [];\n $scope.itemsSizeOptions[item.id] = item.sizeGroup ? item.sizeGroup.sizes.map(function (size) { return size.size; }) : [];\n });\n });\n\n });\n});\n\n","define('modules/quote/details/modals/ship-to-customer-ctrl',['../../module','underscore'], function (module, _) {\n 'use strict';\n\n module.controller('ShipToCustomerQuoteModalCtrl', function($scope, $rootScope, $modalInstance, $modal, $locale, $translate, AppLicense, alerts, User, Enums, modalService, Quote, QuoteAddress, Contact, Event, EventMember, quote, addresses, eventMembers, settings, taxCodes) {\n\n var license = AppLicense.get();\n\n $scope.locale = $locale;\n $scope.states = $locale.states;\n $scope.taxCodes = _.filter(taxCodes, function(taxCode) {\n return taxCode && taxCode.description !== 'BLeCommerceTax';\n });\n\n $scope.showTaxableColumn = !(settings && settings.apiKey && settings.apiKey.length);\n\n var defaultTaxCode = _(taxCodes).findWhere({ shippingDefault: true });\n\n if(!defaultTaxCode && taxCodes && taxCodes.length) {\n defaultTaxCode = _(taxCodes).findWhere({ default: true });\n }\n\n $scope.countries = Enums.countries;\n $scope.quote = angular.copy(quote);\n\n //Preselect all the lineItems\n var customerAddress = _(addresses).findWhere({ contactId: quote.contactId });\n\n _($scope.quote.quoteLineItems).each(function (item) {\n if($scope.showTaxableColumn) {\n if(!item.shippingTaxCodeId && defaultTaxCode) {\n item.shippingTaxCodeId = defaultTaxCode.id;\n item.shippingTaxPercent = defaultTaxCode.percent;\n }\n }\n\n if(!item.addressId) {\n item.addressId = customerAddress ? customerAddress.id : null;\n }\n\n item.selected = true;\n });\n\n $scope.company = license && license.company;\n $scope.validAddress = validateAddress($scope.company);\n\n $scope.contactAddressNotValid = true;\n $scope.quoteAddressNotValid = false;\n $scope.selectAll = true;\n $scope.lineItemUpdated = false;\n $scope.flatShipping = 0;\n\n $scope.step = 1;\n\n if(!addresses || !addresses.length) {\n var contactId = $scope.quote && $scope.quote.contactId;\n\n if(contactId) {\n Contact.getById(contactId, function (contact) {\n $scope.address = buildAddressObject(contact, contactId, false, true);\n });\n }\n } else {\n var invalidQuoteAddress = _(addresses).findWhere({ quoteAddressInvalid: true });\n\n if(invalidQuoteAddress) {\n addresses = _(addresses).without(invalidQuoteAddress);\n\n $scope.step = 1;\n $scope.quoteAddressNotValid = true;\n\n $scope.address = buildAddressObject(invalidQuoteAddress, null, true, false);\n } else {\n $scope.step = 0;\n }\n\n $scope.contactAddressNotValid = false;\n }\n\n $scope.addressOptions = addresses;\n $scope.eventMembers = eventMembers;\n\n _($scope.eventMembers).each(function (member) {\n var memberType = member.eventMemberRoleDescription ? ' - ' + member.eventMemberRoleDescription : '';\n member.label = member.firstName + ' ' + (member.lastName || '') + memberType;\n });\n\n var defaultAddress = { id: null, addressHtml: buildAddressHmtl($scope.company), addressString: $translate.instant('transaction.ship-to-customer.in-store-pick-up') };\n\n $scope.addressOptions.unshift(defaultAddress);\n updateAddressDropDown($scope);\n\n $scope.selectAllEnabledItems = function (selectAll) {\n $scope.selectAll = !selectAll;\n\n _($scope.quote.quoteLineItems).each(function (item) {\n item.selected = selectAll;\n });\n };\n\n $scope.isQuoteItemDisabled = function(quoteItem) {\n if(quoteItem) {\n if(quoteItem.purchaseOrderItemId) {\n return false;\n } else {\n return quoteItem.quantity <= quoteItem.quantitySold || quoteItem.itemStatus;\n }\n }\n };\n\n $scope.addNew = function () {\n $scope.address = buildAddressObject(null, $scope.quote.contactId, false, false);\n $scope.previousStep = $scope.step;\n $scope.step = 1;\n };\n\n $scope.edit = function (address, index) {\n $scope.previousStep = $scope.step;\n $scope.addressIndex = index;\n $scope.address = buildAddressObject(address, address.contactId, true, false);\n $scope.step = 2;\n };\n\n $scope.back = function() {\n $scope.step = $scope.previousStep;\n $scope.address = buildAddressObject();\n $scope.addressIndex = null;\n };\n\n $scope.getShippingName = function(addressId) {\n var address = _($scope.addressOptions).findWhere({ id: addressId });\n\n if(address) {\n return address.firstName + ' ' + address.lastName;\n }\n\n return '';\n };\n\n $scope.onSaveClick = function () {\n if(isAddressInvalid($scope.address)) {\n return modalService.showMessage('transaction.ship-to-customer.required-address-fields');\n }\n\n if ($scope.onSaveClick.isInProgress) {\n // quit if save is already going on\n return;\n }\n\n $scope.onSaveClick.isInProgress = true;\n\n var isUpdate = false;\n\n if($scope.address && $scope.address.id) {\n $scope.address.modifiedByUser = User.username;\n $scope.address.modifiedDate = new Date();\n\n isUpdate = true;\n } else {\n $scope.address.createdByUser = User.username;\n $scope.address.createdDate = new Date();\n }\n\n $scope.address.$saveOrUpdate(function (updatedAddress) {\n $scope.contactAddressNotValid = false;\n\n if(isUpdate && !$scope.quoteAddressNotValid) {\n $scope.addressOptions[$scope.addressIndex] = updatedAddress;\n $scope.addressIndex = null;\n } else {\n $scope.addressOptions.push(updatedAddress);\n }\n\n $scope.quoteAddressNotValid = false;\n\n updateAddressDropDown($scope);\n\n $scope.step = 0;\n\n $scope.address = buildAddressObject();\n }, null).finally(function () {\n $scope.onSaveClick.isInProgress = false;\n });\n };\n $scope.onSaveClick.isInProgress = false;\n\n $scope.removeAddress = function (address, e) {\n if(e) {\n e.stopPropagation();\n }\n\n var posAddress = _(address).clone();\n\n var html = '
';\n html += ' ' + address.address1 + (address.address2 ? \", \" + address.address2 : '') + '
';\n html += address.city + ', ' + address.state + ' ' + address.zip + '
' + address.country + '
';\n\n modalService.showConfirmation({\n key: 'transaction.ship-to-customer.remove-confirmation',\n params: { addressHtml: html }\n }, function () {\n posAddress.$remove(function () {\n $scope.addressOptions = _($scope.addressOptions).without(address);\n updateAddressDropDown($scope);\n });\n });\n };\n\n $scope.onMemberChange = function(member) {\n $scope.address = buildAddressObject(member, (member && member.id));\n };\n\n $scope.setSelected = function (addressId) {\n _($scope.quote.quoteLineItems).each(function (item) {\n if(item.selected) {\n _(item.addresses).each(function (address) {\n address.ticked = address.id === addressId;\n });\n\n item.addressId = addressId;\n }\n });\n };\n\n $scope.distributeFlatShipping = function(shippingIn) {\n if(!$scope.quote.quoteLineItems || !$scope.quote.quoteLineItems.length) {\n return;\n }\n\n var selectedCount = 0;\n _($scope.quote.quoteLineItems).each( function(item) {\n if (item.selected) {\n selectedCount++;\n }\n });\n\n var shippingSplit = shippingIn / selectedCount;\n shippingSplit = Math.round(shippingSplit * 100) / 100;\n _($scope.quote.quoteLineItems).each( function(item) {\n item.shippingCost = shippingSplit;\n });\n\n $scope.quote.quoteLineItems[0].shippingCost += shippingIn - (shippingSplit * selectedCount);\n };\n\n $scope.saveAndCalculate = function () {\n var quote = angular.copy($scope.quote);\n\n _(quote.quoteLineItems).each(function (item) {\n var address = item.address[0];\n\n if(address && address.id) {\n item.addressId = address.id;\n } else {\n item.addressId = null;\n }\n\n delete item.address;\n });\n\n $scope.saving = true;\n Quote.updateLineItemsAndCalculateTaxes(quote, false, function (response) {\n alerts.pushSuccess('transaction.ship-to-customer.successfully-saved-shipping-address');\n $scope.saving = false;\n $scope.$close(response);\n }, function (data, status) {\n $scope.saving = false;\n Quote.defaultErrorHandler(data, status);\n });\n };\n\n $scope.onClose = function() {\n $scope.$close(null);\n };\n\n $scope.getCountry = function (entity) {\n return getCountryName(entity);\n };\n\n $scope.onAddressChanged = function (data, quoteItem) {\n if(data) {\n quoteItem.addressId = data.id;\n }\n };\n\n $scope.onTaxCodeChange = function (quoteItem) {\n var taxCode = _(taxCodes).findWhere({ id: quoteItem.shippingTaxCodeId });\n if(taxCode) {\n quoteItem.shippingTaxPercent = taxCode.percent;\n quoteItem.shippingTaxCodeId = taxCode.id;\n }\n };\n\n /**\n * Helpers\n */\n\n function getCountryName(entity) {\n var countryValue = entity && entity.locale ? entity.locale : entity && entity.country;\n var country = _(Enums.locales).findWhere({ value: countryValue });\n\n if(country) {\n return $translate.instant(country.label);\n }\n\n return countryValue;\n }\n\n function buildAddressHmtl(entity) {\n var name = entity && entity.firstName ? entity.firstName + (entity.lastName ? ' ' + entity.lastName : '') : $translate.instant('transaction.ship-to-customer.in-store-pick-up');\n\n var html = '

' + name + '

';\n\n if(entity && entity.name) {\n html += entity.name + '
';\n }\n\n html += entity.address1 + (entity.address2 ? ', ' + entity.address2 : '') + '
';\n html += entity.city + ', ' + entity.state + ' ' + entity.zip + '
' + getCountryName(entity) + '
';\n return html;\n }\n\n function updateAddressDropDown($scope) {\n _($scope.addressOptions).each(function (address) {\n if(address.id) {\n address.addressHtml = buildAddressHmtl(address);\n }\n });\n\n _($scope.quote.quoteLineItems).each(function (item) {\n item.addresses = angular.copy($scope.addressOptions);\n\n var address = _(item.addresses).findWhere({ id: item.addressId });\n\n if(address) {\n item.address = [address];\n } else {\n item.addressId = null;\n item.address = [defaultAddress];\n }\n\n _(item.addresses).each(function (address) {\n address.ticked = item.addressId === address.id;\n });\n });\n }\n\n function isAddressInvalid(address) {\n if(!address || !address.firstName || !address.lastName || !address.address1 || !address.city || !address.state || !address.zip || !address.country) {\n return true;\n }\n\n return false;\n }\n\n function validateAddress(company) {\n if(!company) {\n return false;\n }\n\n if(!company.address1 || !company.city || !company.state || !company.zip || !company.locale) {\n return false;\n }\n\n return true;\n }\n\n function buildAddressObject(address, contactId, isEdit, isNew) {\n if(isEdit) {\n address.updateContactAddress = address.quoteId ? false : true;\n\n return address;\n } else {\n return new QuoteAddress ({\n firstName: address && address.firstName ? address.firstName : '',\n lastName: address && address.lastName ? address.lastName : '',\n state: address && address.state ? findState(address.state) : '',\n city: address && address.city ? address.city : '',\n zip: address && address.zip ? address.zip : '',\n address1: address && address.address1 ? address.address1 : '',\n address2: address && address.address2 ? address.address2 : '',\n country: address && address.country ? address.country : $locale.defaultCountryValue ? $locale.defaultCountryValue : '',\n addressString: address ? buildAddressString(address) : '',\n updateContactAddress: !!isNew,\n contactId: contactId ? contactId : null\n });\n }\n }\n\n function findState(stateValue) {\n var state = _($locale.states).findWhere({ value: stateValue });\n if(state) {\n return state.value;\n }\n }\n\n function buildAddressString(addressIn) {\n return addressIn.address1 + (addressIn.address2 ? \", \" + addressIn.address2 : \"\") + \"\\n\" + addressIn.city + \", \" + addressIn.state + \", \" + addressIn.zip;\n }\n });\n});\n\n","define('modules/quote/search/search-ctrl',['./../module', 'angular', 'underscore'], function (module, angular, _) {\n 'use strict';\n\n module.controller('QuoteSearchCtrl', function ($scope, $state, $stateParams, $controller, $modal, $translate, $timeout, $locale, $filter,\n Enums, Quote, employees, alerts, modalService, ResourcesHelper, Transaction, security, Contact, User) {\n\n $scope.locale = $locale;\n\n $scope.isUS = $locale.isUS;\n\n $scope.statuses = [\n Enums.statuses.all,\n Enums.statuses.pending,\n Enums.statuses.converted,\n Enums.statuses.voided,\n ];\n\n $scope.enumStatuses = Enums.statuses;\n\n var headers = [\n {\n title: ''\n },\n {\n title: 'quote.quote-#',\n sortField: 'quoteNumber'\n },\n {\n title: 'contact.purchase.headers.trx-#',\n sortField: 'convertedTransactionNumber'\n },\n {\n title: 'reports.headers.created-date',\n sortField: 'createdDate',\n active: true\n },\n {\n title: 'common.contact',\n sortField: 'contactName'\n },\n {\n title: 'common.modal.event-date',\n sortField: 'eventDate'\n },\n {\n title: 'transaction.event-contact',\n sortField: 'eventContactName'\n },\n {\n title: 'common.associate',\n sortField: 'employeeName',\n hideOnTablets: true\n },\n {\n title: 'purchase-order.total',\n sortField: 'totalAmount'\n },\n ];\n\n $scope.doIgnoreMemorizeSearch = !!_($stateParams).chain().values().compact().value().length;\n\n $scope.perms = {\n create: security.hasPermission('QUOTES'),\n view: security.hasPermission('VIEW_QUOTES'),\n edit: security.hasPermission('EDIT_QUOTES'),\n delete: security.hasPermission('DELETE_QUOTES'),\n void: security.hasPermission('VOID_QUOTES'),\n duplicate: security.hasPermission('DUPLICATE_QUOTES'),\n convert: security.hasPermission('CONVERT_QUOTES')\n };\n\n angular.extend(this, $controller('SearchCtrl', { $scope: $scope, headers: headers }));\n\n var status = $stateParams.status || Enums.statuses.all.value;\n $scope.initialValues = { eventDateBefore: $stateParams.eventDateBefore, status: status, createdDate: $stateParams.quoteStartDate, createdDateBefore: $stateParams.quoteEndDate};\n $scope.formValues = angular.copy($scope.initialValues);\n $scope.memorizeSearch();\n\n if(employees) {\n employees = ResourcesHelper.adaptList('employees', employees);\n employees.unshift({ fullName: $translate.instant('common.all') });\n }\n\n $scope.employees = employees;\n\n $scope.results = $scope.selectedResults = [];\n $scope.search = function () {\n Quote.query($scope.buildFilterObject(), function (resultModel) {\n $scope.updateResults(resultModel);\n });\n };\n\n $scope.bulkPrint = function () {\n if (!$scope.selectedResults.length) {\n return modalService.showMessage('transaction.message.select-at-least-one', 'common.message.wooops');\n }\n\n Quote.bulkPrint(_($scope.selectedResults).pluck('id'));\n };\n\n // $scope.bulkConvert = function (typeId) {\n // validateThenBulkConvert(typeId, function () {\n // modalService.showConfirmation({\n // key: 'quote.messages.are-you-sure-you-would-like-to-convert-quotes?',\n // params: { number: $scope.selectedResults.length, type: $translate.instant($scope.getTrxType(typeId).description)}\n // }, function () {\n // Quote.bulkConvertToTransaction(User.id, typeId, _($scope.selectedResults).pluck('id'), function (result) {\n // $scope.search();\n // alerts.pushSuccess({\n // key: 'quote.messages.successfully-converted',\n // params: { number: result.nbrRowsAffected }\n // });\n // });\n // });\n // });\n // };\n\n function validateThenBulkConvert(typeId, callback) {\n if(!$scope.perms.convert) {\n return modalService.showMessage('security.permission-denied', 'security.permission-denied');\n }\n\n if(!$scope.selectedResults.length) {\n return modalService.showMessage('transaction.message.select-at-least-one', 'common.message.wooops');\n }\n\n if($scope.selectedResults.length > 10) {\n return modalService.showMessage('quote.messages.too-many-to-convert', 'common.message.wooops');\n }\n\n var statuses = _($scope.selectedResults).pluck('status');\n if (_.contains(statuses, Enums.statuses.converted.value)) {\n return modalService.showMessage('quote.messages.already-converted', 'common.message.wooops');\n }\n\n for(var i = 0; i < $scope.selectedResults.length; i++) {\n var quote = $scope.selectedResults[i];\n\n if(quote && !quote.smartFlowsProcessedDateTime && quote.smartFlowsTriggeredDateTime && security.hasPlanPermission('smartFlows')) {\n modalService.showMessage('transaction.message.process-smart-flow-before-completing', 'transaction.smart-flows');\n return;\n }\n }\n\n Quote.validateBeforeBulkConvertToTrx($scope.selectedResults, typeId, function(result) {\n if(result) {\n if(result.errors && result.errors.length) {\n modalService.showMessage(buildConvertErrors(result.errors), 'modal-service.error');\n } else if(callback) {\n callback();\n }\n }\n });\n }\n\n function buildConvertErrors(errors) {\n var errorMessage = '';\n\n if(errors && errors.length) {\n var heading = $translate.instant('modal-service.please-correct-following-errors');\n\n errorMessage += '' + heading + '

    ';\n _(errors).each(function(error) {\n if(error.errorMessages && error.errorMessages.length) {\n _(error.errorMessages).each(function(message) {\n errorMessage += '
  • ' + message + '
  • ';\n });\n }\n });\n\n errorMessage += '
';\n }\n\n return errorMessage;\n }\n\n $scope.duplicate = function(quote) {\n if($scope.perms.duplicate) {\n Quote.duplicate(quote, User, function () {\n $scope.search();\n });\n } else {\n modalService.showMessage('security.permission-denied', 'security.permission-denied');\n }\n };\n\n $scope.createQuote = function() {\n if($scope.perms && $scope.perms.create) {\n $state.go('quote.create');\n }\n };\n\n $scope.delete = function(quote) {\n if($scope.perms.delete) {\n modalService.showConfirmation('quote.messages.would-like-to-delete-quote?', function () {\n quote.$remove(function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'quote.messages.successfully-deleted',\n params: { number: 1 }\n });\n });\n });\n } else {\n modalService.showMessage('security.permission-denied', 'security.permission-denied');\n }\n };\n\n $scope.bulkDelete = function() {\n var selectedItems = _($scope.results).where({ checked: true });\n\n if(!selectedItems.length) {\n return modalService.showMessage('quote.messages.select-one-quote-to-delete');\n }\n\n if($scope.selectedResults.length > 100) {\n return modalService.showMessage('quote.messages.too-many-to-delete', 'common.message.wooops');\n }\n\n modalService.showConfirmation({ key: 'quote.messages.are-you-sure-you-would-like-to-delete-quotes?', params: { number: $scope.selectedResults.length }}, function () {\n Quote.bulkDelete({ ids: _(selectedItems).pluck('id'), contactIds: _(selectedItems).pluck('contactId') }, function (result) {\n $scope.search();\n alerts.pushSuccess({\n key: 'quote.messages.successfully-deleted',\n params: { number: result.nbrRowsAffected }\n });\n });\n });\n };\n\n $scope.bulkVoid = function() {\n var selectedItems = _($scope.results).where({ checked: true });\n\n if(!selectedItems.length) {\n return modalService.showMessage('quote.messages.select-one-quote-to-void');\n }\n\n if($scope.selectedResults.length > 100) {\n return modalService.showMessage('quote.messages.too-many-to-void', 'common.message.wooops');\n }\n\n modalService.showConfirmation({ key: 'quote.messages.are-you-sure-you-would-like-to-void-quotes?', params: { number: $scope.selectedResults.length }}, function () {\n Quote.bulkVoid({ ids: _(selectedItems).pluck('id'), contactIds: _(selectedItems).pluck('contactId') }, function (result) {\n $scope.search();\n alerts.pushSuccess({\n key: 'quote.messages.successfully-voided',\n params: { number: result.nbrRowsAffected }\n });\n });\n });\n };\n\n $scope.changeEmployee = function (emp) {\n if(!$scope.selectedResults.length) {\n modalService.showMessage('quote.messages.select-at-least-one-quote', 'common.message.wooops');\n return false;\n }\n\n var successcb = function () {\n $scope.search();\n alerts.pushSuccess({\n key: 'quote.messages.successfully-assigned',\n params: {\n number: $scope.selectedResults.length,\n firstName: emp.firstName,\n lastName: emp.lastName\n }\n });\n };\n\n modalService.showConfirmation({\n key: 'quote.messages.are-you-sure-you-would-like-to-assign?',\n params: {\n number: $scope.selectedResults.length,\n firstName: emp.firstName,\n lastName: emp.lastName\n }\n }, function () {\n Quote.bulkUpdateEmployee(emp.id, _($scope.selectedResults).pluck('id'), successcb);\n });\n };\n\n $scope.exportToExcel = function () {\n if (!$scope.selectedResults.length) {\n modalService.showMessage('transaction.message.select-at-least-one', 'common.message.wooops');\n return false;\n }\n\n modalService.showConfirmation({\n key: 'transaction.message.would-like-export-to-excel?',\n params: { number: $scope.selectedResults.length }\n }, function () {\n Quote.exportToExcel(_($scope.selectedResults).pluck('id'));\n });\n };\n\n $scope.gotoQuote = function (quote) {\n $state.go('quote.edit', { id: quote.id });\n };\n\n $scope.chooseEventContact = function(eventContact) {\n $scope.eventContact = eventContact;\n $scope.formValues.eventContactId = eventContact.id;\n $scope.formValues.eventContactName = eventContact.firstName + ' ' + eventContact.lastName;\n $scope.eventContactName = $scope.formValues.eventContactName;\n };\n\n $scope.unselectEventContact = function() {\n $scope.eventContact = null;\n $scope.formValues.eventContactId = null;\n $scope.formValues.eventContactName = null;\n $scope.eventContactName = null;\n };\n\n $scope.buildStatusTooltip = function(quote) {\n if(quote.status === $scope.enumStatuses.pending.value) {\n return $translate.instant($scope.enumStatuses.pending.description);\n } else if(quote.status === $scope.enumStatuses.converted.value && quote.convertedDate) {\n return $filter('date')(quote.convertedDate, 'mediumDate');\n }\n\n return '';\n };\n\n $scope.goToTransaction = function(typeId, trxId) {\n $state.go(getTrxRoute(typeId), { id: trxId });\n };\n\n $scope.getTrxType = function(trxTypeId) {\n return _.findWhere(Enums.trxTypes, { value: trxTypeId });\n };\n\n function getTrxRoute(typeId) {\n var trxRoutes = {\n 1: 'transaction.sale',\n 2: 'transaction.specialOrder',\n 3: 'transaction.return',\n 4: 'transaction.layaway'\n };\n\n return trxRoutes[typeId];\n }\n\n /**\n * Init\n */\n\n $timeout(function () {\n if($scope.formValues.eventContactId) {\n Contact.getById($scope.formValues.eventContactId, $scope.chooseEventContact);\n }\n });\n });\n});\n\n","define('modules/reports/common-ctrl',['angular', 'underscore'], function (angular, _) {\n 'use strict';\n /**\n * This common controller contains all of the common functions\n * for running reports.\n */\n return angular.module('bl.reports.common', [])\n .controller('CommonReportsCtrl', function ($scope, $translate, headers, security, AppLicense) {\n $scope.security = security;\n $scope.sortHeaders = headers;\n $scope.colspan = _(headers).filter(function(header) {\n return !header.isHidden;\n }).length;\n\n var license = AppLicense.get();\n var multiLocations = [];\n if(license && license.linkedAccounts && license.linkedAccounts.length && license.plan && license.plan.multiStore) {\n multiLocations = angular.copy(license.linkedAccounts);\n }\n\n var isAllPerPage = function () {\n return $scope.pagination.perPage === 'All';\n };\n\n var isAllLocations = function () {\n return $scope.formValues.retailerId === 'ALL_LOCATIONS';\n };\n\n $scope.buildReportsObject = function () {\n var reportsObject = {\n criteria: $scope.formValues,\n page: $scope.pagination.page,\n size: isAllPerPage() ? '' : $scope.pagination.perPage,\n sortField: $scope.pagination.sortField,\n sortDirection: $scope.pagination.sortDirection\n };\n\n if($scope.formValues.hasOwnProperty(\"selectedDepartments\")) {\n reportsObject.criteria.departmentIds = _($scope.formValues.selectedDepartments).pluck(\"id\");\n }\n\n if($scope.formValues.hasOwnProperty(\"selectedVendors\")) {\n reportsObject.criteria.vendorIds = _($scope.formValues.selectedVendors).pluck(\"id\");\n }\n\n if($scope.formValues.hasOwnProperty(\"selectedMethods\")) {\n reportsObject.criteria.methodIds = _($scope.formValues.selectedMethods).pluck(\"id\");\n }\n\n if($scope.formValues.hasOwnProperty(\"selectedAttributes\")) {\n reportsObject.criteria.attributeIds = _($scope.formValues.selectedAttributes).chain().pluck(\"attributeIds\").flatten().value();\n }\n\n if($scope.formValues.hasOwnProperty(\"appointmentTypes\")) {\n reportsObject.criteria.appointmentTypeIds = _($scope.formValues.appointmentTypes).pluck(\"id\");\n }\n\n return reportsObject;\n };\n\n function setSortProperties(header) {\n if (!header.sortField) {\n return false;\n }\n\n if ($scope.pagination.sortField === header.sortField) {\n $scope.pagination.sortDirection = $scope.pagination.sortDirection === 'asc' ? 'desc' : 'asc';\n }\n\n $scope.pagination.sortField = header.sortField;\n\n if ($scope.activeHeader) {\n $scope.activeHeader.active = false;\n }\n\n header.active = true;\n $scope.activeHeader = header;\n }\n\n // pagination settings wrapper\n $scope.pagination = {\n page: 1,\n perPage: 25,\n perPageOptions: [\n { size: 10, label: 10 },\n { size: 25, label: 25 },\n { size: 50, label: 50 },\n { size: 100, label: 100 },\n { size: '', label: $translate.instant('common.all') }\n ],\n totalItems: 0,\n sortField: $scope.sortHeaders[0].sortField,\n sortDirection: 'desc'\n };\n\n $scope.activeHeader = $scope.sortHeaders[0];\n setSortProperties($scope.activeHeader);\n\n $scope.sort = function (header) {\n setSortProperties(header);\n $scope.newSearch();\n $scope.runReport();\n };\n\n /**\n * Returns user back to first page and fires runReport\n */\n $scope.newSearch = function () {\n $scope.pagination.page = 1;\n };\n\n /**\n * Goes 1 page forward\n * @param $event\n */\n $scope.nextPage = function ($event) {\n if ($event) {\n $event.preventDefault();\n }\n\n if ($scope.pagination.nextDisabled) {\n return;\n }\n\n $scope.pagination.page += 1;\n $scope.selectAll = false;\n $scope.runReport();\n };\n\n /**\n * Goes 1 page backward\n * @param $event\n */\n $scope.previousPage = function ($event) {\n if ($event) {\n $event.preventDefault();\n }\n\n if ($scope.pagination.previousDisabled) {\n return;\n }\n\n if ($scope.pagination.page > 0) {\n $scope.pagination.page -= 1;\n }\n $scope.selectAll = false;\n $scope.runReport();\n };\n\n $scope.reset = function () {\n $scope.formValues = $scope.initialValues;\n };\n\n $scope.syncSelectedResults = function (task) {\n var checkedTaskWasSelected = _($scope.selectedResults).findWhere({ id: task.id });\n if (checkedTaskWasSelected) {\n $scope.selectedResults = _($scope.selectedResults).without(checkedTaskWasSelected);\n } else {\n $scope.selectedResults.push(task);\n }\n };\n\n $scope.selectAll = false;\n $scope.toggleSelectAll = function (removeAll) {\n $scope.selectAll = !$scope.selectAll;\n if ($scope.selectAll) {\n $scope.selectedResults = _.union($scope.selectedResults, $scope.results);\n } else {\n $scope.selectedResults = removeAll ? [] : _($scope.selectedResults).difference($scope.results);\n }\n\n //toggle all contacts\n $scope.results = _($scope.results).map(function (task) {\n task.checked = $scope.selectAll;\n return task;\n });\n };\n\n $scope.uncheckSelectedResults = function () {\n $scope.selectAll = true;\n $scope.toggleSelectAll(true);\n };\n\n $scope.updateResults = function (resultModel) {\n populateRetailerLocation(resultModel);\n $scope.results = resultModel.result;\n $scope.pagination.totalItems = resultModel.total;\n $scope.pagination.page = resultModel.page;\n $scope.pagination.totalAfterFilter = resultModel.totalAfterFilter;\n $scope.pagination.previousDisabled = ($scope.pagination.page === 1);\n $scope.pagination.nextDisabled = (isAllPerPage() || $scope.pagination.totalItems <= $scope.pagination.page * $scope.pagination.perPage);\n\n if(isAllPerPage()) {\n $scope.pagination.showingFrom = 1;\n $scope.pagination.showingTo = $scope.pagination.totalItems;\n } else {\n $scope.pagination.showingFrom = ($scope.pagination.page - 1) * $scope.pagination.perPage + 1;\n $scope.pagination.showingTo = Math.min($scope.pagination.page * $scope.pagination.perPage, $scope.pagination.totalItems);\n }\n\n // Check all previously selected contacts\n if(($scope.selectedResults && $scope.selectedResults.length) || ($scope.results && $scope.results.length)) {\n $scope.results = _($scope.results).map(function (task) {\n var foundTask = _($scope.selectedResults).findWhere({ id: task.id });\n if (foundTask && foundTask.checked) {\n task.checked = true;\n }\n return task;\n });\n }\n\n if($scope.drawGraph) {\n $scope.drawGraph($scope.results);\n }\n\n // calculates permissions to conditionally hide/show layout items in results table\n // is done in a function to\n $scope.permissions = {\n ITEM_COST: security.hasPermission('ITEM_COST')\n };\n };\n\n $scope.initializeResults = function() {\n $scope.results = [];\n $scope.pagination.totalItems = 0;\n $scope.pagination.page = 1;\n $scope.pagination.previousDisabled = true;\n $scope.pagination.nextDisabled = true;\n $scope.pagination.showingFrom = 1;\n $scope.pagination.showingTo = 1;\n };\n\n /**\n * Populates location name if needed\n * @param resultModel\n */\n function populateRetailerLocation(resultModel) {\n if(isAllLocations() && multiLocations && multiLocations.length && resultModel.criteria.retailerIds && resultModel.criteria.retailerIds.length) {\n var retailerMap = {};\n _.each(resultModel.result, function(result) {\n if(result.retailerId) {\n if(!retailerMap.hasOwnProperty(result.retailerId)) {\n retailerMap[result.retailerId] = getCompanyNickName(result.retailerId, multiLocations);\n }\n\n result.location = retailerMap[result.retailerId];\n result.locationRetailerId = result.retailerId;\n }\n });\n }\n }\n\n function getCompanyNickName(retailerId, locations) {\n var location = _(locations).findWhere({ linkedRetailerId: retailerId });\n return location && location.nickName;\n }\n\n // Listen deep changes of formValues\n $scope.$watch('formValues', _.throttle($scope.newSearch, 500), true);\n });\n});\n\n","/*!\n * Chart.js\n * http://chartjs.org/\n * Version: 2.5.0\n *\n * Copyright 2017 Nick Downie\n * Released under the MIT license\n * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md\n */\n(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define('chart',[],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.Chart = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o lum2) {\n\t\t\treturn (lum1 + 0.05) / (lum2 + 0.05);\n\t\t}\n\t\treturn (lum2 + 0.05) / (lum1 + 0.05);\n\t},\n\n\tlevel: function (color2) {\n\t\tvar contrastRatio = this.contrast(color2);\n\t\tif (contrastRatio >= 7.1) {\n\t\t\treturn 'AAA';\n\t\t}\n\n\t\treturn (contrastRatio >= 4.5) ? 'AA' : '';\n\t},\n\n\tdark: function () {\n\t\t// YIQ equation from http://24ways.org/2010/calculating-color-contrast\n\t\tvar rgb = this.values.rgb;\n\t\tvar yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000;\n\t\treturn yiq < 128;\n\t},\n\n\tlight: function () {\n\t\treturn !this.dark();\n\t},\n\n\tnegate: function () {\n\t\tvar rgb = [];\n\t\tfor (var i = 0; i < 3; i++) {\n\t\t\trgb[i] = 255 - this.values.rgb[i];\n\t\t}\n\t\tthis.setValues('rgb', rgb);\n\t\treturn this;\n\t},\n\n\tlighten: function (ratio) {\n\t\tvar hsl = this.values.hsl;\n\t\thsl[2] += hsl[2] * ratio;\n\t\tthis.setValues('hsl', hsl);\n\t\treturn this;\n\t},\n\n\tdarken: function (ratio) {\n\t\tvar hsl = this.values.hsl;\n\t\thsl[2] -= hsl[2] * ratio;\n\t\tthis.setValues('hsl', hsl);\n\t\treturn this;\n\t},\n\n\tsaturate: function (ratio) {\n\t\tvar hsl = this.values.hsl;\n\t\thsl[1] += hsl[1] * ratio;\n\t\tthis.setValues('hsl', hsl);\n\t\treturn this;\n\t},\n\n\tdesaturate: function (ratio) {\n\t\tvar hsl = this.values.hsl;\n\t\thsl[1] -= hsl[1] * ratio;\n\t\tthis.setValues('hsl', hsl);\n\t\treturn this;\n\t},\n\n\twhiten: function (ratio) {\n\t\tvar hwb = this.values.hwb;\n\t\thwb[1] += hwb[1] * ratio;\n\t\tthis.setValues('hwb', hwb);\n\t\treturn this;\n\t},\n\n\tblacken: function (ratio) {\n\t\tvar hwb = this.values.hwb;\n\t\thwb[2] += hwb[2] * ratio;\n\t\tthis.setValues('hwb', hwb);\n\t\treturn this;\n\t},\n\n\tgreyscale: function () {\n\t\tvar rgb = this.values.rgb;\n\t\t// http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale\n\t\tvar val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11;\n\t\tthis.setValues('rgb', [val, val, val]);\n\t\treturn this;\n\t},\n\n\tclearer: function (ratio) {\n\t\tvar alpha = this.values.alpha;\n\t\tthis.setValues('alpha', alpha - (alpha * ratio));\n\t\treturn this;\n\t},\n\n\topaquer: function (ratio) {\n\t\tvar alpha = this.values.alpha;\n\t\tthis.setValues('alpha', alpha + (alpha * ratio));\n\t\treturn this;\n\t},\n\n\trotate: function (degrees) {\n\t\tvar hsl = this.values.hsl;\n\t\tvar hue = (hsl[0] + degrees) % 360;\n\t\thsl[0] = hue < 0 ? 360 + hue : hue;\n\t\tthis.setValues('hsl', hsl);\n\t\treturn this;\n\t},\n\n\t/**\n\t * Ported from sass implementation in C\n\t * https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209\n\t */\n\tmix: function (mixinColor, weight) {\n\t\tvar color1 = this;\n\t\tvar color2 = mixinColor;\n\t\tvar p = weight === undefined ? 0.5 : weight;\n\n\t\tvar w = 2 * p - 1;\n\t\tvar a = color1.alpha() - color2.alpha();\n\n\t\tvar w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0;\n\t\tvar w2 = 1 - w1;\n\n\t\treturn this\n\t\t\t.rgb(\n\t\t\t\tw1 * color1.red() + w2 * color2.red(),\n\t\t\t\tw1 * color1.green() + w2 * color2.green(),\n\t\t\t\tw1 * color1.blue() + w2 * color2.blue()\n\t\t\t)\n\t\t\t.alpha(color1.alpha() * p + color2.alpha() * (1 - p));\n\t},\n\n\ttoJSON: function () {\n\t\treturn this.rgb();\n\t},\n\n\tclone: function () {\n\t\t// NOTE(SB): using node-clone creates a dependency to Buffer when using browserify,\n\t\t// making the final build way to big to embed in Chart.js. So let's do it manually,\n\t\t// assuming that values to clone are 1 dimension arrays containing only numbers,\n\t\t// except 'alpha' which is a number.\n\t\tvar result = new Color();\n\t\tvar source = this.values;\n\t\tvar target = result.values;\n\t\tvar value, type;\n\n\t\tfor (var prop in source) {\n\t\t\tif (source.hasOwnProperty(prop)) {\n\t\t\t\tvalue = source[prop];\n\t\t\t\ttype = ({}).toString.call(value);\n\t\t\t\tif (type === '[object Array]') {\n\t\t\t\t\ttarget[prop] = value.slice(0);\n\t\t\t\t} else if (type === '[object Number]') {\n\t\t\t\t\ttarget[prop] = value;\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error('unexpected color value:', value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t}\n};\n\nColor.prototype.spaces = {\n\trgb: ['red', 'green', 'blue'],\n\thsl: ['hue', 'saturation', 'lightness'],\n\thsv: ['hue', 'saturation', 'value'],\n\thwb: ['hue', 'whiteness', 'blackness'],\n\tcmyk: ['cyan', 'magenta', 'yellow', 'black']\n};\n\nColor.prototype.maxes = {\n\trgb: [255, 255, 255],\n\thsl: [360, 100, 100],\n\thsv: [360, 100, 100],\n\thwb: [360, 100, 100],\n\tcmyk: [100, 100, 100, 100]\n};\n\nColor.prototype.getValues = function (space) {\n\tvar values = this.values;\n\tvar vals = {};\n\n\tfor (var i = 0; i < space.length; i++) {\n\t\tvals[space.charAt(i)] = values[space][i];\n\t}\n\n\tif (values.alpha !== 1) {\n\t\tvals.a = values.alpha;\n\t}\n\n\t// {r: 255, g: 255, b: 255, a: 0.4}\n\treturn vals;\n};\n\nColor.prototype.setValues = function (space, vals) {\n\tvar values = this.values;\n\tvar spaces = this.spaces;\n\tvar maxes = this.maxes;\n\tvar alpha = 1;\n\tvar i;\n\n\tif (space === 'alpha') {\n\t\talpha = vals;\n\t} else if (vals.length) {\n\t\t// [10, 10, 10]\n\t\tvalues[space] = vals.slice(0, space.length);\n\t\talpha = vals[space.length];\n\t} else if (vals[space.charAt(0)] !== undefined) {\n\t\t// {r: 10, g: 10, b: 10}\n\t\tfor (i = 0; i < space.length; i++) {\n\t\t\tvalues[space][i] = vals[space.charAt(i)];\n\t\t}\n\n\t\talpha = vals.a;\n\t} else if (vals[spaces[space][0]] !== undefined) {\n\t\t// {red: 10, green: 10, blue: 10}\n\t\tvar chans = spaces[space];\n\n\t\tfor (i = 0; i < space.length; i++) {\n\t\t\tvalues[space][i] = vals[chans[i]];\n\t\t}\n\n\t\talpha = vals.alpha;\n\t}\n\n\tvalues.alpha = Math.max(0, Math.min(1, (alpha === undefined ? values.alpha : alpha)));\n\n\tif (space === 'alpha') {\n\t\treturn false;\n\t}\n\n\tvar capped;\n\n\t// cap values of the space prior converting all values\n\tfor (i = 0; i < space.length; i++) {\n\t\tcapped = Math.max(0, Math.min(maxes[space][i], values[space][i]));\n\t\tvalues[space][i] = Math.round(capped);\n\t}\n\n\t// convert to all the other color spaces\n\tfor (var sname in spaces) {\n\t\tif (sname !== space) {\n\t\t\tvalues[sname] = convert[space][sname](values[space]);\n\t\t}\n\t}\n\n\treturn true;\n};\n\nColor.prototype.setSpace = function (space, args) {\n\tvar vals = args[0];\n\n\tif (vals === undefined) {\n\t\t// color.rgb()\n\t\treturn this.getValues(space);\n\t}\n\n\t// color.rgb(10, 10, 10)\n\tif (typeof vals === 'number') {\n\t\tvals = Array.prototype.slice.call(args);\n\t}\n\n\tthis.setValues(space, vals);\n\treturn this;\n};\n\nColor.prototype.setChannel = function (space, index, val) {\n\tvar svalues = this.values[space];\n\tif (val === undefined) {\n\t\t// color.red()\n\t\treturn svalues[index];\n\t} else if (val === svalues[index]) {\n\t\t// color.red(color.red())\n\t\treturn this;\n\t}\n\n\t// color.red(100)\n\tsvalues[index] = val;\n\tthis.setValues(space, svalues);\n\n\treturn this;\n};\n\nif (typeof window !== 'undefined') {\n\twindow.Color = Color;\n}\n\nmodule.exports = Color;\n\n},{\"2\":2,\"5\":5}],4:[function(require,module,exports){\n/* MIT license */\n\nmodule.exports = {\n rgb2hsl: rgb2hsl,\n rgb2hsv: rgb2hsv,\n rgb2hwb: rgb2hwb,\n rgb2cmyk: rgb2cmyk,\n rgb2keyword: rgb2keyword,\n rgb2xyz: rgb2xyz,\n rgb2lab: rgb2lab,\n rgb2lch: rgb2lch,\n\n hsl2rgb: hsl2rgb,\n hsl2hsv: hsl2hsv,\n hsl2hwb: hsl2hwb,\n hsl2cmyk: hsl2cmyk,\n hsl2keyword: hsl2keyword,\n\n hsv2rgb: hsv2rgb,\n hsv2hsl: hsv2hsl,\n hsv2hwb: hsv2hwb,\n hsv2cmyk: hsv2cmyk,\n hsv2keyword: hsv2keyword,\n\n hwb2rgb: hwb2rgb,\n hwb2hsl: hwb2hsl,\n hwb2hsv: hwb2hsv,\n hwb2cmyk: hwb2cmyk,\n hwb2keyword: hwb2keyword,\n\n cmyk2rgb: cmyk2rgb,\n cmyk2hsl: cmyk2hsl,\n cmyk2hsv: cmyk2hsv,\n cmyk2hwb: cmyk2hwb,\n cmyk2keyword: cmyk2keyword,\n\n keyword2rgb: keyword2rgb,\n keyword2hsl: keyword2hsl,\n keyword2hsv: keyword2hsv,\n keyword2hwb: keyword2hwb,\n keyword2cmyk: keyword2cmyk,\n keyword2lab: keyword2lab,\n keyword2xyz: keyword2xyz,\n\n xyz2rgb: xyz2rgb,\n xyz2lab: xyz2lab,\n xyz2lch: xyz2lch,\n\n lab2xyz: lab2xyz,\n lab2rgb: lab2rgb,\n lab2lch: lab2lch,\n\n lch2lab: lch2lab,\n lch2xyz: lch2xyz,\n lch2rgb: lch2rgb\n}\n\n\nfunction rgb2hsl(rgb) {\n var r = rgb[0]/255,\n g = rgb[1]/255,\n b = rgb[2]/255,\n min = Math.min(r, g, b),\n max = Math.max(r, g, b),\n delta = max - min,\n h, s, l;\n\n if (max == min)\n h = 0;\n else if (r == max)\n h = (g - b) / delta;\n else if (g == max)\n h = 2 + (b - r) / delta;\n else if (b == max)\n h = 4 + (r - g)/ delta;\n\n h = Math.min(h * 60, 360);\n\n if (h < 0)\n h += 360;\n\n l = (min + max) / 2;\n\n if (max == min)\n s = 0;\n else if (l <= 0.5)\n s = delta / (max + min);\n else\n s = delta / (2 - max - min);\n\n return [h, s * 100, l * 100];\n}\n\nfunction rgb2hsv(rgb) {\n var r = rgb[0],\n g = rgb[1],\n b = rgb[2],\n min = Math.min(r, g, b),\n max = Math.max(r, g, b),\n delta = max - min,\n h, s, v;\n\n if (max == 0)\n s = 0;\n else\n s = (delta/max * 1000)/10;\n\n if (max == min)\n h = 0;\n else if (r == max)\n h = (g - b) / delta;\n else if (g == max)\n h = 2 + (b - r) / delta;\n else if (b == max)\n h = 4 + (r - g) / delta;\n\n h = Math.min(h * 60, 360);\n\n if (h < 0)\n h += 360;\n\n v = ((max / 255) * 1000) / 10;\n\n return [h, s, v];\n}\n\nfunction rgb2hwb(rgb) {\n var r = rgb[0],\n g = rgb[1],\n b = rgb[2],\n h = rgb2hsl(rgb)[0],\n w = 1/255 * Math.min(r, Math.min(g, b)),\n b = 1 - 1/255 * Math.max(r, Math.max(g, b));\n\n return [h, w * 100, b * 100];\n}\n\nfunction rgb2cmyk(rgb) {\n var r = rgb[0] / 255,\n g = rgb[1] / 255,\n b = rgb[2] / 255,\n c, m, y, k;\n\n k = Math.min(1 - r, 1 - g, 1 - b);\n c = (1 - r - k) / (1 - k) || 0;\n m = (1 - g - k) / (1 - k) || 0;\n y = (1 - b - k) / (1 - k) || 0;\n return [c * 100, m * 100, y * 100, k * 100];\n}\n\nfunction rgb2keyword(rgb) {\n return reverseKeywords[JSON.stringify(rgb)];\n}\n\nfunction rgb2xyz(rgb) {\n var r = rgb[0] / 255,\n g = rgb[1] / 255,\n b = rgb[2] / 255;\n\n // assume sRGB\n r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92);\n g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92);\n b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92);\n\n var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);\n var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);\n var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);\n\n return [x * 100, y *100, z * 100];\n}\n\nfunction rgb2lab(rgb) {\n var xyz = rgb2xyz(rgb),\n x = xyz[0],\n y = xyz[1],\n z = xyz[2],\n l, a, b;\n\n x /= 95.047;\n y /= 100;\n z /= 108.883;\n\n x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116);\n y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116);\n z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116);\n\n l = (116 * y) - 16;\n a = 500 * (x - y);\n b = 200 * (y - z);\n\n return [l, a, b];\n}\n\nfunction rgb2lch(args) {\n return lab2lch(rgb2lab(args));\n}\n\nfunction hsl2rgb(hsl) {\n var h = hsl[0] / 360,\n s = hsl[1] / 100,\n l = hsl[2] / 100,\n t1, t2, t3, rgb, val;\n\n if (s == 0) {\n val = l * 255;\n return [val, val, val];\n }\n\n if (l < 0.5)\n t2 = l * (1 + s);\n else\n t2 = l + s - l * s;\n t1 = 2 * l - t2;\n\n rgb = [0, 0, 0];\n for (var i = 0; i < 3; i++) {\n t3 = h + 1 / 3 * - (i - 1);\n t3 < 0 && t3++;\n t3 > 1 && t3--;\n\n if (6 * t3 < 1)\n val = t1 + (t2 - t1) * 6 * t3;\n else if (2 * t3 < 1)\n val = t2;\n else if (3 * t3 < 2)\n val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;\n else\n val = t1;\n\n rgb[i] = val * 255;\n }\n\n return rgb;\n}\n\nfunction hsl2hsv(hsl) {\n var h = hsl[0],\n s = hsl[1] / 100,\n l = hsl[2] / 100,\n sv, v;\n\n if(l === 0) {\n // no need to do calc on black\n // also avoids divide by 0 error\n return [0, 0, 0];\n }\n\n l *= 2;\n s *= (l <= 1) ? l : 2 - l;\n v = (l + s) / 2;\n sv = (2 * s) / (l + s);\n return [h, sv * 100, v * 100];\n}\n\nfunction hsl2hwb(args) {\n return rgb2hwb(hsl2rgb(args));\n}\n\nfunction hsl2cmyk(args) {\n return rgb2cmyk(hsl2rgb(args));\n}\n\nfunction hsl2keyword(args) {\n return rgb2keyword(hsl2rgb(args));\n}\n\n\nfunction hsv2rgb(hsv) {\n var h = hsv[0] / 60,\n s = hsv[1] / 100,\n v = hsv[2] / 100,\n hi = Math.floor(h) % 6;\n\n var f = h - Math.floor(h),\n p = 255 * v * (1 - s),\n q = 255 * v * (1 - (s * f)),\n t = 255 * v * (1 - (s * (1 - f))),\n v = 255 * v;\n\n switch(hi) {\n case 0:\n return [v, t, p];\n case 1:\n return [q, v, p];\n case 2:\n return [p, v, t];\n case 3:\n return [p, q, v];\n case 4:\n return [t, p, v];\n case 5:\n return [v, p, q];\n }\n}\n\nfunction hsv2hsl(hsv) {\n var h = hsv[0],\n s = hsv[1] / 100,\n v = hsv[2] / 100,\n sl, l;\n\n l = (2 - s) * v;\n sl = s * v;\n sl /= (l <= 1) ? l : 2 - l;\n sl = sl || 0;\n l /= 2;\n return [h, sl * 100, l * 100];\n}\n\nfunction hsv2hwb(args) {\n return rgb2hwb(hsv2rgb(args))\n}\n\nfunction hsv2cmyk(args) {\n return rgb2cmyk(hsv2rgb(args));\n}\n\nfunction hsv2keyword(args) {\n return rgb2keyword(hsv2rgb(args));\n}\n\n// http://dev.w3.org/csswg/css-color/#hwb-to-rgb\nfunction hwb2rgb(hwb) {\n var h = hwb[0] / 360,\n wh = hwb[1] / 100,\n bl = hwb[2] / 100,\n ratio = wh + bl,\n i, v, f, n;\n\n // wh + bl cant be > 1\n if (ratio > 1) {\n wh /= ratio;\n bl /= ratio;\n }\n\n i = Math.floor(6 * h);\n v = 1 - bl;\n f = 6 * h - i;\n if ((i & 0x01) != 0) {\n f = 1 - f;\n }\n n = wh + f * (v - wh); // linear interpolation\n\n switch (i) {\n default:\n case 6:\n case 0: r = v; g = n; b = wh; break;\n case 1: r = n; g = v; b = wh; break;\n case 2: r = wh; g = v; b = n; break;\n case 3: r = wh; g = n; b = v; break;\n case 4: r = n; g = wh; b = v; break;\n case 5: r = v; g = wh; b = n; break;\n }\n\n return [r * 255, g * 255, b * 255];\n}\n\nfunction hwb2hsl(args) {\n return rgb2hsl(hwb2rgb(args));\n}\n\nfunction hwb2hsv(args) {\n return rgb2hsv(hwb2rgb(args));\n}\n\nfunction hwb2cmyk(args) {\n return rgb2cmyk(hwb2rgb(args));\n}\n\nfunction hwb2keyword(args) {\n return rgb2keyword(hwb2rgb(args));\n}\n\nfunction cmyk2rgb(cmyk) {\n var c = cmyk[0] / 100,\n m = cmyk[1] / 100,\n y = cmyk[2] / 100,\n k = cmyk[3] / 100,\n r, g, b;\n\n r = 1 - Math.min(1, c * (1 - k) + k);\n g = 1 - Math.min(1, m * (1 - k) + k);\n b = 1 - Math.min(1, y * (1 - k) + k);\n return [r * 255, g * 255, b * 255];\n}\n\nfunction cmyk2hsl(args) {\n return rgb2hsl(cmyk2rgb(args));\n}\n\nfunction cmyk2hsv(args) {\n return rgb2hsv(cmyk2rgb(args));\n}\n\nfunction cmyk2hwb(args) {\n return rgb2hwb(cmyk2rgb(args));\n}\n\nfunction cmyk2keyword(args) {\n return rgb2keyword(cmyk2rgb(args));\n}\n\n\nfunction xyz2rgb(xyz) {\n var x = xyz[0] / 100,\n y = xyz[1] / 100,\n z = xyz[2] / 100,\n r, g, b;\n\n r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);\n g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);\n b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);\n\n // assume sRGB\n r = r > 0.0031308 ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055)\n : r = (r * 12.92);\n\n g = g > 0.0031308 ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055)\n : g = (g * 12.92);\n\n b = b > 0.0031308 ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055)\n : b = (b * 12.92);\n\n r = Math.min(Math.max(0, r), 1);\n g = Math.min(Math.max(0, g), 1);\n b = Math.min(Math.max(0, b), 1);\n\n return [r * 255, g * 255, b * 255];\n}\n\nfunction xyz2lab(xyz) {\n var x = xyz[0],\n y = xyz[1],\n z = xyz[2],\n l, a, b;\n\n x /= 95.047;\n y /= 100;\n z /= 108.883;\n\n x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116);\n y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116);\n z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116);\n\n l = (116 * y) - 16;\n a = 500 * (x - y);\n b = 200 * (y - z);\n\n return [l, a, b];\n}\n\nfunction xyz2lch(args) {\n return lab2lch(xyz2lab(args));\n}\n\nfunction lab2xyz(lab) {\n var l = lab[0],\n a = lab[1],\n b = lab[2],\n x, y, z, y2;\n\n if (l <= 8) {\n y = (l * 100) / 903.3;\n y2 = (7.787 * (y / 100)) + (16 / 116);\n } else {\n y = 100 * Math.pow((l + 16) / 116, 3);\n y2 = Math.pow(y / 100, 1/3);\n }\n\n x = x / 95.047 <= 0.008856 ? x = (95.047 * ((a / 500) + y2 - (16 / 116))) / 7.787 : 95.047 * Math.pow((a / 500) + y2, 3);\n\n z = z / 108.883 <= 0.008859 ? z = (108.883 * (y2 - (b / 200) - (16 / 116))) / 7.787 : 108.883 * Math.pow(y2 - (b / 200), 3);\n\n return [x, y, z];\n}\n\nfunction lab2lch(lab) {\n var l = lab[0],\n a = lab[1],\n b = lab[2],\n hr, h, c;\n\n hr = Math.atan2(b, a);\n h = hr * 360 / 2 / Math.PI;\n if (h < 0) {\n h += 360;\n }\n c = Math.sqrt(a * a + b * b);\n return [l, c, h];\n}\n\nfunction lab2rgb(args) {\n return xyz2rgb(lab2xyz(args));\n}\n\nfunction lch2lab(lch) {\n var l = lch[0],\n c = lch[1],\n h = lch[2],\n a, b, hr;\n\n hr = h / 360 * 2 * Math.PI;\n a = c * Math.cos(hr);\n b = c * Math.sin(hr);\n return [l, a, b];\n}\n\nfunction lch2xyz(args) {\n return lab2xyz(lch2lab(args));\n}\n\nfunction lch2rgb(args) {\n return lab2rgb(lch2lab(args));\n}\n\nfunction keyword2rgb(keyword) {\n return cssKeywords[keyword];\n}\n\nfunction keyword2hsl(args) {\n return rgb2hsl(keyword2rgb(args));\n}\n\nfunction keyword2hsv(args) {\n return rgb2hsv(keyword2rgb(args));\n}\n\nfunction keyword2hwb(args) {\n return rgb2hwb(keyword2rgb(args));\n}\n\nfunction keyword2cmyk(args) {\n return rgb2cmyk(keyword2rgb(args));\n}\n\nfunction keyword2lab(args) {\n return rgb2lab(keyword2rgb(args));\n}\n\nfunction keyword2xyz(args) {\n return rgb2xyz(keyword2rgb(args));\n}\n\nvar cssKeywords = {\n aliceblue: [240,248,255],\n antiquewhite: [250,235,215],\n aqua: [0,255,255],\n aquamarine: [127,255,212],\n azure: [240,255,255],\n beige: [245,245,220],\n bisque: [255,228,196],\n black: [0,0,0],\n blanchedalmond: [255,235,205],\n blue: [0,0,255],\n blueviolet: [138,43,226],\n brown: [165,42,42],\n burlywood: [222,184,135],\n cadetblue: [95,158,160],\n chartreuse: [127,255,0],\n chocolate: [210,105,30],\n coral: [255,127,80],\n cornflowerblue: [100,149,237],\n cornsilk: [255,248,220],\n crimson: [220,20,60],\n cyan: [0,255,255],\n darkblue: [0,0,139],\n darkcyan: [0,139,139],\n darkgoldenrod: [184,134,11],\n darkgray: [169,169,169],\n darkgreen: [0,100,0],\n darkgrey: [169,169,169],\n darkkhaki: [189,183,107],\n darkmagenta: [139,0,139],\n darkolivegreen: [85,107,47],\n darkorange: [255,140,0],\n darkorchid: [153,50,204],\n darkred: [139,0,0],\n darksalmon: [233,150,122],\n darkseagreen: [143,188,143],\n darkslateblue: [72,61,139],\n darkslategray: [47,79,79],\n darkslategrey: [47,79,79],\n darkturquoise: [0,206,209],\n darkviolet: [148,0,211],\n deeppink: [255,20,147],\n deepskyblue: [0,191,255],\n dimgray: [105,105,105],\n dimgrey: [105,105,105],\n dodgerblue: [30,144,255],\n firebrick: [178,34,34],\n floralwhite: [255,250,240],\n forestgreen: [34,139,34],\n fuchsia: [255,0,255],\n gainsboro: [220,220,220],\n ghostwhite: [248,248,255],\n gold: [255,215,0],\n goldenrod: [218,165,32],\n gray: [128,128,128],\n green: [0,128,0],\n greenyellow: [173,255,47],\n grey: [128,128,128],\n honeydew: [240,255,240],\n hotpink: [255,105,180],\n indianred: [205,92,92],\n indigo: [75,0,130],\n ivory: [255,255,240],\n khaki: [240,230,140],\n lavender: [230,230,250],\n lavenderblush: [255,240,245],\n lawngreen: [124,252,0],\n lemonchiffon: [255,250,205],\n lightblue: [173,216,230],\n lightcoral: [240,128,128],\n lightcyan: [224,255,255],\n lightgoldenrodyellow: [250,250,210],\n lightgray: [211,211,211],\n lightgreen: [144,238,144],\n lightgrey: [211,211,211],\n lightpink: [255,182,193],\n lightsalmon: [255,160,122],\n lightseagreen: [32,178,170],\n lightskyblue: [135,206,250],\n lightslategray: [119,136,153],\n lightslategrey: [119,136,153],\n lightsteelblue: [176,196,222],\n lightyellow: [255,255,224],\n lime: [0,255,0],\n limegreen: [50,205,50],\n linen: [250,240,230],\n magenta: [255,0,255],\n maroon: [128,0,0],\n mediumaquamarine: [102,205,170],\n mediumblue: [0,0,205],\n mediumorchid: [186,85,211],\n mediumpurple: [147,112,219],\n mediumseagreen: [60,179,113],\n mediumslateblue: [123,104,238],\n mediumspringgreen: [0,250,154],\n mediumturquoise: [72,209,204],\n mediumvioletred: [199,21,133],\n midnightblue: [25,25,112],\n mintcream: [245,255,250],\n mistyrose: [255,228,225],\n moccasin: [255,228,181],\n navajowhite: [255,222,173],\n navy: [0,0,128],\n oldlace: [253,245,230],\n olive: [128,128,0],\n olivedrab: [107,142,35],\n orange: [255,165,0],\n orangered: [255,69,0],\n orchid: [218,112,214],\n palegoldenrod: [238,232,170],\n palegreen: [152,251,152],\n paleturquoise: [175,238,238],\n palevioletred: [219,112,147],\n papayawhip: [255,239,213],\n peachpuff: [255,218,185],\n peru: [205,133,63],\n pink: [255,192,203],\n plum: [221,160,221],\n powderblue: [176,224,230],\n purple: [128,0,128],\n rebeccapurple: [102, 51, 153],\n red: [255,0,0],\n rosybrown: [188,143,143],\n royalblue: [65,105,225],\n saddlebrown: [139,69,19],\n salmon: [250,128,114],\n sandybrown: [244,164,96],\n seagreen: [46,139,87],\n seashell: [255,245,238],\n sienna: [160,82,45],\n silver: [192,192,192],\n skyblue: [135,206,235],\n slateblue: [106,90,205],\n slategray: [112,128,144],\n slategrey: [112,128,144],\n snow: [255,250,250],\n springgreen: [0,255,127],\n steelblue: [70,130,180],\n tan: [210,180,140],\n teal: [0,128,128],\n thistle: [216,191,216],\n tomato: [255,99,71],\n turquoise: [64,224,208],\n violet: [238,130,238],\n wheat: [245,222,179],\n white: [255,255,255],\n whitesmoke: [245,245,245],\n yellow: [255,255,0],\n yellowgreen: [154,205,50]\n};\n\nvar reverseKeywords = {};\nfor (var key in cssKeywords) {\n reverseKeywords[JSON.stringify(cssKeywords[key])] = key;\n}\n\n},{}],5:[function(require,module,exports){\nvar conversions = require(4);\n\nvar convert = function() {\n return new Converter();\n}\n\nfor (var func in conversions) {\n // export Raw versions\n convert[func + \"Raw\"] = (function(func) {\n // accept array or plain args\n return function(arg) {\n if (typeof arg == \"number\")\n arg = Array.prototype.slice.call(arguments);\n return conversions[func](arg);\n }\n })(func);\n\n var pair = /(\\w+)2(\\w+)/.exec(func),\n from = pair[1],\n to = pair[2];\n\n // export rgb2hsl and [\"rgb\"][\"hsl\"]\n convert[from] = convert[from] || {};\n\n convert[from][to] = convert[func] = (function(func) { \n return function(arg) {\n if (typeof arg == \"number\")\n arg = Array.prototype.slice.call(arguments);\n \n var val = conversions[func](arg);\n if (typeof val == \"string\" || val === undefined)\n return val; // keyword\n\n for (var i = 0; i < val.length; i++)\n val[i] = Math.round(val[i]);\n return val;\n }\n })(func);\n}\n\n\n/* Converter does lazy conversion and caching */\nvar Converter = function() {\n this.convs = {};\n};\n\n/* Either get the values for a space or\n set the values for a space, depending on args */\nConverter.prototype.routeSpace = function(space, args) {\n var values = args[0];\n if (values === undefined) {\n // color.rgb()\n return this.getValues(space);\n }\n // color.rgb(10, 10, 10)\n if (typeof values == \"number\") {\n values = Array.prototype.slice.call(args); \n }\n\n return this.setValues(space, values);\n};\n \n/* Set the values for a space, invalidating cache */\nConverter.prototype.setValues = function(space, values) {\n this.space = space;\n this.convs = {};\n this.convs[space] = values;\n return this;\n};\n\n/* Get the values for a space. If there's already\n a conversion for the space, fetch it, otherwise\n compute it */\nConverter.prototype.getValues = function(space) {\n var vals = this.convs[space];\n if (!vals) {\n var fspace = this.space,\n from = this.convs[fspace];\n vals = convert[fspace][space](from);\n\n this.convs[space] = vals;\n }\n return vals;\n};\n\n[\"rgb\", \"hsl\", \"hsv\", \"cmyk\", \"keyword\"].forEach(function(space) {\n Converter.prototype[space] = function(vals) {\n return this.routeSpace(space, arguments);\n }\n});\n\nmodule.exports = convert;\n},{\"4\":4}],6:[function(require,module,exports){\nmodule.exports = {\n\t\"aliceblue\": [240, 248, 255],\n\t\"antiquewhite\": [250, 235, 215],\n\t\"aqua\": [0, 255, 255],\n\t\"aquamarine\": [127, 255, 212],\n\t\"azure\": [240, 255, 255],\n\t\"beige\": [245, 245, 220],\n\t\"bisque\": [255, 228, 196],\n\t\"black\": [0, 0, 0],\n\t\"blanchedalmond\": [255, 235, 205],\n\t\"blue\": [0, 0, 255],\n\t\"blueviolet\": [138, 43, 226],\n\t\"brown\": [165, 42, 42],\n\t\"burlywood\": [222, 184, 135],\n\t\"cadetblue\": [95, 158, 160],\n\t\"chartreuse\": [127, 255, 0],\n\t\"chocolate\": [210, 105, 30],\n\t\"coral\": [255, 127, 80],\n\t\"cornflowerblue\": [100, 149, 237],\n\t\"cornsilk\": [255, 248, 220],\n\t\"crimson\": [220, 20, 60],\n\t\"cyan\": [0, 255, 255],\n\t\"darkblue\": [0, 0, 139],\n\t\"darkcyan\": [0, 139, 139],\n\t\"darkgoldenrod\": [184, 134, 11],\n\t\"darkgray\": [169, 169, 169],\n\t\"darkgreen\": [0, 100, 0],\n\t\"darkgrey\": [169, 169, 169],\n\t\"darkkhaki\": [189, 183, 107],\n\t\"darkmagenta\": [139, 0, 139],\n\t\"darkolivegreen\": [85, 107, 47],\n\t\"darkorange\": [255, 140, 0],\n\t\"darkorchid\": [153, 50, 204],\n\t\"darkred\": [139, 0, 0],\n\t\"darksalmon\": [233, 150, 122],\n\t\"darkseagreen\": [143, 188, 143],\n\t\"darkslateblue\": [72, 61, 139],\n\t\"darkslategray\": [47, 79, 79],\n\t\"darkslategrey\": [47, 79, 79],\n\t\"darkturquoise\": [0, 206, 209],\n\t\"darkviolet\": [148, 0, 211],\n\t\"deeppink\": [255, 20, 147],\n\t\"deepskyblue\": [0, 191, 255],\n\t\"dimgray\": [105, 105, 105],\n\t\"dimgrey\": [105, 105, 105],\n\t\"dodgerblue\": [30, 144, 255],\n\t\"firebrick\": [178, 34, 34],\n\t\"floralwhite\": [255, 250, 240],\n\t\"forestgreen\": [34, 139, 34],\n\t\"fuchsia\": [255, 0, 255],\n\t\"gainsboro\": [220, 220, 220],\n\t\"ghostwhite\": [248, 248, 255],\n\t\"gold\": [255, 215, 0],\n\t\"goldenrod\": [218, 165, 32],\n\t\"gray\": [128, 128, 128],\n\t\"green\": [0, 128, 0],\n\t\"greenyellow\": [173, 255, 47],\n\t\"grey\": [128, 128, 128],\n\t\"honeydew\": [240, 255, 240],\n\t\"hotpink\": [255, 105, 180],\n\t\"indianred\": [205, 92, 92],\n\t\"indigo\": [75, 0, 130],\n\t\"ivory\": [255, 255, 240],\n\t\"khaki\": [240, 230, 140],\n\t\"lavender\": [230, 230, 250],\n\t\"lavenderblush\": [255, 240, 245],\n\t\"lawngreen\": [124, 252, 0],\n\t\"lemonchiffon\": [255, 250, 205],\n\t\"lightblue\": [173, 216, 230],\n\t\"lightcoral\": [240, 128, 128],\n\t\"lightcyan\": [224, 255, 255],\n\t\"lightgoldenrodyellow\": [250, 250, 210],\n\t\"lightgray\": [211, 211, 211],\n\t\"lightgreen\": [144, 238, 144],\n\t\"lightgrey\": [211, 211, 211],\n\t\"lightpink\": [255, 182, 193],\n\t\"lightsalmon\": [255, 160, 122],\n\t\"lightseagreen\": [32, 178, 170],\n\t\"lightskyblue\": [135, 206, 250],\n\t\"lightslategray\": [119, 136, 153],\n\t\"lightslategrey\": [119, 136, 153],\n\t\"lightsteelblue\": [176, 196, 222],\n\t\"lightyellow\": [255, 255, 224],\n\t\"lime\": [0, 255, 0],\n\t\"limegreen\": [50, 205, 50],\n\t\"linen\": [250, 240, 230],\n\t\"magenta\": [255, 0, 255],\n\t\"maroon\": [128, 0, 0],\n\t\"mediumaquamarine\": [102, 205, 170],\n\t\"mediumblue\": [0, 0, 205],\n\t\"mediumorchid\": [186, 85, 211],\n\t\"mediumpurple\": [147, 112, 219],\n\t\"mediumseagreen\": [60, 179, 113],\n\t\"mediumslateblue\": [123, 104, 238],\n\t\"mediumspringgreen\": [0, 250, 154],\n\t\"mediumturquoise\": [72, 209, 204],\n\t\"mediumvioletred\": [199, 21, 133],\n\t\"midnightblue\": [25, 25, 112],\n\t\"mintcream\": [245, 255, 250],\n\t\"mistyrose\": [255, 228, 225],\n\t\"moccasin\": [255, 228, 181],\n\t\"navajowhite\": [255, 222, 173],\n\t\"navy\": [0, 0, 128],\n\t\"oldlace\": [253, 245, 230],\n\t\"olive\": [128, 128, 0],\n\t\"olivedrab\": [107, 142, 35],\n\t\"orange\": [255, 165, 0],\n\t\"orangered\": [255, 69, 0],\n\t\"orchid\": [218, 112, 214],\n\t\"palegoldenrod\": [238, 232, 170],\n\t\"palegreen\": [152, 251, 152],\n\t\"paleturquoise\": [175, 238, 238],\n\t\"palevioletred\": [219, 112, 147],\n\t\"papayawhip\": [255, 239, 213],\n\t\"peachpuff\": [255, 218, 185],\n\t\"peru\": [205, 133, 63],\n\t\"pink\": [255, 192, 203],\n\t\"plum\": [221, 160, 221],\n\t\"powderblue\": [176, 224, 230],\n\t\"purple\": [128, 0, 128],\n\t\"rebeccapurple\": [102, 51, 153],\n\t\"red\": [255, 0, 0],\n\t\"rosybrown\": [188, 143, 143],\n\t\"royalblue\": [65, 105, 225],\n\t\"saddlebrown\": [139, 69, 19],\n\t\"salmon\": [250, 128, 114],\n\t\"sandybrown\": [244, 164, 96],\n\t\"seagreen\": [46, 139, 87],\n\t\"seashell\": [255, 245, 238],\n\t\"sienna\": [160, 82, 45],\n\t\"silver\": [192, 192, 192],\n\t\"skyblue\": [135, 206, 235],\n\t\"slateblue\": [106, 90, 205],\n\t\"slategray\": [112, 128, 144],\n\t\"slategrey\": [112, 128, 144],\n\t\"snow\": [255, 250, 250],\n\t\"springgreen\": [0, 255, 127],\n\t\"steelblue\": [70, 130, 180],\n\t\"tan\": [210, 180, 140],\n\t\"teal\": [0, 128, 128],\n\t\"thistle\": [216, 191, 216],\n\t\"tomato\": [255, 99, 71],\n\t\"turquoise\": [64, 224, 208],\n\t\"violet\": [238, 130, 238],\n\t\"wheat\": [245, 222, 179],\n\t\"white\": [255, 255, 255],\n\t\"whitesmoke\": [245, 245, 245],\n\t\"yellow\": [255, 255, 0],\n\t\"yellowgreen\": [154, 205, 50]\n};\n},{}],7:[function(require,module,exports){\n/**\n * @namespace Chart\n */\nvar Chart = require(28)();\n\nrequire(26)(Chart);\nrequire(42)(Chart);\nrequire(22)(Chart);\nrequire(31)(Chart);\nrequire(25)(Chart);\nrequire(21)(Chart);\nrequire(23)(Chart);\nrequire(24)(Chart);\nrequire(29)(Chart);\nrequire(33)(Chart);\nrequire(34)(Chart);\nrequire(32)(Chart);\nrequire(35)(Chart);\nrequire(30)(Chart);\nrequire(27)(Chart);\nrequire(36)(Chart);\n\nrequire(37)(Chart);\nrequire(38)(Chart);\nrequire(39)(Chart);\nrequire(40)(Chart);\n\nrequire(45)(Chart);\nrequire(43)(Chart);\nrequire(44)(Chart);\nrequire(46)(Chart);\nrequire(47)(Chart);\nrequire(48)(Chart);\n\n// Controllers must be loaded after elements\n// See Chart.core.datasetController.dataElementType\nrequire(15)(Chart);\nrequire(16)(Chart);\nrequire(17)(Chart);\nrequire(18)(Chart);\nrequire(19)(Chart);\nrequire(20)(Chart);\n\nrequire(8)(Chart);\nrequire(9)(Chart);\nrequire(10)(Chart);\nrequire(11)(Chart);\nrequire(12)(Chart);\nrequire(13)(Chart);\nrequire(14)(Chart);\n\nwindow.Chart = module.exports = Chart;\n\n},{\"10\":10,\"11\":11,\"12\":12,\"13\":13,\"14\":14,\"15\":15,\"16\":16,\"17\":17,\"18\":18,\"19\":19,\"20\":20,\"21\":21,\"22\":22,\"23\":23,\"24\":24,\"25\":25,\"26\":26,\"27\":27,\"28\":28,\"29\":29,\"30\":30,\"31\":31,\"32\":32,\"33\":33,\"34\":34,\"35\":35,\"36\":36,\"37\":37,\"38\":38,\"39\":39,\"40\":40,\"42\":42,\"43\":43,\"44\":44,\"45\":45,\"46\":46,\"47\":47,\"48\":48,\"8\":8,\"9\":9}],8:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function(Chart) {\n\n\tChart.Bar = function(context, config) {\n\t\tconfig.type = 'bar';\n\n\t\treturn new Chart(context, config);\n\t};\n\n};\n\n},{}],9:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function(Chart) {\n\n\tChart.Bubble = function(context, config) {\n\t\tconfig.type = 'bubble';\n\t\treturn new Chart(context, config);\n\t};\n\n};\n\n},{}],10:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function(Chart) {\n\n\tChart.Doughnut = function(context, config) {\n\t\tconfig.type = 'doughnut';\n\n\t\treturn new Chart(context, config);\n\t};\n\n};\n\n},{}],11:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function(Chart) {\n\n\tChart.Line = function(context, config) {\n\t\tconfig.type = 'line';\n\n\t\treturn new Chart(context, config);\n\t};\n\n};\n\n},{}],12:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function(Chart) {\n\n\tChart.PolarArea = function(context, config) {\n\t\tconfig.type = 'polarArea';\n\n\t\treturn new Chart(context, config);\n\t};\n\n};\n\n},{}],13:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function(Chart) {\n\n\tChart.Radar = function(context, config) {\n\t\tconfig.type = 'radar';\n\n\t\treturn new Chart(context, config);\n\t};\n\n};\n\n},{}],14:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function(Chart) {\n\n\tvar defaultConfig = {\n\t\thover: {\n\t\t\tmode: 'single'\n\t\t},\n\n\t\tscales: {\n\t\t\txAxes: [{\n\t\t\t\ttype: 'linear', // scatter should not use a category axis\n\t\t\t\tposition: 'bottom',\n\t\t\t\tid: 'x-axis-1' // need an ID so datasets can reference the scale\n\t\t\t}],\n\t\t\tyAxes: [{\n\t\t\t\ttype: 'linear',\n\t\t\t\tposition: 'left',\n\t\t\t\tid: 'y-axis-1'\n\t\t\t}]\n\t\t},\n\n\t\ttooltips: {\n\t\t\tcallbacks: {\n\t\t\t\ttitle: function() {\n\t\t\t\t\t// Title doesn't make sense for scatter since we format the data as a point\n\t\t\t\t\treturn '';\n\t\t\t\t},\n\t\t\t\tlabel: function(tooltipItem) {\n\t\t\t\t\treturn '(' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ')';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\t// Register the default config for this type\n\tChart.defaults.scatter = defaultConfig;\n\n\t// Scatter charts use line controllers\n\tChart.controllers.scatter = Chart.controllers.line;\n\n\tChart.Scatter = function(context, config) {\n\t\tconfig.type = 'scatter';\n\t\treturn new Chart(context, config);\n\t};\n\n};\n\n},{}],15:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function(Chart) {\n\n\tvar helpers = Chart.helpers;\n\n\tChart.defaults.bar = {\n\t\thover: {\n\t\t\tmode: 'label'\n\t\t},\n\n\t\tscales: {\n\t\t\txAxes: [{\n\t\t\t\ttype: 'category',\n\n\t\t\t\t// Specific to Bar Controller\n\t\t\t\tcategoryPercentage: 0.8,\n\t\t\t\tbarPercentage: 0.9,\n\n\t\t\t\t// grid line settings\n\t\t\t\tgridLines: {\n\t\t\t\t\toffsetGridLines: true\n\t\t\t\t}\n\t\t\t}],\n\t\t\tyAxes: [{\n\t\t\t\ttype: 'linear'\n\t\t\t}]\n\t\t}\n\t};\n\n\tChart.controllers.bar = Chart.DatasetController.extend({\n\n\t\tdataElementType: Chart.elements.Rectangle,\n\n\t\tinitialize: function(chart, datasetIndex) {\n\t\t\tChart.DatasetController.prototype.initialize.call(this, chart, datasetIndex);\n\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar dataset = me.getDataset();\n\n\t\t\tmeta.stack = dataset.stack;\n\t\t\t// Use this to indicate that this is a bar dataset.\n\t\t\tmeta.bar = true;\n\t\t},\n\n\t\t// Correctly calculate the bar width accounting for stacks and the fact that not all bars are visible\n\t\tgetStackCount: function() {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar yScale = me.getScaleForId(meta.yAxisID);\n\n\t\t\tvar stacks = [];\n\t\t\thelpers.each(me.chart.data.datasets, function(dataset, datasetIndex) {\n\t\t\t\tvar dsMeta = me.chart.getDatasetMeta(datasetIndex);\n\t\t\t\tif (dsMeta.bar && me.chart.isDatasetVisible(datasetIndex) &&\n\t\t\t\t\t(yScale.options.stacked === false ||\n\t\t\t\t\t(yScale.options.stacked === true && stacks.indexOf(dsMeta.stack) === -1) ||\n\t\t\t\t\t(yScale.options.stacked === undefined && (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) {\n\t\t\t\t\tstacks.push(dsMeta.stack);\n\t\t\t\t}\n\t\t\t}, me);\n\n\t\t\treturn stacks.length;\n\t\t},\n\n\t\tupdate: function(reset) {\n\t\t\tvar me = this;\n\t\t\thelpers.each(me.getMeta().data, function(rectangle, index) {\n\t\t\t\tme.updateElement(rectangle, index, reset);\n\t\t\t}, me);\n\t\t},\n\n\t\tupdateElement: function(rectangle, index, reset) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar xScale = me.getScaleForId(meta.xAxisID);\n\t\t\tvar yScale = me.getScaleForId(meta.yAxisID);\n\t\t\tvar scaleBase = yScale.getBasePixel();\n\t\t\tvar rectangleElementOptions = me.chart.options.elements.rectangle;\n\t\t\tvar custom = rectangle.custom || {};\n\t\t\tvar dataset = me.getDataset();\n\n\t\t\trectangle._xScale = xScale;\n\t\t\trectangle._yScale = yScale;\n\t\t\trectangle._datasetIndex = me.index;\n\t\t\trectangle._index = index;\n\n\t\t\tvar ruler = me.getRuler(index); // The index argument for compatible\n\t\t\trectangle._model = {\n\t\t\t\tx: me.calculateBarX(index, me.index, ruler),\n\t\t\t\ty: reset ? scaleBase : me.calculateBarY(index, me.index),\n\n\t\t\t\t// Tooltip\n\t\t\t\tlabel: me.chart.data.labels[index],\n\t\t\t\tdatasetLabel: dataset.label,\n\n\t\t\t\t// Appearance\n\t\t\t\thorizontal: false,\n\t\t\t\tbase: reset ? scaleBase : me.calculateBarBase(me.index, index),\n\t\t\t\twidth: me.calculateBarWidth(ruler),\n\t\t\t\tbackgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),\n\t\t\t\tborderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,\n\t\t\t\tborderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),\n\t\t\t\tborderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)\n\t\t\t};\n\n\t\t\trectangle.pivot();\n\t\t},\n\n\t\tcalculateBarBase: function(datasetIndex, index) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar yScale = me.getScaleForId(meta.yAxisID);\n\t\t\tvar base = yScale.getBaseValue();\n\t\t\tvar original = base;\n\n\t\t\tif ((yScale.options.stacked === true) ||\n\t\t\t\t(yScale.options.stacked === undefined && meta.stack !== undefined)) {\n\t\t\t\tvar chart = me.chart;\n\t\t\t\tvar datasets = chart.data.datasets;\n\t\t\t\tvar value = Number(datasets[datasetIndex].data[index]);\n\n\t\t\t\tfor (var i = 0; i < datasetIndex; i++) {\n\t\t\t\t\tvar currentDs = datasets[i];\n\t\t\t\t\tvar currentDsMeta = chart.getDatasetMeta(i);\n\t\t\t\t\tif (currentDsMeta.bar && currentDsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i) &&\n\t\t\t\t\t\tmeta.stack === currentDsMeta.stack) {\n\t\t\t\t\t\tvar currentVal = Number(currentDs.data[index]);\n\t\t\t\t\t\tbase += value < 0 ? Math.min(currentVal, original) : Math.max(currentVal, original);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn yScale.getPixelForValue(base);\n\t\t\t}\n\n\t\t\treturn yScale.getBasePixel();\n\t\t},\n\n\t\tgetRuler: function() {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar xScale = me.getScaleForId(meta.xAxisID);\n\t\t\tvar stackCount = me.getStackCount();\n\n\t\t\tvar tickWidth = xScale.width / xScale.ticks.length;\n\t\t\tvar categoryWidth = tickWidth * xScale.options.categoryPercentage;\n\t\t\tvar categorySpacing = (tickWidth - (tickWidth * xScale.options.categoryPercentage)) / 2;\n\t\t\tvar fullBarWidth = categoryWidth / stackCount;\n\n\t\t\tvar barWidth = fullBarWidth * xScale.options.barPercentage;\n\t\t\tvar barSpacing = fullBarWidth - (fullBarWidth * xScale.options.barPercentage);\n\n\t\t\treturn {\n\t\t\t\tstackCount: stackCount,\n\t\t\t\ttickWidth: tickWidth,\n\t\t\t\tcategoryWidth: categoryWidth,\n\t\t\t\tcategorySpacing: categorySpacing,\n\t\t\t\tfullBarWidth: fullBarWidth,\n\t\t\t\tbarWidth: barWidth,\n\t\t\t\tbarSpacing: barSpacing\n\t\t\t};\n\t\t},\n\n\t\tcalculateBarWidth: function(ruler) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar xScale = me.getScaleForId(meta.xAxisID);\n\t\t\tif (xScale.options.barThickness) {\n\t\t\t\treturn xScale.options.barThickness;\n\t\t\t}\n\t\t\treturn ruler.barWidth;\n\t\t},\n\n\t\t// Get stack index from the given dataset index accounting for stacks and the fact that not all bars are visible\n\t\tgetStackIndex: function(datasetIndex) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.chart.getDatasetMeta(datasetIndex);\n\t\t\tvar yScale = me.getScaleForId(meta.yAxisID);\n\t\t\tvar dsMeta, j;\n\t\t\tvar stacks = [meta.stack];\n\n\t\t\tfor (j = 0; j < datasetIndex; ++j) {\n\t\t\t\tdsMeta = this.chart.getDatasetMeta(j);\n\t\t\t\tif (dsMeta.bar && this.chart.isDatasetVisible(j) &&\n\t\t\t\t\t(yScale.options.stacked === false ||\n\t\t\t\t\t(yScale.options.stacked === true && stacks.indexOf(dsMeta.stack) === -1) ||\n\t\t\t\t\t(yScale.options.stacked === undefined && (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) {\n\t\t\t\t\tstacks.push(dsMeta.stack);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn stacks.length - 1;\n\t\t},\n\n\t\tcalculateBarX: function(index, datasetIndex, ruler) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar xScale = me.getScaleForId(meta.xAxisID);\n\t\t\tvar stackIndex = me.getStackIndex(datasetIndex);\n\t\t\tvar leftTick = xScale.getPixelForValue(null, index, datasetIndex, me.chart.isCombo);\n\t\t\tleftTick -= me.chart.isCombo ? (ruler.tickWidth / 2) : 0;\n\n\t\t\treturn leftTick +\n\t\t\t\t(ruler.barWidth / 2) +\n\t\t\t\truler.categorySpacing +\n\t\t\t\t(ruler.barWidth * stackIndex) +\n\t\t\t\t(ruler.barSpacing / 2) +\n\t\t\t\t(ruler.barSpacing * stackIndex);\n\t\t},\n\n\t\tcalculateBarY: function(index, datasetIndex) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar yScale = me.getScaleForId(meta.yAxisID);\n\t\t\tvar value = Number(me.getDataset().data[index]);\n\n\t\t\tif (yScale.options.stacked ||\n\t\t\t\t(yScale.options.stacked === undefined && meta.stack !== undefined)) {\n\t\t\t\tvar base = yScale.getBaseValue();\n\t\t\t\tvar sumPos = base,\n\t\t\t\t\tsumNeg = base;\n\n\t\t\t\tfor (var i = 0; i < datasetIndex; i++) {\n\t\t\t\t\tvar ds = me.chart.data.datasets[i];\n\t\t\t\t\tvar dsMeta = me.chart.getDatasetMeta(i);\n\t\t\t\t\tif (dsMeta.bar && dsMeta.yAxisID === yScale.id && me.chart.isDatasetVisible(i) &&\n\t\t\t\t\t\tmeta.stack === dsMeta.stack) {\n\t\t\t\t\t\tvar stackedVal = Number(ds.data[index]);\n\t\t\t\t\t\tif (stackedVal < 0) {\n\t\t\t\t\t\t\tsumNeg += stackedVal || 0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsumPos += stackedVal || 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (value < 0) {\n\t\t\t\t\treturn yScale.getPixelForValue(sumNeg + value);\n\t\t\t\t}\n\t\t\t\treturn yScale.getPixelForValue(sumPos + value);\n\t\t\t}\n\n\t\t\treturn yScale.getPixelForValue(value);\n\t\t},\n\n\t\tdraw: function(ease) {\n\t\t\tvar me = this;\n\t\t\tvar easingDecimal = ease || 1;\n\t\t\tvar metaData = me.getMeta().data;\n\t\t\tvar dataset = me.getDataset();\n\t\t\tvar i, len;\n\n\t\t\tChart.canvasHelpers.clipArea(me.chart.chart.ctx, me.chart.chartArea);\n\t\t\tfor (i = 0, len = metaData.length; i < len; ++i) {\n\t\t\t\tvar d = dataset.data[i];\n\t\t\t\tif (d !== null && d !== undefined && !isNaN(d)) {\n\t\t\t\t\tmetaData[i].transition(easingDecimal).draw();\n\t\t\t\t}\n\t\t\t}\n\t\t\tChart.canvasHelpers.unclipArea(me.chart.chart.ctx);\n\t\t},\n\n\t\tsetHoverStyle: function(rectangle) {\n\t\t\tvar dataset = this.chart.data.datasets[rectangle._datasetIndex];\n\t\t\tvar index = rectangle._index;\n\n\t\t\tvar custom = rectangle.custom || {};\n\t\t\tvar model = rectangle._model;\n\t\t\tmodel.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));\n\t\t\tmodel.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor));\n\t\t\tmodel.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);\n\t\t},\n\n\t\tremoveHoverStyle: function(rectangle) {\n\t\t\tvar dataset = this.chart.data.datasets[rectangle._datasetIndex];\n\t\t\tvar index = rectangle._index;\n\t\t\tvar custom = rectangle.custom || {};\n\t\t\tvar model = rectangle._model;\n\t\t\tvar rectangleElementOptions = this.chart.options.elements.rectangle;\n\n\t\t\tmodel.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor);\n\t\t\tmodel.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor);\n\t\t\tmodel.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth);\n\t\t}\n\n\t});\n\n\n\t// including horizontalBar in the bar file, instead of a file of its own\n\t// it extends bar (like pie extends doughnut)\n\tChart.defaults.horizontalBar = {\n\t\thover: {\n\t\t\tmode: 'label'\n\t\t},\n\n\t\tscales: {\n\t\t\txAxes: [{\n\t\t\t\ttype: 'linear',\n\t\t\t\tposition: 'bottom'\n\t\t\t}],\n\t\t\tyAxes: [{\n\t\t\t\tposition: 'left',\n\t\t\t\ttype: 'category',\n\n\t\t\t\t// Specific to Horizontal Bar Controller\n\t\t\t\tcategoryPercentage: 0.8,\n\t\t\t\tbarPercentage: 0.9,\n\n\t\t\t\t// grid line settings\n\t\t\t\tgridLines: {\n\t\t\t\t\toffsetGridLines: true\n\t\t\t\t}\n\t\t\t}]\n\t\t},\n\t\telements: {\n\t\t\trectangle: {\n\t\t\t\tborderSkipped: 'left'\n\t\t\t}\n\t\t},\n\t\ttooltips: {\n\t\t\tcallbacks: {\n\t\t\t\ttitle: function(tooltipItems, data) {\n\t\t\t\t\t// Pick first xLabel for now\n\t\t\t\t\tvar title = '';\n\n\t\t\t\t\tif (tooltipItems.length > 0) {\n\t\t\t\t\t\tif (tooltipItems[0].yLabel) {\n\t\t\t\t\t\t\ttitle = tooltipItems[0].yLabel;\n\t\t\t\t\t\t} else if (data.labels.length > 0 && tooltipItems[0].index < data.labels.length) {\n\t\t\t\t\t\t\ttitle = data.labels[tooltipItems[0].index];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn title;\n\t\t\t\t},\n\t\t\t\tlabel: function(tooltipItem, data) {\n\t\t\t\t\tvar datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';\n\t\t\t\t\treturn datasetLabel + ': ' + tooltipItem.xLabel;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tChart.controllers.horizontalBar = Chart.controllers.bar.extend({\n\n\t\t// Correctly calculate the bar width accounting for stacks and the fact that not all bars are visible\n\t\tgetStackCount: function() {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar xScale = me.getScaleForId(meta.xAxisID);\n\n\t\t\tvar stacks = [];\n\t\t\thelpers.each(me.chart.data.datasets, function(dataset, datasetIndex) {\n\t\t\t\tvar dsMeta = me.chart.getDatasetMeta(datasetIndex);\n\t\t\t\tif (dsMeta.bar && me.chart.isDatasetVisible(datasetIndex) &&\n\t\t\t\t\t(xScale.options.stacked === false ||\n\t\t\t\t\t(xScale.options.stacked === true && stacks.indexOf(dsMeta.stack) === -1) ||\n\t\t\t\t\t(xScale.options.stacked === undefined && (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) {\n\t\t\t\t\tstacks.push(dsMeta.stack);\n\t\t\t\t}\n\t\t\t}, me);\n\n\t\t\treturn stacks.length;\n\t\t},\n\n\t\tupdateElement: function(rectangle, index, reset) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar xScale = me.getScaleForId(meta.xAxisID);\n\t\t\tvar yScale = me.getScaleForId(meta.yAxisID);\n\t\t\tvar scaleBase = xScale.getBasePixel();\n\t\t\tvar custom = rectangle.custom || {};\n\t\t\tvar dataset = me.getDataset();\n\t\t\tvar rectangleElementOptions = me.chart.options.elements.rectangle;\n\n\t\t\trectangle._xScale = xScale;\n\t\t\trectangle._yScale = yScale;\n\t\t\trectangle._datasetIndex = me.index;\n\t\t\trectangle._index = index;\n\n\t\t\tvar ruler = me.getRuler(index); // The index argument for compatible\n\t\t\trectangle._model = {\n\t\t\t\tx: reset ? scaleBase : me.calculateBarX(index, me.index),\n\t\t\t\ty: me.calculateBarY(index, me.index, ruler),\n\n\t\t\t\t// Tooltip\n\t\t\t\tlabel: me.chart.data.labels[index],\n\t\t\t\tdatasetLabel: dataset.label,\n\n\t\t\t\t// Appearance\n\t\t\t\thorizontal: true,\n\t\t\t\tbase: reset ? scaleBase : me.calculateBarBase(me.index, index),\n\t\t\t\theight: me.calculateBarHeight(ruler),\n\t\t\t\tbackgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),\n\t\t\t\tborderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,\n\t\t\t\tborderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),\n\t\t\t\tborderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)\n\t\t\t};\n\n\t\t\trectangle.pivot();\n\t\t},\n\n\t\tcalculateBarBase: function(datasetIndex, index) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar xScale = me.getScaleForId(meta.xAxisID);\n\t\t\tvar base = xScale.getBaseValue();\n\t\t\tvar originalBase = base;\n\n\t\t\tif (xScale.options.stacked ||\n\t\t\t\t(xScale.options.stacked === undefined && meta.stack !== undefined)) {\n\t\t\t\tvar chart = me.chart;\n\t\t\t\tvar datasets = chart.data.datasets;\n\t\t\t\tvar value = Number(datasets[datasetIndex].data[index]);\n\n\t\t\t\tfor (var i = 0; i < datasetIndex; i++) {\n\t\t\t\t\tvar currentDs = datasets[i];\n\t\t\t\t\tvar currentDsMeta = chart.getDatasetMeta(i);\n\t\t\t\t\tif (currentDsMeta.bar && currentDsMeta.xAxisID === xScale.id && chart.isDatasetVisible(i) &&\n\t\t\t\t\t\tmeta.stack === currentDsMeta.stack) {\n\t\t\t\t\t\tvar currentVal = Number(currentDs.data[index]);\n\t\t\t\t\t\tbase += value < 0 ? Math.min(currentVal, originalBase) : Math.max(currentVal, originalBase);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn xScale.getPixelForValue(base);\n\t\t\t}\n\n\t\t\treturn xScale.getBasePixel();\n\t\t},\n\n\t\tgetRuler: function() {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar yScale = me.getScaleForId(meta.yAxisID);\n\t\t\tvar stackCount = me.getStackCount();\n\n\t\t\tvar tickHeight = yScale.height / yScale.ticks.length;\n\t\t\tvar categoryHeight = tickHeight * yScale.options.categoryPercentage;\n\t\t\tvar categorySpacing = (tickHeight - (tickHeight * yScale.options.categoryPercentage)) / 2;\n\t\t\tvar fullBarHeight = categoryHeight / stackCount;\n\n\t\t\tvar barHeight = fullBarHeight * yScale.options.barPercentage;\n\t\t\tvar barSpacing = fullBarHeight - (fullBarHeight * yScale.options.barPercentage);\n\n\t\t\treturn {\n\t\t\t\tstackCount: stackCount,\n\t\t\t\ttickHeight: tickHeight,\n\t\t\t\tcategoryHeight: categoryHeight,\n\t\t\t\tcategorySpacing: categorySpacing,\n\t\t\t\tfullBarHeight: fullBarHeight,\n\t\t\t\tbarHeight: barHeight,\n\t\t\t\tbarSpacing: barSpacing\n\t\t\t};\n\t\t},\n\n\t\tcalculateBarHeight: function(ruler) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar yScale = me.getScaleForId(meta.yAxisID);\n\t\t\tif (yScale.options.barThickness) {\n\t\t\t\treturn yScale.options.barThickness;\n\t\t\t}\n\t\t\treturn ruler.barHeight;\n\t\t},\n\n\t\t// Get stack index from the given dataset index accounting for stacks and the fact that not all bars are visible\n\t\tgetStackIndex: function(datasetIndex) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.chart.getDatasetMeta(datasetIndex);\n\t\t\tvar xScale = me.getScaleForId(meta.xAxisID);\n\t\t\tvar dsMeta, j;\n\t\t\tvar stacks = [meta.stack];\n\n\t\t\tfor (j = 0; j < datasetIndex; ++j) {\n\t\t\t\tdsMeta = this.chart.getDatasetMeta(j);\n\t\t\t\tif (dsMeta.bar && this.chart.isDatasetVisible(j) &&\n\t\t\t\t\t(xScale.options.stacked === false ||\n\t\t\t\t\t(xScale.options.stacked === true && stacks.indexOf(dsMeta.stack) === -1) ||\n\t\t\t\t\t(xScale.options.stacked === undefined && (dsMeta.stack === undefined || stacks.indexOf(dsMeta.stack) === -1)))) {\n\t\t\t\t\tstacks.push(dsMeta.stack);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn stacks.length - 1;\n\t\t},\n\n\t\tcalculateBarX: function(index, datasetIndex) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar xScale = me.getScaleForId(meta.xAxisID);\n\t\t\tvar value = Number(me.getDataset().data[index]);\n\n\t\t\tif (xScale.options.stacked ||\n\t\t\t\t(xScale.options.stacked === undefined && meta.stack !== undefined)) {\n\t\t\t\tvar base = xScale.getBaseValue();\n\t\t\t\tvar sumPos = base,\n\t\t\t\t\tsumNeg = base;\n\n\t\t\t\tfor (var i = 0; i < datasetIndex; i++) {\n\t\t\t\t\tvar ds = me.chart.data.datasets[i];\n\t\t\t\t\tvar dsMeta = me.chart.getDatasetMeta(i);\n\t\t\t\t\tif (dsMeta.bar && dsMeta.xAxisID === xScale.id && me.chart.isDatasetVisible(i) &&\n\t\t\t\t\t\tmeta.stack === dsMeta.stack) {\n\t\t\t\t\t\tvar stackedVal = Number(ds.data[index]);\n\t\t\t\t\t\tif (stackedVal < 0) {\n\t\t\t\t\t\t\tsumNeg += stackedVal || 0;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsumPos += stackedVal || 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (value < 0) {\n\t\t\t\t\treturn xScale.getPixelForValue(sumNeg + value);\n\t\t\t\t}\n\t\t\t\treturn xScale.getPixelForValue(sumPos + value);\n\t\t\t}\n\n\t\t\treturn xScale.getPixelForValue(value);\n\t\t},\n\n\t\tcalculateBarY: function(index, datasetIndex, ruler) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar yScale = me.getScaleForId(meta.yAxisID);\n\t\t\tvar stackIndex = me.getStackIndex(datasetIndex);\n\t\t\tvar topTick = yScale.getPixelForValue(null, index, datasetIndex, me.chart.isCombo);\n\t\t\ttopTick -= me.chart.isCombo ? (ruler.tickHeight / 2) : 0;\n\n\t\t\treturn topTick +\n\t\t\t\t(ruler.barHeight / 2) +\n\t\t\t\truler.categorySpacing +\n\t\t\t\t(ruler.barHeight * stackIndex) +\n\t\t\t\t(ruler.barSpacing / 2) +\n\t\t\t\t(ruler.barSpacing * stackIndex);\n\t\t}\n\t});\n};\n\n},{}],16:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function(Chart) {\n\n\tvar helpers = Chart.helpers;\n\n\tChart.defaults.bubble = {\n\t\thover: {\n\t\t\tmode: 'single'\n\t\t},\n\n\t\tscales: {\n\t\t\txAxes: [{\n\t\t\t\ttype: 'linear', // bubble should probably use a linear scale by default\n\t\t\t\tposition: 'bottom',\n\t\t\t\tid: 'x-axis-0' // need an ID so datasets can reference the scale\n\t\t\t}],\n\t\t\tyAxes: [{\n\t\t\t\ttype: 'linear',\n\t\t\t\tposition: 'left',\n\t\t\t\tid: 'y-axis-0'\n\t\t\t}]\n\t\t},\n\n\t\ttooltips: {\n\t\t\tcallbacks: {\n\t\t\t\ttitle: function() {\n\t\t\t\t\t// Title doesn't make sense for scatter since we format the data as a point\n\t\t\t\t\treturn '';\n\t\t\t\t},\n\t\t\t\tlabel: function(tooltipItem, data) {\n\t\t\t\t\tvar datasetLabel = data.datasets[tooltipItem.datasetIndex].label || '';\n\t\t\t\t\tvar dataPoint = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];\n\t\t\t\t\treturn datasetLabel + ': (' + tooltipItem.xLabel + ', ' + tooltipItem.yLabel + ', ' + dataPoint.r + ')';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tChart.controllers.bubble = Chart.DatasetController.extend({\n\n\t\tdataElementType: Chart.elements.Point,\n\n\t\tupdate: function(reset) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar points = meta.data;\n\n\t\t\t// Update Points\n\t\t\thelpers.each(points, function(point, index) {\n\t\t\t\tme.updateElement(point, index, reset);\n\t\t\t});\n\t\t},\n\n\t\tupdateElement: function(point, index, reset) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar xScale = me.getScaleForId(meta.xAxisID);\n\t\t\tvar yScale = me.getScaleForId(meta.yAxisID);\n\n\t\t\tvar custom = point.custom || {};\n\t\t\tvar dataset = me.getDataset();\n\t\t\tvar data = dataset.data[index];\n\t\t\tvar pointElementOptions = me.chart.options.elements.point;\n\t\t\tvar dsIndex = me.index;\n\n\t\t\thelpers.extend(point, {\n\t\t\t\t// Utility\n\t\t\t\t_xScale: xScale,\n\t\t\t\t_yScale: yScale,\n\t\t\t\t_datasetIndex: dsIndex,\n\t\t\t\t_index: index,\n\n\t\t\t\t// Desired view properties\n\t\t\t\t_model: {\n\t\t\t\t\tx: reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(typeof data === 'object' ? data : NaN, index, dsIndex, me.chart.isCombo),\n\t\t\t\t\ty: reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex),\n\t\t\t\t\t// Appearance\n\t\t\t\t\tradius: reset ? 0 : custom.radius ? custom.radius : me.getRadius(data),\n\n\t\t\t\t\t// Tooltip\n\t\t\t\t\thitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius)\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Trick to reset the styles of the point\n\t\t\tChart.DatasetController.prototype.removeHoverStyle.call(me, point, pointElementOptions);\n\n\t\t\tvar model = point._model;\n\t\t\tmodel.skip = custom.skip ? custom.skip : (isNaN(model.x) || isNaN(model.y));\n\n\t\t\tpoint.pivot();\n\t\t},\n\n\t\tgetRadius: function(value) {\n\t\t\treturn value.r || this.chart.options.elements.point.radius;\n\t\t},\n\n\t\tsetHoverStyle: function(point) {\n\t\t\tvar me = this;\n\t\t\tChart.DatasetController.prototype.setHoverStyle.call(me, point);\n\n\t\t\t// Radius\n\t\t\tvar dataset = me.chart.data.datasets[point._datasetIndex];\n\t\t\tvar index = point._index;\n\t\t\tvar custom = point.custom || {};\n\t\t\tvar model = point._model;\n\t\t\tmodel.radius = custom.hoverRadius ? custom.hoverRadius : (helpers.getValueAtIndexOrDefault(dataset.hoverRadius, index, me.chart.options.elements.point.hoverRadius)) + me.getRadius(dataset.data[index]);\n\t\t},\n\n\t\tremoveHoverStyle: function(point) {\n\t\t\tvar me = this;\n\t\t\tChart.DatasetController.prototype.removeHoverStyle.call(me, point, me.chart.options.elements.point);\n\n\t\t\tvar dataVal = me.chart.data.datasets[point._datasetIndex].data[point._index];\n\t\t\tvar custom = point.custom || {};\n\t\t\tvar model = point._model;\n\n\t\t\tmodel.radius = custom.radius ? custom.radius : me.getRadius(dataVal);\n\t\t}\n\t});\n};\n\n},{}],17:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function(Chart) {\n\n\tvar helpers = Chart.helpers,\n\t\tdefaults = Chart.defaults;\n\n\tdefaults.doughnut = {\n\t\tanimation: {\n\t\t\t// Boolean - Whether we animate the rotation of the Doughnut\n\t\t\tanimateRotate: true,\n\t\t\t// Boolean - Whether we animate scaling the Doughnut from the centre\n\t\t\tanimateScale: false\n\t\t},\n\t\taspectRatio: 1,\n\t\thover: {\n\t\t\tmode: 'single'\n\t\t},\n\t\tlegendCallback: function(chart) {\n\t\t\tvar text = [];\n\t\t\ttext.push('
    ');\n\n\t\t\tvar data = chart.data;\n\t\t\tvar datasets = data.datasets;\n\t\t\tvar labels = data.labels;\n\n\t\t\tif (datasets.length) {\n\t\t\t\tfor (var i = 0; i < datasets[0].data.length; ++i) {\n\t\t\t\t\ttext.push('
  • ');\n\t\t\t\t\tif (labels[i]) {\n\t\t\t\t\t\ttext.push(labels[i]);\n\t\t\t\t\t}\n\t\t\t\t\ttext.push('
  • ');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttext.push('
');\n\t\t\treturn text.join('');\n\t\t},\n\t\tlegend: {\n\t\t\tlabels: {\n\t\t\t\tgenerateLabels: function(chart) {\n\t\t\t\t\tvar data = chart.data;\n\t\t\t\t\tif (data.labels.length && data.datasets.length) {\n\t\t\t\t\t\treturn data.labels.map(function(label, i) {\n\t\t\t\t\t\t\tvar meta = chart.getDatasetMeta(0);\n\t\t\t\t\t\t\tvar ds = data.datasets[0];\n\t\t\t\t\t\t\tvar arc = meta.data[i];\n\t\t\t\t\t\t\tvar custom = arc && arc.custom || {};\n\t\t\t\t\t\t\tvar getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\n\t\t\t\t\t\t\tvar arcOpts = chart.options.elements.arc;\n\t\t\t\t\t\t\tvar fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);\n\t\t\t\t\t\t\tvar stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);\n\t\t\t\t\t\t\tvar bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);\n\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\ttext: label,\n\t\t\t\t\t\t\t\tfillStyle: fill,\n\t\t\t\t\t\t\t\tstrokeStyle: stroke,\n\t\t\t\t\t\t\t\tlineWidth: bw,\n\t\t\t\t\t\t\t\thidden: isNaN(ds.data[i]) || meta.data[i].hidden,\n\n\t\t\t\t\t\t\t\t// Extra data used for toggling the correct item\n\t\t\t\t\t\t\t\tindex: i\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tonClick: function(e, legendItem) {\n\t\t\t\tvar index = legendItem.index;\n\t\t\t\tvar chart = this.chart;\n\t\t\t\tvar i, ilen, meta;\n\n\t\t\t\tfor (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {\n\t\t\t\t\tmeta = chart.getDatasetMeta(i);\n\t\t\t\t\t// toggle visibility of index if exists\n\t\t\t\t\tif (meta.data[index]) {\n\t\t\t\t\t\tmeta.data[index].hidden = !meta.data[index].hidden;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tchart.update();\n\t\t\t}\n\t\t},\n\n\t\t// The percentage of the chart that we cut out of the middle.\n\t\tcutoutPercentage: 50,\n\n\t\t// The rotation of the chart, where the first data arc begins.\n\t\trotation: Math.PI * -0.5,\n\n\t\t// The total circumference of the chart.\n\t\tcircumference: Math.PI * 2.0,\n\n\t\t// Need to override these to give a nice default\n\t\ttooltips: {\n\t\t\tcallbacks: {\n\t\t\t\ttitle: function() {\n\t\t\t\t\treturn '';\n\t\t\t\t},\n\t\t\t\tlabel: function(tooltipItem, data) {\n\t\t\t\t\tvar dataLabel = data.labels[tooltipItem.index];\n\t\t\t\t\tvar value = ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];\n\n\t\t\t\t\tif (helpers.isArray(dataLabel)) {\n\t\t\t\t\t\t// show value on first line of multiline label\n\t\t\t\t\t\t// need to clone because we are changing the value\n\t\t\t\t\t\tdataLabel = dataLabel.slice();\n\t\t\t\t\t\tdataLabel[0] += value;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdataLabel += value;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn dataLabel;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tdefaults.pie = helpers.clone(defaults.doughnut);\n\thelpers.extend(defaults.pie, {\n\t\tcutoutPercentage: 0\n\t});\n\n\n\tChart.controllers.doughnut = Chart.controllers.pie = Chart.DatasetController.extend({\n\n\t\tdataElementType: Chart.elements.Arc,\n\n\t\tlinkScales: helpers.noop,\n\n\t\t// Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly\n\t\tgetRingIndex: function(datasetIndex) {\n\t\t\tvar ringIndex = 0;\n\n\t\t\tfor (var j = 0; j < datasetIndex; ++j) {\n\t\t\t\tif (this.chart.isDatasetVisible(j)) {\n\t\t\t\t\t++ringIndex;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ringIndex;\n\t\t},\n\n\t\tupdate: function(reset) {\n\t\t\tvar me = this;\n\t\t\tvar chart = me.chart,\n\t\t\t\tchartArea = chart.chartArea,\n\t\t\t\topts = chart.options,\n\t\t\t\tarcOpts = opts.elements.arc,\n\t\t\t\tavailableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth,\n\t\t\t\tavailableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth,\n\t\t\t\tminSize = Math.min(availableWidth, availableHeight),\n\t\t\t\toffset = {\n\t\t\t\t\tx: 0,\n\t\t\t\t\ty: 0\n\t\t\t\t},\n\t\t\t\tmeta = me.getMeta(),\n\t\t\t\tcutoutPercentage = opts.cutoutPercentage,\n\t\t\t\tcircumference = opts.circumference;\n\n\t\t\t// If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc\n\t\t\tif (circumference < Math.PI * 2.0) {\n\t\t\t\tvar startAngle = opts.rotation % (Math.PI * 2.0);\n\t\t\t\tstartAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0);\n\t\t\t\tvar endAngle = startAngle + circumference;\n\t\t\t\tvar start = {x: Math.cos(startAngle), y: Math.sin(startAngle)};\n\t\t\t\tvar end = {x: Math.cos(endAngle), y: Math.sin(endAngle)};\n\t\t\t\tvar contains0 = (startAngle <= 0 && 0 <= endAngle) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle);\n\t\t\t\tvar contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle);\n\t\t\t\tvar contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle);\n\t\t\t\tvar contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle);\n\t\t\t\tvar cutout = cutoutPercentage / 100.0;\n\t\t\t\tvar min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))};\n\t\t\t\tvar max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))};\n\t\t\t\tvar size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5};\n\t\t\t\tminSize = Math.min(availableWidth / size.width, availableHeight / size.height);\n\t\t\t\toffset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5};\n\t\t\t}\n\n\t\t\tchart.borderWidth = me.getMaxBorderWidth(meta.data);\n\t\t\tchart.outerRadius = Math.max((minSize - chart.borderWidth) / 2, 0);\n\t\t\tchart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 0, 0);\n\t\t\tchart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();\n\t\t\tchart.offsetX = offset.x * chart.outerRadius;\n\t\t\tchart.offsetY = offset.y * chart.outerRadius;\n\n\t\t\tmeta.total = me.calculateTotal();\n\n\t\t\tme.outerRadius = chart.outerRadius - (chart.radiusLength * me.getRingIndex(me.index));\n\t\t\tme.innerRadius = Math.max(me.outerRadius - chart.radiusLength, 0);\n\n\t\t\thelpers.each(meta.data, function(arc, index) {\n\t\t\t\tme.updateElement(arc, index, reset);\n\t\t\t});\n\t\t},\n\n\t\tupdateElement: function(arc, index, reset) {\n\t\t\tvar me = this;\n\t\t\tvar chart = me.chart,\n\t\t\t\tchartArea = chart.chartArea,\n\t\t\t\topts = chart.options,\n\t\t\t\tanimationOpts = opts.animation,\n\t\t\t\tcenterX = (chartArea.left + chartArea.right) / 2,\n\t\t\t\tcenterY = (chartArea.top + chartArea.bottom) / 2,\n\t\t\t\tstartAngle = opts.rotation, // non reset case handled later\n\t\t\t\tendAngle = opts.rotation, // non reset case handled later\n\t\t\t\tdataset = me.getDataset(),\n\t\t\t\tcircumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI)),\n\t\t\t\tinnerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius,\n\t\t\t\touterRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius,\n\t\t\t\tvalueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\n\n\t\t\thelpers.extend(arc, {\n\t\t\t\t// Utility\n\t\t\t\t_datasetIndex: me.index,\n\t\t\t\t_index: index,\n\n\t\t\t\t// Desired view properties\n\t\t\t\t_model: {\n\t\t\t\t\tx: centerX + chart.offsetX,\n\t\t\t\t\ty: centerY + chart.offsetY,\n\t\t\t\t\tstartAngle: startAngle,\n\t\t\t\t\tendAngle: endAngle,\n\t\t\t\t\tcircumference: circumference,\n\t\t\t\t\touterRadius: outerRadius,\n\t\t\t\t\tinnerRadius: innerRadius,\n\t\t\t\t\tlabel: valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index])\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tvar model = arc._model;\n\t\t\t// Resets the visual styles\n\t\t\tthis.removeHoverStyle(arc);\n\n\t\t\t// Set correct angles if not resetting\n\t\t\tif (!reset || !animationOpts.animateRotate) {\n\t\t\t\tif (index === 0) {\n\t\t\t\t\tmodel.startAngle = opts.rotation;\n\t\t\t\t} else {\n\t\t\t\t\tmodel.startAngle = me.getMeta().data[index - 1]._model.endAngle;\n\t\t\t\t}\n\n\t\t\t\tmodel.endAngle = model.startAngle + model.circumference;\n\t\t\t}\n\n\t\t\tarc.pivot();\n\t\t},\n\n\t\tremoveHoverStyle: function(arc) {\n\t\t\tChart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);\n\t\t},\n\n\t\tcalculateTotal: function() {\n\t\t\tvar dataset = this.getDataset();\n\t\t\tvar meta = this.getMeta();\n\t\t\tvar total = 0;\n\t\t\tvar value;\n\n\t\t\thelpers.each(meta.data, function(element, index) {\n\t\t\t\tvalue = dataset.data[index];\n\t\t\t\tif (!isNaN(value) && !element.hidden) {\n\t\t\t\t\ttotal += Math.abs(value);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t/* if (total === 0) {\n\t\t\t\ttotal = NaN;\n\t\t\t}*/\n\n\t\t\treturn total;\n\t\t},\n\n\t\tcalculateCircumference: function(value) {\n\t\t\tvar total = this.getMeta().total;\n\t\t\tif (total > 0 && !isNaN(value)) {\n\t\t\t\treturn (Math.PI * 2.0) * (value / total);\n\t\t\t}\n\t\t\treturn 0;\n\t\t},\n\n\t\t// gets the max border or hover width to properly scale pie charts\n\t\tgetMaxBorderWidth: function(elements) {\n\t\t\tvar max = 0,\n\t\t\t\tindex = this.index,\n\t\t\t\tlength = elements.length,\n\t\t\t\tborderWidth,\n\t\t\t\thoverWidth;\n\n\t\t\tfor (var i = 0; i < length; i++) {\n\t\t\t\tborderWidth = elements[i]._model ? elements[i]._model.borderWidth : 0;\n\t\t\t\thoverWidth = elements[i]._chart ? elements[i]._chart.config.data.datasets[index].hoverBorderWidth : 0;\n\n\t\t\t\tmax = borderWidth > max ? borderWidth : max;\n\t\t\t\tmax = hoverWidth > max ? hoverWidth : max;\n\t\t\t}\n\t\t\treturn max;\n\t\t}\n\t});\n};\n\n},{}],18:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function(Chart) {\n\n\tvar helpers = Chart.helpers;\n\n\tChart.defaults.line = {\n\t\tshowLines: true,\n\t\tspanGaps: false,\n\n\t\thover: {\n\t\t\tmode: 'label'\n\t\t},\n\n\t\tscales: {\n\t\t\txAxes: [{\n\t\t\t\ttype: 'category',\n\t\t\t\tid: 'x-axis-0'\n\t\t\t}],\n\t\t\tyAxes: [{\n\t\t\t\ttype: 'linear',\n\t\t\t\tid: 'y-axis-0'\n\t\t\t}]\n\t\t}\n\t};\n\n\tfunction lineEnabled(dataset, options) {\n\t\treturn helpers.getValueOrDefault(dataset.showLine, options.showLines);\n\t}\n\n\tChart.controllers.line = Chart.DatasetController.extend({\n\n\t\tdatasetElementType: Chart.elements.Line,\n\n\t\tdataElementType: Chart.elements.Point,\n\n\t\tupdate: function(reset) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar line = meta.dataset;\n\t\t\tvar points = meta.data || [];\n\t\t\tvar options = me.chart.options;\n\t\t\tvar lineElementOptions = options.elements.line;\n\t\t\tvar scale = me.getScaleForId(meta.yAxisID);\n\t\t\tvar i, ilen, custom;\n\t\t\tvar dataset = me.getDataset();\n\t\t\tvar showLine = lineEnabled(dataset, options);\n\n\t\t\t// Update Line\n\t\t\tif (showLine) {\n\t\t\t\tcustom = line.custom || {};\n\n\t\t\t\t// Compatibility: If the properties are defined with only the old name, use those values\n\t\t\t\tif ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {\n\t\t\t\t\tdataset.lineTension = dataset.tension;\n\t\t\t\t}\n\n\t\t\t\t// Utility\n\t\t\t\tline._scale = scale;\n\t\t\t\tline._datasetIndex = me.index;\n\t\t\t\t// Data\n\t\t\t\tline._children = points;\n\t\t\t\t// Model\n\t\t\t\tline._model = {\n\t\t\t\t\t// Appearance\n\t\t\t\t\t// The default behavior of lines is to break at null values, according\n\t\t\t\t\t// to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158\n\t\t\t\t\t// This option gives lines the ability to span gaps\n\t\t\t\t\tspanGaps: dataset.spanGaps ? dataset.spanGaps : options.spanGaps,\n\t\t\t\t\ttension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension),\n\t\t\t\t\tbackgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),\n\t\t\t\t\tborderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),\n\t\t\t\t\tborderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),\n\t\t\t\t\tborderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),\n\t\t\t\t\tborderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),\n\t\t\t\t\tborderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),\n\t\t\t\t\tborderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),\n\t\t\t\t\tfill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),\n\t\t\t\t\tsteppedLine: custom.steppedLine ? custom.steppedLine : helpers.getValueOrDefault(dataset.steppedLine, lineElementOptions.stepped),\n\t\t\t\t\tcubicInterpolationMode: custom.cubicInterpolationMode ? custom.cubicInterpolationMode : helpers.getValueOrDefault(dataset.cubicInterpolationMode, lineElementOptions.cubicInterpolationMode),\n\t\t\t\t\t// Scale\n\t\t\t\t\tscaleTop: scale.top,\n\t\t\t\t\tscaleBottom: scale.bottom,\n\t\t\t\t\tscaleZero: scale.getBasePixel()\n\t\t\t\t};\n\n\t\t\t\tline.pivot();\n\t\t\t}\n\n\t\t\t// Update Points\n\t\t\tfor (i=0, ilen=points.length; i');\n\n\t\t\tvar data = chart.data;\n\t\t\tvar datasets = data.datasets;\n\t\t\tvar labels = data.labels;\n\n\t\t\tif (datasets.length) {\n\t\t\t\tfor (var i = 0; i < datasets[0].data.length; ++i) {\n\t\t\t\t\ttext.push('
  • ');\n\t\t\t\t\tif (labels[i]) {\n\t\t\t\t\t\ttext.push(labels[i]);\n\t\t\t\t\t}\n\t\t\t\t\ttext.push('
  • ');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttext.push('');\n\t\t\treturn text.join('');\n\t\t},\n\t\tlegend: {\n\t\t\tlabels: {\n\t\t\t\tgenerateLabels: function(chart) {\n\t\t\t\t\tvar data = chart.data;\n\t\t\t\t\tif (data.labels.length && data.datasets.length) {\n\t\t\t\t\t\treturn data.labels.map(function(label, i) {\n\t\t\t\t\t\t\tvar meta = chart.getDatasetMeta(0);\n\t\t\t\t\t\t\tvar ds = data.datasets[0];\n\t\t\t\t\t\t\tvar arc = meta.data[i];\n\t\t\t\t\t\t\tvar custom = arc.custom || {};\n\t\t\t\t\t\t\tvar getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\n\t\t\t\t\t\t\tvar arcOpts = chart.options.elements.arc;\n\t\t\t\t\t\t\tvar fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);\n\t\t\t\t\t\t\tvar stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);\n\t\t\t\t\t\t\tvar bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);\n\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\ttext: label,\n\t\t\t\t\t\t\t\tfillStyle: fill,\n\t\t\t\t\t\t\t\tstrokeStyle: stroke,\n\t\t\t\t\t\t\t\tlineWidth: bw,\n\t\t\t\t\t\t\t\thidden: isNaN(ds.data[i]) || meta.data[i].hidden,\n\n\t\t\t\t\t\t\t\t// Extra data used for toggling the correct item\n\t\t\t\t\t\t\t\tindex: i\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tonClick: function(e, legendItem) {\n\t\t\t\tvar index = legendItem.index;\n\t\t\t\tvar chart = this.chart;\n\t\t\t\tvar i, ilen, meta;\n\n\t\t\t\tfor (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) {\n\t\t\t\t\tmeta = chart.getDatasetMeta(i);\n\t\t\t\t\tmeta.data[index].hidden = !meta.data[index].hidden;\n\t\t\t\t}\n\n\t\t\t\tchart.update();\n\t\t\t}\n\t\t},\n\n\t\t// Need to override these to give a nice default\n\t\ttooltips: {\n\t\t\tcallbacks: {\n\t\t\t\ttitle: function() {\n\t\t\t\t\treturn '';\n\t\t\t\t},\n\t\t\t\tlabel: function(tooltipItem, data) {\n\t\t\t\t\treturn data.labels[tooltipItem.index] + ': ' + tooltipItem.yLabel;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tChart.controllers.polarArea = Chart.DatasetController.extend({\n\n\t\tdataElementType: Chart.elements.Arc,\n\n\t\tlinkScales: helpers.noop,\n\n\t\tupdate: function(reset) {\n\t\t\tvar me = this;\n\t\t\tvar chart = me.chart;\n\t\t\tvar chartArea = chart.chartArea;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar opts = chart.options;\n\t\t\tvar arcOpts = opts.elements.arc;\n\t\t\tvar minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);\n\t\t\tchart.outerRadius = Math.max((minSize - arcOpts.borderWidth / 2) / 2, 0);\n\t\t\tchart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);\n\t\t\tchart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount();\n\n\t\t\tme.outerRadius = chart.outerRadius - (chart.radiusLength * me.index);\n\t\t\tme.innerRadius = me.outerRadius - chart.radiusLength;\n\n\t\t\tmeta.count = me.countVisibleElements();\n\n\t\t\thelpers.each(meta.data, function(arc, index) {\n\t\t\t\tme.updateElement(arc, index, reset);\n\t\t\t});\n\t\t},\n\n\t\tupdateElement: function(arc, index, reset) {\n\t\t\tvar me = this;\n\t\t\tvar chart = me.chart;\n\t\t\tvar dataset = me.getDataset();\n\t\t\tvar opts = chart.options;\n\t\t\tvar animationOpts = opts.animation;\n\t\t\tvar scale = chart.scale;\n\t\t\tvar getValueAtIndexOrDefault = helpers.getValueAtIndexOrDefault;\n\t\t\tvar labels = chart.data.labels;\n\n\t\t\tvar circumference = me.calculateCircumference(dataset.data[index]);\n\t\t\tvar centerX = scale.xCenter;\n\t\t\tvar centerY = scale.yCenter;\n\n\t\t\t// If there is NaN data before us, we need to calculate the starting angle correctly.\n\t\t\t// We could be way more efficient here, but its unlikely that the polar area chart will have a lot of data\n\t\t\tvar visibleCount = 0;\n\t\t\tvar meta = me.getMeta();\n\t\t\tfor (var i = 0; i < index; ++i) {\n\t\t\t\tif (!isNaN(dataset.data[i]) && !meta.data[i].hidden) {\n\t\t\t\t\t++visibleCount;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// var negHalfPI = -0.5 * Math.PI;\n\t\t\tvar datasetStartAngle = opts.startAngle;\n\t\t\tvar distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);\n\t\t\tvar startAngle = datasetStartAngle + (circumference * visibleCount);\n\t\t\tvar endAngle = startAngle + (arc.hidden ? 0 : circumference);\n\n\t\t\tvar resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]);\n\n\t\t\thelpers.extend(arc, {\n\t\t\t\t// Utility\n\t\t\t\t_datasetIndex: me.index,\n\t\t\t\t_index: index,\n\t\t\t\t_scale: scale,\n\n\t\t\t\t// Desired view properties\n\t\t\t\t_model: {\n\t\t\t\t\tx: centerX,\n\t\t\t\t\ty: centerY,\n\t\t\t\t\tinnerRadius: 0,\n\t\t\t\t\touterRadius: reset ? resetRadius : distance,\n\t\t\t\t\tstartAngle: reset && animationOpts.animateRotate ? datasetStartAngle : startAngle,\n\t\t\t\t\tendAngle: reset && animationOpts.animateRotate ? datasetStartAngle : endAngle,\n\t\t\t\t\tlabel: getValueAtIndexOrDefault(labels, index, labels[index])\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Apply border and fill style\n\t\t\tme.removeHoverStyle(arc);\n\n\t\t\tarc.pivot();\n\t\t},\n\n\t\tremoveHoverStyle: function(arc) {\n\t\t\tChart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc);\n\t\t},\n\n\t\tcountVisibleElements: function() {\n\t\t\tvar dataset = this.getDataset();\n\t\t\tvar meta = this.getMeta();\n\t\t\tvar count = 0;\n\n\t\t\thelpers.each(meta.data, function(element, index) {\n\t\t\t\tif (!isNaN(dataset.data[index]) && !element.hidden) {\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn count;\n\t\t},\n\n\t\tcalculateCircumference: function(value) {\n\t\t\tvar count = this.getMeta().count;\n\t\t\tif (count > 0 && !isNaN(value)) {\n\t\t\t\treturn (2 * Math.PI) / count;\n\t\t\t}\n\t\t\treturn 0;\n\t\t}\n\t});\n};\n\n},{}],20:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function(Chart) {\n\n\tvar helpers = Chart.helpers;\n\n\tChart.defaults.radar = {\n\t\taspectRatio: 1,\n\t\tscale: {\n\t\t\ttype: 'radialLinear'\n\t\t},\n\t\telements: {\n\t\t\tline: {\n\t\t\t\ttension: 0 // no bezier in radar\n\t\t\t}\n\t\t}\n\t};\n\n\tChart.controllers.radar = Chart.DatasetController.extend({\n\n\t\tdatasetElementType: Chart.elements.Line,\n\n\t\tdataElementType: Chart.elements.Point,\n\n\t\tlinkScales: helpers.noop,\n\n\t\tupdate: function(reset) {\n\t\t\tvar me = this;\n\t\t\tvar meta = me.getMeta();\n\t\t\tvar line = meta.dataset;\n\t\t\tvar points = meta.data;\n\t\t\tvar custom = line.custom || {};\n\t\t\tvar dataset = me.getDataset();\n\t\t\tvar lineElementOptions = me.chart.options.elements.line;\n\t\t\tvar scale = me.chart.scale;\n\n\t\t\t// Compatibility: If the properties are defined with only the old name, use those values\n\t\t\tif ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) {\n\t\t\t\tdataset.lineTension = dataset.tension;\n\t\t\t}\n\n\t\t\thelpers.extend(meta.dataset, {\n\t\t\t\t// Utility\n\t\t\t\t_datasetIndex: me.index,\n\t\t\t\t// Data\n\t\t\t\t_children: points,\n\t\t\t\t_loop: true,\n\t\t\t\t// Model\n\t\t\t\t_model: {\n\t\t\t\t\t// Appearance\n\t\t\t\t\ttension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, lineElementOptions.tension),\n\t\t\t\t\tbackgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor),\n\t\t\t\t\tborderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth),\n\t\t\t\t\tborderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor),\n\t\t\t\t\tfill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill),\n\t\t\t\t\tborderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle),\n\t\t\t\t\tborderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash),\n\t\t\t\t\tborderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset),\n\t\t\t\t\tborderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle),\n\n\t\t\t\t\t// Scale\n\t\t\t\t\tscaleTop: scale.top,\n\t\t\t\t\tscaleBottom: scale.bottom,\n\t\t\t\t\tscaleZero: scale.getBasePosition()\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tmeta.dataset.pivot();\n\n\t\t\t// Update Points\n\t\t\thelpers.each(points, function(point, index) {\n\t\t\t\tme.updateElement(point, index, reset);\n\t\t\t}, me);\n\n\t\t\t// Update bezier control points\n\t\t\tme.updateBezierControlPoints();\n\t\t},\n\t\tupdateElement: function(point, index, reset) {\n\t\t\tvar me = this;\n\t\t\tvar custom = point.custom || {};\n\t\t\tvar dataset = me.getDataset();\n\t\t\tvar scale = me.chart.scale;\n\t\t\tvar pointElementOptions = me.chart.options.elements.point;\n\t\t\tvar pointPosition = scale.getPointPositionForValue(index, dataset.data[index]);\n\n\t\t\thelpers.extend(point, {\n\t\t\t\t// Utility\n\t\t\t\t_datasetIndex: me.index,\n\t\t\t\t_index: index,\n\t\t\t\t_scale: scale,\n\n\t\t\t\t// Desired view properties\n\t\t\t\t_model: {\n\t\t\t\t\tx: reset ? scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales\n\t\t\t\t\ty: reset ? scale.yCenter : pointPosition.y,\n\n\t\t\t\t\t// Appearance\n\t\t\t\t\ttension: custom.tension ? custom.tension : helpers.getValueOrDefault(dataset.lineTension, me.chart.options.elements.line.tension),\n\t\t\t\t\tradius: custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.pointRadius, index, pointElementOptions.radius),\n\t\t\t\t\tbackgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor),\n\t\t\t\t\tborderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor),\n\t\t\t\t\tborderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth),\n\t\t\t\t\tpointStyle: custom.pointStyle ? custom.pointStyle : helpers.getValueAtIndexOrDefault(dataset.pointStyle, index, pointElementOptions.pointStyle),\n\n\t\t\t\t\t// Tooltip\n\t\t\t\t\thitRadius: custom.hitRadius ? custom.hitRadius : helpers.getValueAtIndexOrDefault(dataset.hitRadius, index, pointElementOptions.hitRadius)\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tpoint._model.skip = custom.skip ? custom.skip : (isNaN(point._model.x) || isNaN(point._model.y));\n\t\t},\n\t\tupdateBezierControlPoints: function() {\n\t\t\tvar chartArea = this.chart.chartArea;\n\t\t\tvar meta = this.getMeta();\n\n\t\t\thelpers.each(meta.data, function(point, index) {\n\t\t\t\tvar model = point._model;\n\t\t\t\tvar controlPoints = helpers.splineCurve(\n\t\t\t\t\thelpers.previousItem(meta.data, index, true)._model,\n\t\t\t\t\tmodel,\n\t\t\t\t\thelpers.nextItem(meta.data, index, true)._model,\n\t\t\t\t\tmodel.tension\n\t\t\t\t);\n\n\t\t\t\t// Prevent the bezier going outside of the bounds of the graph\n\t\t\t\tmodel.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, chartArea.right), chartArea.left);\n\t\t\t\tmodel.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, chartArea.bottom), chartArea.top);\n\n\t\t\t\tmodel.controlPointNextX = Math.max(Math.min(controlPoints.next.x, chartArea.right), chartArea.left);\n\t\t\t\tmodel.controlPointNextY = Math.max(Math.min(controlPoints.next.y, chartArea.bottom), chartArea.top);\n\n\t\t\t\t// Now pivot the point for animation\n\t\t\t\tpoint.pivot();\n\t\t\t});\n\t\t},\n\n\t\tdraw: function(ease) {\n\t\t\tvar meta = this.getMeta();\n\t\t\tvar easingDecimal = ease || 1;\n\n\t\t\t// Transition Point Locations\n\t\t\thelpers.each(meta.data, function(point) {\n\t\t\t\tpoint.transition(easingDecimal);\n\t\t\t});\n\n\t\t\t// Transition and Draw the line\n\t\t\tmeta.dataset.transition(easingDecimal).draw();\n\n\t\t\t// Draw the points\n\t\t\thelpers.each(meta.data, function(point) {\n\t\t\t\tpoint.draw();\n\t\t\t});\n\t\t},\n\n\t\tsetHoverStyle: function(point) {\n\t\t\t// Point\n\t\t\tvar dataset = this.chart.data.datasets[point._datasetIndex];\n\t\t\tvar custom = point.custom || {};\n\t\t\tvar index = point._index;\n\t\t\tvar model = point._model;\n\n\t\t\tmodel.radius = custom.hoverRadius ? custom.hoverRadius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius);\n\t\t\tmodel.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));\n\t\t\tmodel.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor));\n\t\t\tmodel.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth);\n\t\t},\n\n\t\tremoveHoverStyle: function(point) {\n\t\t\tvar dataset = this.chart.data.datasets[point._datasetIndex];\n\t\t\tvar custom = point.custom || {};\n\t\t\tvar index = point._index;\n\t\t\tvar model = point._model;\n\t\t\tvar pointElementOptions = this.chart.options.elements.point;\n\n\t\t\tmodel.radius = custom.radius ? custom.radius : helpers.getValueAtIndexOrDefault(dataset.radius, index, pointElementOptions.radius);\n\t\t\tmodel.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor);\n\t\t\tmodel.borderColor = custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor);\n\t\t\tmodel.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth);\n\t\t}\n\t});\n};\n\n},{}],21:[function(require,module,exports){\n/* global window: false */\n'use strict';\n\nmodule.exports = function(Chart) {\n\n\tvar helpers = Chart.helpers;\n\n\tChart.defaults.global.animation = {\n\t\tduration: 1000,\n\t\teasing: 'easeOutQuart',\n\t\tonProgress: helpers.noop,\n\t\tonComplete: helpers.noop\n\t};\n\n\tChart.Animation = Chart.Element.extend({\n\t\tcurrentStep: null, // the current animation step\n\t\tnumSteps: 60, // default number of steps\n\t\teasing: '', // the easing to use for this animation\n\t\trender: null, // render function used by the animation service\n\n\t\tonAnimationProgress: null, // user specified callback to fire on each step of the animation\n\t\tonAnimationComplete: null // user specified callback to fire when the animation finishes\n\t});\n\n\tChart.animationService = {\n\t\tframeDuration: 17,\n\t\tanimations: [],\n\t\tdropFrames: 0,\n\t\trequest: null,\n\n\t\t/**\n\t\t * @function Chart.animationService.addAnimation\n\t\t * @param chartInstance {ChartController} the chart to animate\n\t\t * @param animationObject {IAnimation} the animation that we will animate\n\t\t * @param duration {Number} length of animation in ms\n\t\t * @param lazy {Boolean} if true, the chart is not marked as animating to enable more responsive interactions\n\t\t */\n\t\taddAnimation: function(chartInstance, animationObject, duration, lazy) {\n\t\t\tvar me = this;\n\n\t\t\tif (!lazy) {\n\t\t\t\tchartInstance.animating = true;\n\t\t\t}\n\n\t\t\tfor (var index = 0; index < me.animations.length; ++index) {\n\t\t\t\tif (me.animations[index].chartInstance === chartInstance) {\n\t\t\t\t\t// replacing an in progress animation\n\t\t\t\t\tme.animations[index].animationObject = animationObject;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tme.animations.push({\n\t\t\t\tchartInstance: chartInstance,\n\t\t\t\tanimationObject: animationObject\n\t\t\t});\n\n\t\t\t// If there are no animations queued, manually kickstart a digest, for lack of a better word\n\t\t\tif (me.animations.length === 1) {\n\t\t\t\tme.requestAnimationFrame();\n\t\t\t}\n\t\t},\n\t\t// Cancel the animation for a given chart instance\n\t\tcancelAnimation: function(chartInstance) {\n\t\t\tvar index = helpers.findIndex(this.animations, function(animationWrapper) {\n\t\t\t\treturn animationWrapper.chartInstance === chartInstance;\n\t\t\t});\n\n\t\t\tif (index !== -1) {\n\t\t\t\tthis.animations.splice(index, 1);\n\t\t\t\tchartInstance.animating = false;\n\t\t\t}\n\t\t},\n\t\trequestAnimationFrame: function() {\n\t\t\tvar me = this;\n\t\t\tif (me.request === null) {\n\t\t\t\t// Skip animation frame requests until the active one is executed.\n\t\t\t\t// This can happen when processing mouse events, e.g. 'mousemove'\n\t\t\t\t// and 'mouseout' events will trigger multiple renders.\n\t\t\t\tme.request = helpers.requestAnimFrame.call(window, function() {\n\t\t\t\t\tme.request = null;\n\t\t\t\t\tme.startDigest();\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tstartDigest: function() {\n\t\t\tvar me = this;\n\n\t\t\tvar startTime = Date.now();\n\t\t\tvar framesToDrop = 0;\n\n\t\t\tif (me.dropFrames > 1) {\n\t\t\t\tframesToDrop = Math.floor(me.dropFrames);\n\t\t\t\tme.dropFrames = me.dropFrames % 1;\n\t\t\t}\n\n\t\t\tvar i = 0;\n\t\t\twhile (i < me.animations.length) {\n\t\t\t\tif (me.animations[i].animationObject.currentStep === null) {\n\t\t\t\t\tme.animations[i].animationObject.currentStep = 0;\n\t\t\t\t}\n\n\t\t\t\tme.animations[i].animationObject.currentStep += 1 + framesToDrop;\n\n\t\t\t\tif (me.animations[i].animationObject.currentStep > me.animations[i].animationObject.numSteps) {\n\t\t\t\t\tme.animations[i].animationObject.currentStep = me.animations[i].animationObject.numSteps;\n\t\t\t\t}\n\n\t\t\t\tme.animations[i].animationObject.render(me.animations[i].chartInstance, me.animations[i].animationObject);\n\t\t\t\tif (me.animations[i].animationObject.onAnimationProgress && me.animations[i].animationObject.onAnimationProgress.call) {\n\t\t\t\t\tme.animations[i].animationObject.onAnimationProgress.call(me.animations[i].chartInstance, me.animations[i]);\n\t\t\t\t}\n\n\t\t\t\tif (me.animations[i].animationObject.currentStep === me.animations[i].animationObject.numSteps) {\n\t\t\t\t\tif (me.animations[i].animationObject.onAnimationComplete && me.animations[i].animationObject.onAnimationComplete.call) {\n\t\t\t\t\t\tme.animations[i].animationObject.onAnimationComplete.call(me.animations[i].chartInstance, me.animations[i]);\n\t\t\t\t\t}\n\n\t\t\t\t\t// executed the last frame. Remove the animation.\n\t\t\t\t\tme.animations[i].chartInstance.animating = false;\n\n\t\t\t\t\tme.animations.splice(i, 1);\n\t\t\t\t} else {\n\t\t\t\t\t++i;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar endTime = Date.now();\n\t\t\tvar dropFrames = (endTime - startTime) / me.frameDuration;\n\n\t\t\tme.dropFrames += dropFrames;\n\n\t\t\t// Do we have more stuff to animate?\n\t\t\tif (me.animations.length > 0) {\n\t\t\t\tme.requestAnimationFrame();\n\t\t\t}\n\t\t}\n\t};\n};\n\n},{}],22:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function(Chart) {\n\t// Global Chart canvas helpers object for drawing items to canvas\n\tvar helpers = Chart.canvasHelpers = {};\n\n\thelpers.drawPoint = function(ctx, pointStyle, radius, x, y) {\n\t\tvar type, edgeLength, xOffset, yOffset, height, size;\n\n\t\tif (typeof pointStyle === 'object') {\n\t\t\ttype = pointStyle.toString();\n\t\t\tif (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {\n\t\t\t\tctx.drawImage(pointStyle, x - pointStyle.width / 2, y - pointStyle.height / 2);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (isNaN(radius) || radius <= 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tswitch (pointStyle) {\n\t\t// Default includes circle\n\t\tdefault:\n\t\t\tctx.beginPath();\n\t\t\tctx.arc(x, y, radius, 0, Math.PI * 2);\n\t\t\tctx.closePath();\n\t\t\tctx.fill();\n\t\t\tbreak;\n\t\tcase 'triangle':\n\t\t\tctx.beginPath();\n\t\t\tedgeLength = 3 * radius / Math.sqrt(3);\n\t\t\theight = edgeLength * Math.sqrt(3) / 2;\n\t\t\tctx.moveTo(x - edgeLength / 2, y + height / 3);\n\t\t\tctx.lineTo(x + edgeLength / 2, y + height / 3);\n\t\t\tctx.lineTo(x, y - 2 * height / 3);\n\t\t\tctx.closePath();\n\t\t\tctx.fill();\n\t\t\tbreak;\n\t\tcase 'rect':\n\t\t\tsize = 1 / Math.SQRT2 * radius;\n\t\t\tctx.beginPath();\n\t\t\tctx.fillRect(x - size, y - size, 2 * size, 2 * size);\n\t\t\tctx.strokeRect(x - size, y - size, 2 * size, 2 * size);\n\t\t\tbreak;\n\t\tcase 'rectRounded':\n\t\t\tvar offset = radius / Math.SQRT2;\n\t\t\tvar leftX = x - offset;\n\t\t\tvar topY = y - offset;\n\t\t\tvar sideSize = Math.SQRT2 * radius;\n\t\t\tChart.helpers.drawRoundedRectangle(ctx, leftX, topY, sideSize, sideSize, radius / 2);\n\t\t\tctx.fill();\n\t\t\tbreak;\n\t\tcase 'rectRot':\n\t\t\tsize = 1 / Math.SQRT2 * radius;\n\t\t\tctx.beginPath();\n\t\t\tctx.moveTo(x - size, y);\n\t\t\tctx.lineTo(x, y + size);\n\t\t\tctx.lineTo(x + size, y);\n\t\t\tctx.lineTo(x, y - size);\n\t\t\tctx.closePath();\n\t\t\tctx.fill();\n\t\t\tbreak;\n\t\tcase 'cross':\n\t\t\tctx.beginPath();\n\t\t\tctx.moveTo(x, y + radius);\n\t\t\tctx.lineTo(x, y - radius);\n\t\t\tctx.moveTo(x - radius, y);\n\t\t\tctx.lineTo(x + radius, y);\n\t\t\tctx.closePath();\n\t\t\tbreak;\n\t\tcase 'crossRot':\n\t\t\tctx.beginPath();\n\t\t\txOffset = Math.cos(Math.PI / 4) * radius;\n\t\t\tyOffset = Math.sin(Math.PI / 4) * radius;\n\t\t\tctx.moveTo(x - xOffset, y - yOffset);\n\t\t\tctx.lineTo(x + xOffset, y + yOffset);\n\t\t\tctx.moveTo(x - xOffset, y + yOffset);\n\t\t\tctx.lineTo(x + xOffset, y - yOffset);\n\t\t\tctx.closePath();\n\t\t\tbreak;\n\t\tcase 'star':\n\t\t\tctx.beginPath();\n\t\t\tctx.moveTo(x, y + radius);\n\t\t\tctx.lineTo(x, y - radius);\n\t\t\tctx.moveTo(x - radius, y);\n\t\t\tctx.lineTo(x + radius, y);\n\t\t\txOffset = Math.cos(Math.PI / 4) * radius;\n\t\t\tyOffset = Math.sin(Math.PI / 4) * radius;\n\t\t\tctx.moveTo(x - xOffset, y - yOffset);\n\t\t\tctx.lineTo(x + xOffset, y + yOffset);\n\t\t\tctx.moveTo(x - xOffset, y + yOffset);\n\t\t\tctx.lineTo(x + xOffset, y - yOffset);\n\t\t\tctx.closePath();\n\t\t\tbreak;\n\t\tcase 'line':\n\t\t\tctx.beginPath();\n\t\t\tctx.moveTo(x - radius, y);\n\t\t\tctx.lineTo(x + radius, y);\n\t\t\tctx.closePath();\n\t\t\tbreak;\n\t\tcase 'dash':\n\t\t\tctx.beginPath();\n\t\t\tctx.moveTo(x, y);\n\t\t\tctx.lineTo(x + radius, y);\n\t\t\tctx.closePath();\n\t\t\tbreak;\n\t\t}\n\n\t\tctx.stroke();\n\t};\n\n\thelpers.clipArea = function(ctx, clipArea) {\n\t\tctx.save();\n\t\tctx.beginPath();\n\t\tctx.rect(clipArea.left, clipArea.top, clipArea.right - clipArea.left, clipArea.bottom - clipArea.top);\n\t\tctx.clip();\n\t};\n\n\thelpers.unclipArea = function(ctx) {\n\t\tctx.restore();\n\t};\n\n};\n\n},{}],23:[function(require,module,exports){\n'use strict';\n\nmodule.exports = function(Chart) {\n\n\tvar helpers = Chart.helpers;\n\tvar plugins = Chart.plugins;\n\tvar platform = Chart.platform;\n\n\t// Create a dictionary of chart types, to allow for extension of existing types\n\tChart.types = {};\n\n\t// Store a reference to each instance - allowing us to globally resize chart instances on window resize.\n\t// Destroy method on the chart will remove the instance of the chart from this reference.\n\tChart.instances = {};\n\n\t// Controllers available for dataset visualization eg. bar, line, slice, etc.\n\tChart.controllers = {};\n\n\t/**\n\t * Initializes the given config with global and chart default values.\n\t */\n\tfunction initConfig(config) {\n\t\tconfig = config || {};\n\n\t\t// Do NOT use configMerge() for the data object because this method merges arrays\n\t\t// and so would change references to labels and datasets, preventing data updates.\n\t\tvar data = config.data = config.data || {};\n\t\tdata.datasets = data.datasets || [];\n\t\tdata.labels = data.labels || [];\n\n\t\tconfig.options = helpers.configMerge(\n\t\t\tChart.defaults.global,\n\t\t\tChart.defaults[config.type],\n\t\t\tconfig.options || {});\n\n\t\treturn config;\n\t}\n\n\t/**\n\t * Updates the config of the chart\n\t * @param chart {Chart.Controller} chart to update the options for\n\t */\n\tfunction updateConfig(chart) {\n\t\tvar newOptions = chart.options;\n\n\t\t// Update Scale(s) with options\n\t\tif (newOptions.scale) {\n\t\t\tchart.scale.options = newOptions.scale;\n\t\t} else if (newOptions.scales) {\n\t\t\tnewOptions.scales.xAxes.concat(newOptions.scales.yAxes).forEach(function(scaleOptions) {\n\t\t\t\tchart.scales[scaleOptions.id].options = scaleOptions;\n\t\t\t});\n\t\t}\n\n\t\t// Tooltip\n\t\tchart.tooltip._options = newOptions.tooltips;\n\t}\n\n\t/**\n\t * @class Chart.Controller\n\t * The main controller of a chart.\n\t */\n\tChart.Controller = function(item, config, instance) {\n\t\tvar me = this;\n\n\t\tconfig = initConfig(config);\n\n\t\tvar context = platform.acquireContext(item, config);\n\t\tvar canvas = context && context.canvas;\n\t\tvar height = canvas && canvas.height;\n\t\tvar width = canvas && canvas.width;\n\n\t\tinstance.ctx = context;\n\t\tinstance.canvas = canvas;\n\t\tinstance.config = config;\n\t\tinstance.width = width;\n\t\tinstance.height = height;\n\t\tinstance.aspectRatio = height? width / height : null;\n\n\t\tme.id = helpers.uid();\n\t\tme.chart = instance;\n\t\tme.config = config;\n\t\tme.options = config.options;\n\t\tme._bufferedRender = false;\n\n\t\t// Add the chart instance to the global namespace\n\t\tChart.instances[me.id] = me;\n\n\t\tObject.defineProperty(me, 'data', {\n\t\t\tget: function() {\n\t\t\t\treturn me.config.data;\n\t\t\t}\n\t\t});\n\n\t\tif (!context || !canvas) {\n\t\t\t// The given item is not a compatible context2d element, let's return before finalizing\n\t\t\t// the chart initialization but after setting basic chart / controller properties that\n\t\t\t// can help to figure out that the chart is not valid (e.g chart.canvas !== null);\n\t\t\t// https://github.com/chartjs/Chart.js/issues/2807\n\t\t\tconsole.error(\"Failed to create chart: can't acquire context from the given item\");\n\t\t\treturn me;\n\t\t}\n\n\t\tme.initialize();\n\t\tme.update();\n\n\t\treturn me;\n\t};\n\n\thelpers.extend(Chart.Controller.prototype, /** @lends Chart.Controller.prototype */ {\n\t\tinitialize: function() {\n\t\t\tvar me = this;\n\n\t\t\t// Before init plugin notification\n\t\t\tplugins.notify(me, 'beforeInit');\n\n\t\t\thelpers.retinaScale(me.chart);\n\n\t\t\tme.bindEvents();\n\n\t\t\tif (me.options.responsive) {\n\t\t\t\t// Initial resize before chart draws (must be silent to preserve initial animations).\n\t\t\t\tme.resize(true);\n\t\t\t}\n\n\t\t\t// Make sure scales have IDs and are built before we build any controllers.\n\t\t\tme.ensureScalesHaveIDs();\n\t\t\tme.buildScales();\n\t\t\tme.initToolTip();\n\n\t\t\t// After init plugin notification\n\t\t\tplugins.notify(me, 'afterInit');\n\n\t\t\treturn me;\n\t\t},\n\n\t\tclear: function() {\n\t\t\thelpers.clear(this.chart);\n\t\t\treturn this;\n\t\t},\n\n\t\tstop: function() {\n\t\t\t// Stops any current animation loop occurring\n\t\t\tChart.animationService.cancelAnimation(this);\n\t\t\treturn this;\n\t\t},\n\n\t\tresize: function(silent) {\n\t\t\tvar me = this;\n\t\t\tvar chart = me.chart;\n\t\t\tvar options = me.options;\n\t\t\tvar canvas = chart.canvas;\n\t\t\tvar aspectRatio = (options.maintainAspectRatio && chart.aspectRatio) || null;\n\n\t\t\t// the canvas render width and height will be casted to integers so make sure that\n\t\t\t// the canvas display style uses the same integer values to avoid blurring effect.\n\t\t\tvar newWidth = Math.floor(helpers.getMaximumWidth(canvas));\n\t\t\tvar newHeight = Math.floor(aspectRatio? newWidth / aspectRatio : helpers.getMaximumHeight(canvas));\n\n\t\t\tif (chart.width === newWidth && chart.height === newHeight) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcanvas.width = chart.width = newWidth;\n\t\t\tcanvas.height = chart.height = newHeight;\n\t\t\tcanvas.style.width = newWidth + 'px';\n\t\t\tcanvas.style.height = newHeight + 'px';\n\n\t\t\thelpers.retinaScale(chart);\n\n\t\t\tif (!silent) {\n\t\t\t\t// Notify any plugins about the resize\n\t\t\t\tvar newSize = {width: newWidth, height: newHeight};\n\t\t\t\tplugins.notify(me, 'resize', [newSize]);\n\n\t\t\t\t// Notify of resize\n\t\t\t\tif (me.options.onResize) {\n\t\t\t\t\tme.options.onResize(me, newSize);\n\t\t\t\t}\n\n\t\t\t\tme.stop();\n\t\t\t\tme.update(me.options.responsiveAnimationDuration);\n\t\t\t}\n\t\t},\n\n\t\tensureScalesHaveIDs: function() {\n\t\t\tvar options = this.options;\n\t\t\tvar scalesOptions = options.scales || {};\n\t\t\tvar scaleOptions = options.scale;\n\n\t\t\thelpers.each(scalesOptions.xAxes, function(xAxisOptions, index) {\n\t\t\t\txAxisOptions.id = xAxisOptions.id || ('x-axis-' + index);\n\t\t\t});\n\n\t\t\thelpers.each(scalesOptions.yAxes, function(yAxisOptions, index) {\n\t\t\t\tyAxisOptions.id = yAxisOptions.id || ('y-axis-' + index);\n\t\t\t});\n\n\t\t\tif (scaleOptions) {\n\t\t\t\tscaleOptions.id = scaleOptions.id || 'scale';\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Builds a map of scale ID to scale object for future lookup.\n\t\t */\n\t\tbuildScales: function() {\n\t\t\tvar me = this;\n\t\t\tvar options = me.options;\n\t\t\tvar scales = me.scales = {};\n\t\t\tvar items = [];\n\n\t\t\tif (options.scales) {\n\t\t\t\titems = items.concat(\n\t\t\t\t\t(options.scales.xAxes || []).map(function(xAxisOptions) {\n\t\t\t\t\t\treturn {options: xAxisOptions, dtype: 'category'};\n\t\t\t\t\t}),\n\t\t\t\t\t(options.scales.yAxes || []).map(function(yAxisOptions) {\n\t\t\t\t\t\treturn {options: yAxisOptions, dtype: 'linear'};\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (options.scale) {\n\t\t\t\titems.push({options: options.scale, dtype: 'radialLinear', isDefault: true});\n\t\t\t}\n\n\t\t\thelpers.each(items, function(item) {\n\t\t\t\tvar scaleOptions = item.options;\n\t\t\t\tvar scaleType = helpers.getValueOrDefault(scaleOptions.type, item.dtype);\n\t\t\t\tvar scaleClass = Chart.scaleService.getScaleConstructor(scaleType);\n\t\t\t\tif (!scaleClass) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar scale = new scaleClass({\n\t\t\t\t\tid: scaleOptions.id,\n\t\t\t\t\toptions: scaleOptions,\n\t\t\t\t\tctx: me.chart.ctx,\n\t\t\t\t\tchart: me\n\t\t\t\t});\n\n\t\t\t\tscales[scale.id] = scale;\n\n\t\t\t\t// TODO(SB): I think we should be able to remove this custom case (options.scale)\n\t\t\t\t// and consider it as a regular scale part of the \"scales\"\" map only! This would\n\t\t\t\t// make the logic easier and remove some useless? custom code.\n\t\t\t\tif (item.isDefault) {\n\t\t\t\t\tme.scale = scale;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tChart.scaleService.addScalesToLayout(this);\n\t\t},\n\n\t\tbuildOrUpdateControllers: function() {\n\t\t\tvar me = this;\n\t\t\tvar types = [];\n\t\t\tvar newControllers = [];\n\n\t\t\thelpers.each(me.data.datasets, function(dataset, datasetIndex) {\n\t\t\t\tvar meta = me.getDatasetMeta(datasetIndex);\n\t\t\t\tif (!meta.type) {\n\t\t\t\t\tmeta.type = dataset.type || me.config.type;\n\t\t\t\t}\n\n\t\t\t\ttypes.push(meta.type);\n\n\t\t\t\tif (meta.controller) {\n\t\t\t\t\tmeta.controller.updateIndex(datasetIndex);\n\t\t\t\t} else {\n\t\t\t\t\tmeta.controller = new Chart.controllers[meta.type](me, datasetIndex);\n\t\t\t\t\tnewControllers.push(meta.controller);\n\t\t\t\t}\n\t\t\t}, me);\n\n\t\t\tif (types.length > 1) {\n\t\t\t\tfor (var i = 1; i < types.length; i++) {\n\t\t\t\t\tif (types[i] !== types[i - 1]) {\n\t\t\t\t\t\tme.isCombo = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn newControllers;\n\t\t},\n\n\t\t/**\n\t\t * Reset the elements of all datasets\n\t\t * @private\n\t\t */\n\t\tresetElements: function() {\n\t\t\tvar me = this;\n\t\t\thelpers.each(me.data.datasets, function(dataset, datasetIndex) {\n\t\t\t\tme.getDatasetMeta(datasetIndex).controller.reset();\n\t\t\t}, me);\n\t\t},\n\n\t\t/**\n\t\t* Resets the chart back to it's state before the initial animation\n\t\t*/\n\t\treset: function() {\n\t\t\tthis.resetElements();\n\t\t\tthis.tooltip.initialize();\n\t\t},\n\n\t\tupdate: function(animationDuration, lazy) {\n\t\t\tvar me = this;\n\n\t\t\tupdateConfig(me);\n\n\t\t\tif (plugins.notify(me, 'beforeUpdate') === false) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// In case the entire data object changed\n\t\t\tme.tooltip._data = me.data;\n\n\t\t\t// Make sure dataset controllers are updated and new controllers are reset\n\t\t\tvar newControllers = me.buildOrUpdateControllers();\n\n\t\t\t// Make sure all dataset controllers have correct meta data counts\n\t\t\thelpers.each(me.data.datasets, function(dataset, datasetIndex) {\n\t\t\t\tme.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements();\n\t\t\t}, me);\n\n\t\t\tme.updateLayout();\n\n\t\t\t// Can only reset the new controllers after the scales have been updated\n\t\t\thelpers.each(newControllers, function(controller) {\n\t\t\t\tcontroller.reset();\n\t\t\t});\n\n\t\t\tme.updateDatasets();\n\n\t\t\t// Do this before render so that any plugins that need final scale updates can use it\n\t\t\tplugins.notify(me, 'afterUpdate');\n\n\t\t\tif (me._bufferedRender) {\n\t\t\t\tme._bufferedRequest = {\n\t\t\t\t\tlazy: lazy,\n\t\t\t\t\tduration: animationDuration\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tme.render(animationDuration, lazy);\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Updates the chart layout unless a plugin returns `false` to the `beforeLayout`\n\t\t * hook, in which case, plugins will not be called on `afterLayout`.\n\t\t * @private\n\t\t */\n\t\tupdateLayout: function() {\n\t\t\tvar me = this;\n\n\t\t\tif (plugins.notify(me, 'beforeLayout') === false) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tChart.layoutService.update(this, this.chart.width, this.chart.height);\n\n\t\t\t/**\n\t\t\t * Provided for backward compatibility, use `afterLayout` instead.\n\t\t\t * @method IPlugin#afterScaleUpdate\n\t\t\t * @deprecated since version 2.5.0\n\t\t\t * @todo remove at version 3\n\t\t\t */\n\t\t\tplugins.notify(me, 'afterScaleUpdate');\n\t\t\tplugins.notify(me, 'afterLayout');\n\t\t},\n\n\t\t/**\n\t\t * Updates all datasets unless a plugin returns `false` to the `beforeDatasetsUpdate`\n\t\t * hook, in which case, plugins will not be called on `afterDatasetsUpdate`.\n\t\t * @private\n\t\t */\n\t\tupdateDatasets: function() {\n\t\t\tvar me = this;\n\n\t\t\tif (plugins.notify(me, 'beforeDatasetsUpdate') === false) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfor (var i = 0, ilen = me.data.datasets.length; i < ilen; ++i) {\n\t\t\t\tme.getDatasetMeta(i).controller.update();\n\t\t\t}\n\n\t\t\tplugins.notify(me, 'afterDatasetsUpdate');\n\t\t},\n\n\t\trender: function(duration, lazy) {\n\t\t\tvar me = this;\n\n\t\t\tif (plugins.notify(me, 'beforeRender') === false) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar animationOptions = me.options.animation;\n\t\t\tvar onComplete = function() {\n\t\t\t\tplugins.notify(me, 'afterRender');\n\t\t\t\tvar callback = animationOptions && animationOptions.onComplete;\n\t\t\t\tif (callback && callback.call) {\n\t\t\t\t\tcallback.call(me);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (animationOptions && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && animationOptions.duration !== 0))) {\n\t\t\t\tvar animation = new Chart.Animation();\n\t\t\t\tanimation.numSteps = (duration || animationOptions.duration) / 16.66; // 60 fps\n\t\t\t\tanimation.easing = animationOptions.easing;\n\n\t\t\t\t// render function\n\t\t\t\tanimation.render = function(chartInstance, animationObject) {\n\t\t\t\t\tvar easingFunction = helpers.easingEffects[animationObject.easing];\n\t\t\t\t\tvar stepDecimal = animationObject.currentStep / animationObject.numSteps;\n\t\t\t\t\tvar easeDecimal = easingFunction(stepDecimal);\n\n\t\t\t\t\tchartInstance.draw(easeDecimal, stepDecimal, animationObject.currentStep);\n\t\t\t\t};\n\n\t\t\t\t// user events\n\t\t\t\tanimation.onAnimationProgress = animationOptions.onProgress;\n\t\t\t\tanimation.onAnimationComplete = onComplete;\n\n\t\t\t\tChart.animationService.addAnimation(me, animation, duration, lazy);\n\t\t\t} else {\n\t\t\t\tme.draw();\n\t\t\t\tonComplete();\n\t\t\t}\n\n\t\t\treturn me;\n\t\t},\n\n\t\tdraw: function(easingValue) {\n\t\t\tvar me = this;\n\n\t\t\tme.clear();\n\n\t\t\tif (easingValue === undefined || easingValue === null) {\n\t\t\t\teasingValue = 1;\n\t\t\t}\n\n\t\t\tif (plugins.notify(me, 'beforeDraw', [easingValue]) === false) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Draw all the scales\n\t\t\thelpers.each(me.boxes, function(box) {\n\t\t\t\tbox.draw(me.chartArea);\n\t\t\t}, me);\n\n\t\t\tif (me.scale) {\n\t\t\t\tme.scale.draw();\n\t\t\t}\n\n\t\t\tme.drawDatasets(easingValue);\n\n\t\t\t// Finally draw the tooltip\n\t\t\tme.tooltip.transition(easingValue).draw();\n\n\t\t\tplugins.notify(me, 'afterDraw', [easingValue]);\n\t\t},\n\n\t\t/**\n\t\t * Draws all datasets unless a plugin returns `false` to the `beforeDatasetsDraw`\n\t\t * hook, in which case, plugins will not be called on `afterDatasetsDraw`.\n\t\t * @private\n\t\t */\n\t\tdrawDatasets: function(easingValue) {\n\t\t\tvar me = this;\n\n\t\t\tif (plugins.notify(me, 'beforeDatasetsDraw', [easingValue]) === false) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Draw each dataset via its respective controller (reversed to support proper line stacking)\n\t\t\thelpers.each(me.data.datasets, function(dataset, datasetIndex) {\n\t\t\t\tif (me.isDatasetVisible(datasetIndex)) {\n\t\t\t\t\tme.getDatasetMeta(datasetIndex).controller.draw(easingValue);\n\t\t\t\t}\n\t\t\t}, me, true);\n\n\t\t\tplugins.notify(me, 'afterDatasetsDraw', [easingValue]);\n\t\t},\n\n\t\t// Get the single element that was clicked on\n\t\t// @return : An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw\n\t\tgetElementAtEvent: function(e) {\n\t\t\treturn Chart.Interaction.modes.single(this, e);\n\t\t},\n\n\t\tgetElementsAtEvent: function(e) {\n\t\t\treturn Chart.Interaction.modes.label(this, e, {intersect: true});\n\t\t},\n\n\t\tgetElementsAtXAxis: function(e) {\n\t\t\treturn Chart.Interaction.modes['x-axis'](this, e, {intersect: true});\n\t\t},\n\n\t\tgetElementsAtEventForMode: function(e, mode, options) {\n\t\t\tvar method = Chart.Interaction.modes[mode];\n\t\t\tif (typeof method === 'function') {\n\t\t\t\treturn method(this, e, options);\n\t\t\t}\n\n\t\t\treturn [];\n\t\t},\n\n\t\tgetDatasetAtEvent: function(e) {\n\t\t\treturn Chart.Interaction.modes.dataset(this, e, {intersect: true});\n\t\t},\n\n\t\tgetDatasetMeta: function(datasetIndex) {\n\t\t\tvar me = this;\n\t\t\tvar dataset = me.data.datasets[datasetIndex];\n\t\t\tif (!dataset._meta) {\n\t\t\t\tdataset._meta = {};\n\t\t\t}\n\n\t\t\tvar meta = dataset._meta[me.id];\n\t\t\tif (!meta) {\n\t\t\t\tmeta = dataset._meta[me.id] = {\n\t\t\t\t\ttype: null,\n\t\t\t\t\tdata: [],\n\t\t\t\t\tdataset: null,\n\t\t\t\t\tcontroller: null,\n\t\t\t\t\thidden: null,\t\t\t// See isDatasetVisible() comment\n\t\t\t\t\txAxisID: null,\n\t\t\t\t\tyAxisID: null\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn meta;\n\t\t},\n\n\t\tgetVisibleDatasetCount: function() {\n\t\t\tvar count = 0;\n\t\t\tfor (var i = 0, ilen = this.data.datasets.length; i