1var YHA = YHA || {common:{}}; 2 3 4 5(function() { 6 7 YHA.common.base_url = window.base_url; 8 9 YHA.common.template_url = window.template_url; 10 11 YHA.common.lang = window.lang; 12 13 YHA.common.isMobile = (function() { 14 15 var check = false; 16 17 (function(a) { 18 19 if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) 20 21 check = true; 22 23 })(navigator.userAgent || navigator.vendor || window.opera); 24 25 return check; 26 27 })(); 28 29 30 31 YHA.common.formatDate = function(date) { 32 33 if(date instanceof Date) { 34 35 var thisDate = date; 36 37 } else { 38 39 var thisDate = new Date(date); 40 41 } 42 43 var year = thisDate.getFullYear(); 44 45 var month = thisDate.getMonth(); 46 47 var day = thisDate.getDate(); 48 49 var shortMonthsInYear = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 50 51 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; 52 53 switch(YHA.common.lang) { 54 55 case 'en': 56 57 return day + ' ' + shortMonthsInYear[month] + ' ' + year; 58 59 break; 60 61 case 'zh': 62 63 case 'sc': 64 65 return year + 'å¹´' + (month+1) + 'æ' + day + 'æ¥'; 66 67 break; 68 69 default: 70 71 return day + ' ' + shortMonthsInYear[month] + ' ' + year; 72 73 } 74 75 }; 76 77 78 79 YHA.common.popupError = function(msg) { 80 81 $.magnificPopup.open({ 82 83 items: { 84 85 src: '<div class="error-popup popup-content">' + 86 87 '<div class="table error-content">' + 88 89 '<div class="table-cell">' + 90 91 msg + 92 93 '</div>' + 94 95 '</div>' + 96 97 '<div class="btn btn-cricle btn-close" onclick="$.magnificPopup.close();">' + 98 99 '<div class="table">' + 100 101 '<div class="table-cell">' + 102 103 'OK' + 104 105 '</div>' + 106 107 '</div>' + 108 109 '</div>' + 110 111 '</div>', 112 113 type: 'inline' 114 115 }, 116 117 fixedContentPos: true 118 119 }); 120 121 } 122 123})(); 124/*! jQuery v1.11.3 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ 125 126!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.3",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);
vendor: 3,641 bytes, line 126
126return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s
vendor: 18,080 bytes, line 126
126=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\f]' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function qa(){}qa.prototype=d.filters=d.pseudos,d.setFilters=new qa,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function ra(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")}
vendor: 16,846 bytes, lines 126-130
126)||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; 127 128 129 130return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?m.queue(this[0],a):void 0===b?this:this.each(function(){var c=m.queue(this,a,b);m._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&m.dequeue(this,a)})},dequeue:function(a){return this.each(function(){m.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=m.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=m._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=["Top","Right","Bottom","Left"],U=function(a,b){return a=b||a,"none"===m.css(a,"display")||!m.contains(a.ownerDocument,a)},V=m.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===m.type(c)){e=!0;for(h in c)m.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,m.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(m(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav></:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{}
vendor: 1,726 bytes, line 130
130,e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>
vendor: 54,828 bytes, lines 130-132
130=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[m.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=Z.test(e)?this.mouseHooks:Y.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new m.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||y),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||y,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==ca()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===ca()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return m.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return m.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=m.extend(new m.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?m.event.trigger(e,null,b):m.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},m.removeEvent=y.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===K&&(a[d]=null),a.detachEvent(d,c))},m.Event=function(a,b){return this instanceof m.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?aa:ba):this.type=a,b&&m.extend(this,b),this.timeStamp=a&&a.timeStamp||m.now(),void(this[m.expando]=!0)):new m.Event(a,b)},m.Event.prototype={isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=aa,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=aa,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=aa,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},m.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){m.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!m.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.submitBubbles||(m.event.special.submit={setup:function(){return m.nodeName(this,"form")?!1:void m.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=m.nodeName(b,"input")||m.nodeName(b,"button")?b.form:void 0;c&&!m._data(c,"submitBubbles")&&(m.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),m._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&m.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return m.nodeName(this,"form")?!1:void m.event.remove(this,"._submit")}}),k.changeBubbles||(m.event.special.change={setup:function(){return X.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(m.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),m.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),m.event.simulate("change",this,a,!0)})),!1):void m.event.add(this,"beforeactivate._change",function(a){var b=a.target;X.test(b.nodeName)&&!m._data(b,"changeBubbles")&&(m.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||m.event.simulate("change",this.parentNode,a,!0)}),m._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return m.event.remove(this,"._change"),!X.test(this.nodeName)}}),k.focusinBubbles||m.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){m.event.simulate(b,a.target,m.event.fix(a),!0)};m.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=m._data(d,b);e||d.addEventListener(a,c,!0),m._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=m._data(d,b)-1;e?m._data(d,b,e):(d.removeEventListener(a,c,!0),m._removeData(d,b))}}}),m.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=ba;else if(!d)return this;return 1===e&&(g=d,d=function(a){return m().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=m.guid++)),this.each(function(){m.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,m(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=ba),this.each(function(){m.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){m.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?m.event.trigger(a,b,c,!0):void 0}});function da(a){var b=ea.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var ea="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",fa=/ jQuery\d+="(?:null|\d+)"/g,ga=new RegExp("<(?:"+ea+")[\\s/>]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/<tbody/i,la=/<|&#?\w+;/,ma=/<(?:script|style|link)/i,na=/checked\s*(?:[^=]|=\s*.checked.)/i,oa=/^$|\/(?:java|ecma)script/i,pa=/^true\/(.*)/,qa=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ra={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:k.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1></$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?"<table>"!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Ca[0].contentWindow||Ca[0].contentDocument).document,b.write(),b.close(),c=Ea(a,b),Ca.detach()),Da[a]=c),c}!function(){var a;k.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,d;return c=y.getElementsByTagName("body")[0],c&&c.style?(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(y.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(d),a):void 0}}();var Ga=/^margin/,Ha=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ia,Ja,Ka=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ia=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)},Ja=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ia(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||m.contains(a.ownerDocument,a)||(g=m.style(a,b)),Ha.test(g)&&Ga.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):y.documentElement.currentStyle&&(Ia=function(a){return a.currentStyle},Ja=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ia(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Ha.test(g)&&!Ka.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function La(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h;if(b=y.createElement("div"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=d&&d.style){c.cssText="float:left;opacity:.5",k.opacity="0.5"===c.opacity,k.cssFloat=!!c.cssFloat,b.style.backgroundClip="content-box",b.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===b.style.backgroundClip,k.boxSizing=""===c.boxSizing||""===c.MozBoxSizing||""===c.WebkitBoxSizing,m.extend(k,{reliableHiddenOffsets:function(){return null==g&&i(),g},boxSizingReliable:function(){return null==f&&i(),f},pixelPosition:function(){return null==e&&i(),e},reliableMarginRight:function(){return null==h&&i(),h}});function i(){var b,c,d,i;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),b.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",e=f=!1,h=!0,a.getComputedStyle&&(e="1%"!==(a.getComputedStyle(b,null)||{}).top,f="4px"===(a.getComputedStyle(b,null)||{width:"4px"}).width,i=b.appendChild(y.createElement("div")),i.style.cssText=b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",b.style.width="1px",h=!parseFloat((a.getComputedStyle(i,null)||{}).marginRight),b.removeChild(i)),b.innerHTML="<table><tr><td></td><td>t</td></tr></table>",i=b.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",g=0===i[0].offsetHeight,g&&(i[0].style.display="",i[1].style.display="none",g=0===i[0].offsetHeight),c.removeChild(d))}}}(),m.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Ma=/alpha\([^)]*\)/i,Na=/opacity\s*=\s*([^)]*)/,Oa=/^(none|table(?!-c[ea]).+)/,Pa=new RegExp("^("+S+")(.*)$","i"),Qa=new RegExp("^([+-])=("+S+")","i"),Ra={position:"absolute",visibility:"hidden",display:"block"},Sa={letterSpacing:"0",fontWeight:"400"},Ta=["Webkit","O","Moz","ms"];function Ua(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Ta.length;while(e--)if(b=Ta[e]+c,b in a)return b;return d}function Va(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=m._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&U(d)&&(f[g]=m._data(d,"olddisplay",Fa(d.nodeName)))):(e=U(d),(c&&"none"!==c||!e)&&m._data(d,"olddisplay",e?c:m.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Wa(a,b,c){var d=Pa.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Xa(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=m.css(a,c+T[f],!0,e)),d?("content"===c&&(g-=m.css(a,"padding"+T[f],!0,e)),"margin"!==c&&(g-=m.css(a,"border"+T[f]+"Width",!0,e))):(g+=m.css(a,"padding"+T[f],!0,e),"padding"!==c&&(g+=m.css(a,"border"+T[f]+"Width",!0,e)));return g}function Ya(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ia(a),g=k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Ja(a,b,f),(0>e||null==e)&&(e=a.style[b]),Ha.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Xa(a,b,c||(g?"border":"content"),d,f)+"px"}m.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Ja(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":k.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=m.camelCase(b),i=a.style;if(b=m.cssProps[h]||(m.cssProps[h]=Ua(i,h)),g=m.cssHooks[b]||m.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Qa.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(m.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||m.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=m.camelCase(b);return b=m.cssProps[h]||(m.cssProps[h]=Ua(a.style,h)),g=m.cssHooks[b]||m.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Ja(a,b,d)),"normal"===f&&b in Sa&&(f=Sa[b]),""===c||c?(e=parseFloat(f),c===!0||m.isNumeric(e)?e||0:f):f}}),m.each(["height","width"],function(a,b){m.cssHooks[b]={get:function(a,c,d){return c?Oa.test(m.css(a,"display"))&&0===a.offsetWidth?m.swap(a,Ra,function(){return Ya(a,b,d)}):Ya(a,b,d):void 0},set:function(a,c,d){var e=d&&Ia(a);return Wa(a,c,d?Xa(a,b,d,k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,e),e):0)}}}),k.opacity||(m.cssHooks.opacity={get:function(a,b){return Na.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=m.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===m.trim(f.replace(Ma,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Ma.test(f)?f.replace(Ma,e):f+" "+e)}}),m.cssHooks.marginRight=La(k.reliableMarginRight,function(a,b){return b?m.swap(a,{display:"inline-block"},Ja,[a,"marginRight"]):void 0}),m.each({margin:"",padding:"",border:"Width"},function(a,b){m.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+T[d]+b]=f[d]||f[d-2]||f[0];return e}},Ga.test(a)||(m.cssHooks[a+b].set=Wa)}),m.fn.extend({css:function(a,b){return V(this,function(a,b,c){var d,e,f={},g=0;if(m.isArray(b)){for(d=Ia(a),e=b.length;e>g;g++)f[b[g]]=m.css(a,b[g],!1,d);return f}return void 0!==c?m.style(a,b,c):m.css(a,b)},a,b,arguments.length>1)},show:function(){return Va(this,!0)},hide:function(){return Va(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){U(this)?m(this).show():m(this).hide()})}});function Za(a,b,c,d,e){ 131 132return new Za.prototype.init(a,b,c,d,e)}m.Tween=Za,Za.prototype={constructor:Za,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(m.cssNumber[c]?"":"px")},cur:function(){var a=Za.propHooks[this.prop];return a&&a.get?a.get(this):Za.propHooks._default.get(this)},run:function(a){var b,c=Za.propHooks[this.prop];return this.options.duration?this.pos=b=m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Za.propHooks._default.set(this),this}},Za.prototype.init.prototype=Za.prototype,Za.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Za.propHooks.scrollTop=Za.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Za.prototype.init,m.fx.step={};var $a,_a,ab=/^(?:toggle|show|hide)$/,bb=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cb=/queueHooks$/,db=[ib],eb={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bb.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bb.exec(m.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,m.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function fb(){return setTimeout(function(){$a=void 0}),$a=m.now()}function gb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hb(a,b,c){for(var d,e=(eb[b]||[]).concat(eb["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ib(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fa(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fa(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ab.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fa(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hb(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jb(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kb(a,b,c){var d,e,f=0,g=db.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$a||fb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:m.extend({},b),opts:m.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$a||fb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=m.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jb(k,j.opts.specialEasing);g>f;f++)if(d=db[f].call(j,a,k,j.opts))return d;return m.map(k,hb,j),m.isFunction(j.opts.start)&&j.opts.start.call(a,j),m.fx.timer(m.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}m.Animation=m.extend(kb,{tweener:function(a,b){m.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],eb[c]=eb[c]||[],eb[c].unshift(b)},prefilter:function(a,b){b?db.unshift(a):db.push(a)}}),m.speed=function(a,b,c){var d=a&&"object"==typeof a?m.extend({},a):{complete:c||!c&&b||m.isFunction(a)&&a,duration:a,easing:c&&b||b&&!m.isFunction(b)&&b};return d.duration=m.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in m.fx.speeds?m.fx.speeds[d.duration]:m.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){m.isFunction(d.old)&&d.old.call(this),d.queue&&m.dequeue(this,d.queue)},d},m.fn.extend({fadeTo:function(a,b,c,d){return this.filter(U).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=m.isEmptyObject(a),f=m.speed(b,c,d),g=function(){var b=kb(this,m.extend({},a),f);(e||m._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=m.timers,g=m._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&cb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&m.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=m._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=m.timers,g=d?d.length:0;for(c.finish=!0,m.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),m.each(["toggle","show","hide"],function(a,b){var c=m.fn[b];m.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gb(b,!0),a,d,e)}}),m.each({slideDown:gb("show"),slideUp:gb("hide"),slideToggle:gb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){m.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),m.timers=[],m.fx.tick=function(){var a,b=m.timers,c=0;for($a=m.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||m.fx.stop(),$a=void 0},m.fx.timer=function(a){m.timers.push(a),a()?m.fx.start():m.timers.pop()},m.fx.interval=13,m.fx.start=function(){_a||(_a=setInterval(m.fx.tick,m.fx.interval))},m.fx.stop=function(){clearInterval(_a),_a=null},m.fx.speeds={slow:600,fast:200,_default:400},m.fn.delay=function(a,b){return a=m.fx?m.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e;b=y.createElement("div"),b.setAttribute("className","t"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=y.createElement("select"),e=c.appendChild(y.createElement("option")),a=b.getElementsByTagName("input")[0],d.style.cssText="top:1px",k.getSetAttribute="t"!==b.className,k.style=/top/.test(d.getAttribute("style")),k.hrefNormalized="/a"===d.getAttribute("href"),k.checkOn=!!a.value,k.optSelected=e.selected,k.enctype=!!y.createElement("form").enctype,c.disabled=!0,k.optDisabled=!e.disabled,a=y.createElement("input"),a.setAttribute("value",""),k.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),k.radioValue="t"===a.value}();var lb=/\r/g;m.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=m.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,m(this).val()):a,null==e?e="":"number"==typeof e?e+="":m.isArray(e)&&(e=m.map(e,function(a){return null==a?"":a+""})),b=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=m.valHooks[e.type]||m.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(lb,""):null==c?"":c)}}}),m.extend({valHooks:{option:{get:function(a){var b=m.find.attr(a,"value");return null!=b?b:m.trim(m.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&m.nodeName(c.parentNode,"optgroup"))){if(b=m(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=m.makeArray(b),g=e.length;while(g--)if(d=e[g],m.inArray(m.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),m.each(["radio","checkbox"],function(){m.valHooks[this]={set:function(a,b){return m.isArray(b)?a.checked=m.inArray(m(a).val(),b)>=0:void 0}},k.checkOn||(m.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var mb,nb,ob=m.expr.attrHandle,pb=/^(?:checked|selected)$/i,qb=k.getSetAttribute,rb=k.input;m.fn.extend({attr:function(a,b){return V(this,m.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){m.removeAttr(this,a)})}}),m.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===K?m.prop(a,b,c):(1===f&&m.isXMLDoc(a)||(b=b.toLowerCase(),d=m.attrHooks[b]||(m.expr.match.bool.test(b)?nb:mb)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=m.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void m.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=m.propFix[c]||c,m.expr.match.bool.test(c)?rb&&qb||!pb.test(c)?a[d]=!1:a[m.camelCase("default-"+c)]=a[d]=!1:m.attr(a,c,""),a.removeAttribute(qb?c:d)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&m.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),nb={set:function(a,b,c){return b===!1?m.removeAttr(a,c):rb&&qb||!pb.test(c)?a.setAttribute(!qb&&m.propFix[c]||c,c):a[m.camelCase("default-"+c)]=a[c]=!0,c}},m.each(m.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ob[b]||m.find.attr;ob[b]=rb&&qb||!pb.test(b)?function(a,b,d){var e,f;return d||(f=ob[b],ob[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,ob[b]=f),e}:function(a,b,c){return c?void 0:a[m.camelCase("default-"+b)]?b.toLowerCase():null}}),rb&&qb||(m.attrHooks.value={set:function(a,b,c){return m.nodeName(a,"input")?void(a.defaultValue=b):mb&&mb.set(a,b,c)}}),qb||(mb={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},ob.id=ob.name=ob.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},m.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:mb.set},m.attrHooks.contenteditable={set:function(a,b,c){mb.set(a,""===b?!1:b,c)}},m.each(["width","height"],function(a,b){m.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),k.style||(m.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var sb=/^(?:input|select|textarea|button|object)$/i,tb=/^(?:a|area)$/i;m.fn.extend({prop:function(a,b){return V(this,m.prop,a,b,arguments.length>1)},removeProp:function(a){return a=m.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),m.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!m.isXMLDoc(a),f&&(b=m.propFix[b]||b,e=m.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=m.find.attr(a,"tabindex");return b?parseInt(b,10):sb.test(a.nodeName)||tb.test(a.nodeName)&&a.href?0:-1}}}}),k.hrefNormalized||m.each(["href","src"],function(a,b){m.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),k.optSelected||(m.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),m.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){m.propFix[this.toLowerCase()]=this}),k.enctype||(m.propFix.enctype="encoding");var ub=/[\t\r\n\f]/g;m.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ub," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=m.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ub," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?m.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(m.isFunction(a)?function(c){m(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=m(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===K||"boolean"===c)&&(this.className&&m._data(this,"__className__",this.className),this.className=this.className||a===!1?"":m._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ub," ").indexOf(b)>=0)return!0;return!1}}),m.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){m.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),m.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var vb=m.now(),wb=/\?/,xb=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;m.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=m.trim(b+"");return e&&!m.trim(e.replace(xb,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():m.error("Invalid JSON: "+b)},m.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||m.error("Invalid XML: "+b),c};var yb,zb,Ab=/#.*$/,Bb=/([?&])_=[^&]*/,Cb=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Db=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Eb=/^(?:GET|HEAD)$/,Fb=/^\/\//,Gb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Hb={},Ib={},Jb="*/".concat("*");try{zb=location.href}catch(Kb){zb=y.createElement("a"),zb.href="",zb=zb.href}yb=Gb.exec(zb.toLowerCase())||[];function Lb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(m.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Mb(a,b,c,d){var e={},f=a===Ib;function g(h){var i;return e[h]=!0,m.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Nb(a,b){var c,d,e=m.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&m.extend(!0,a,c),a}function Ob(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Pb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}m.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:zb,type:"GET",isLocal:Db.test(yb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Jb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":m.parseJSON,"text xml":m.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Nb(Nb(a,m.ajaxSettings),b):Nb(m.ajaxSettings,a)},ajaxPrefilter:Lb(Hb),ajaxTransport:Lb(Ib),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=m.ajaxSetup({},b),l=k.context||k,n=k.context&&(l.nodeType||l.jquery)?m(l):m.event,o=m.Deferred(),p=m.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Cb.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||zb)+"").replace(Ab,"").replace(Fb,yb[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=m.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(c=Gb.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===yb[1]&&c[2]===yb[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(yb[3]||("http:"===yb[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=m.param(k.data,k.traditional)),Mb(Hb,k,b,v),2===t)return v;h=m.event&&k.global,h&&0===m.active++&&m.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Eb.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(wb.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Bb.test(e)?e.replace(Bb,"$1_="+vb++):e+(wb.test(e)?"&":"?")+"_="+vb++)),k.ifModified&&(m.lastModified[e]&&v.setRequestHeader("If-Modified-Since",m.lastModified[e]),m.etag[e]&&v.setRequestHeader("If-None-Match",m.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Jb+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Mb(Ib,k,b,v)){v.readyState=1,h&&n.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Ob(k,v,c)),u=Pb(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(m.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(m.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&n.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(n.trigger("ajaxComplete",[v,k]),--m.active||m.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return m.get(a,b,c,"json")},getScript:function(a,b){return m.get(a,void 0,b,"script")}}),m.each(["get","post"],function(a,b){m[b]=function(a,c,d,e){return m.isFunction(c)&&(e=e||d,d=c,c=void 0),m.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),m._evalUrl=function(a){return m.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},m.fn.extend({wrapAll:function(a){if(m.isFunction(a))return this.each(function(b){m(this).wrapAll(a.call(this,b))});if(this[0]){var b=m(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(m.isFunction(a)?function(b){m(this).wrapInner(a.call(this,b))}:function(){var b=m(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=m.isFunction(a);return this.each(function(c){m(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){m.nodeName(this,"body")||m(this).replaceWith(this.childNodes)}).end()}}),m.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!k.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||m.css(a,"display"))},m.expr.filters.visible=function(a){return!m.expr.filters.hidden(a)};var Qb=/%20/g,Rb=/\[\]$/,Sb=/\r?\n/g,Tb=/^(?:submit|button|image|reset|file)$/i,Ub=/^(?:input|select|textarea|keygen)/i;function Vb(a,b,c,d){var e;if(m.isArray(b))m.each(b,function(b,e){c||Rb.test(a)?d(a,e):Vb(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==m.type(b))d(a,b);else for(e in b)Vb(a+"["+e+"]",b[e],c,d)}m.param=function(a,b){var c,d=[],e=function(a,b){b=m.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=m.ajaxSettings&&m.ajaxSettings.traditional),m.isArray(a)||a.jquery&&!m.isPlainObject(a))m.each(a,function(){e(this.name,this.value)});else for(c in a)Vb(c,a[c],b,e);return d.join("&").replace(Qb,"+")},m.fn.extend({serialize:function(){return m.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=m.prop(this,"elements");return a?m.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!m(this).is(":disabled")&&Ub.test(this.nodeName)&&!Tb.test(a)&&(this.checked||!W.test(a))}).map(function(a,b){var c=m(this).val();return null==c?null:m.isArray(c)?m.map(c,function(a){return{name:b.name,value:a.replace(Sb,"\r\n")}}):{name:b.name,value:c.replace(Sb,"\r\n")}}).get()}}),m.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&Zb()||$b()}:Zb;var Wb=0,Xb={},Yb=m.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Xb)Xb[a](void 0,!0)}),k.cors=!!Yb&&"withCredentials"in Yb,Yb=k.ajax=!!Yb,Yb&&m.ajaxTransport(function(a){if(!a.crossDomain||k.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Wb;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Xb[g],b=void 0,f.onreadystatechange=m.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Xb[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function Zb(){try{return new a.XMLHttpRequest}catch(b){}}function $b(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}m.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return m.globalEval(a),a}}}),m.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),m.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=y.head||m("head")[0]||y.documentElement;return{send:function(d,e){b=y.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var _b=[],ac=/(=)\?(?=&|$)|\?\?/;m.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=_b.pop()||m.expando+"_"+vb++;return this[a]=!0,a}}),m.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(ac.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&ac.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=m.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(ac,"$1"+e):b.jsonp!==!1&&(b.url+=(wb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||m.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,_b.push(e)),g&&m.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),m.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||y;var d=u.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=m.buildFragment([a],b,e),e&&e.length&&m(e).remove(),m.merge([],d.childNodes))};var bc=m.fn.load;m.fn.load=function(a,b,c){if("string"!=typeof a&&bc)return bc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=m.trim(a.slice(h,a.length)),a=a.slice(0,h)),m.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&m.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?m("<div>").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cc=a.document.documentElement;function dc(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cc;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cc})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=La(k.pixelPosition,function(a,c){return c?(c=Ja(a,b),Ha.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ec=a.jQuery,fc=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fc),b&&a.jQuery===m&&(a.jQuery=ec),m},typeof b===K&&(a.jQuery=a.$=m),m});
vendor: 5,831 bytes, lines 133-444
133 134 135// Sticky Plugin v1.0.3 for jQuery 136 137// ============= 138 139// Author: Anthony Garand 140 141// Improvements by German M. Bravo (Kronuz) and Ruud Kamphuis (ruudk) 142 143// Improvements by Leonardo C. Daronco (daronco) 144 145// Created: 02/14/2011 146 147// Date: 07/20/2015 148 149// Website: http://stickyjs.com/ 150 151// Description: Makes an element on the page stick on the screen as you scroll 152 153// It will only set the 'top' and 'position' of your element, you 154 155// might need to adjust the width in some cases. 156 157 158 159(function (factory) { 160 161 if (typeof define === 'function' && define.amd) { 162 163 // AMD. Register as an anonymous module. 164 165 define(['jquery'], factory); 166 167 } else if (typeof module === 'object' && module.exports) { 168 169 // Node/CommonJS 170 171 module.exports = factory(require('jquery')); 172 173 } else { 174 175 // Browser globals 176 177 factory(jQuery); 178 179 } 180 181}(function ($) { 182 183 var slice = Array.prototype.slice; // save ref to original slice() 184 185 var splice = Array.prototype.splice; // save ref to original slice() 186 187 188 189 var defaults = { 190 191 topSpacing: 0, 192 193 bottomSpacing: 0, 194 195 className: 'is-sticky', 196 197 wrapperClassName: 'sticky-wrapper', 198 199 center: false, 200 201 getWidthFrom: '', 202 203 widthFromWrapper: true, // works only when .getWidthFrom is empty 204 205 responsiveWidth: false 206 207 }, 208 209 $window = $(window), 210 211 $document = $(document), 212 213 sticked = [], 214 215 windowHeight = $window.height(), 216 217 scroller = function() { 218 219 var scrollTop = $window.scrollTop(), 220 221 documentHeight = $document.height(), 222 223 dwh = documentHeight - windowHeight, 224 225 extra = (scrollTop > dwh) ? dwh - scrollTop : 0; 226 227 228 229 for (var i = 0, l = sticked.length; i < l; i++) { 230 231 var s = sticked[i], 232 233 elementTop = s.stickyWrapper.offset().top, 234 235 etse = elementTop - s.topSpacing - extra; 236 237 238 239 //update height in case of dynamic content 240 241 s.stickyWrapper.css('height', s.stickyElement.outerHeight()); 242 243 244 245 if (scrollTop <= etse) { 246 247 if (s.currentTop !== null) { 248 249 s.stickyElement 250 251 .css({ 252 253 'width': '', 254 255 'position': '', 256 257 'top': '' 258 259 }); 260 261 s.stickyElement.parent().removeClass(s.className); 262 263 s.stickyElement.trigger('sticky-end', [s]); 264 265 s.currentTop = null; 266 267 } 268 269 } 270 271 else { 272 273 var newTop = documentHeight - s.stickyElement.outerHeight() 274 275 - s.topSpacing - s.bottomSpacing - scrollTop - extra; 276 277 if (newTop < 0) { 278 279 newTop = newTop + s.topSpacing; 280 281 } else { 282 283 newTop = s.topSpacing; 284 285 } 286 287 if (s.currentTop !== newTop) { 288 289 var newWidth; 290 291 if (s.getWidthFrom) { 292 293 newWidth = $(s.getWidthFrom).width() || null; 294 295 } else if (s.widthFromWrapper) { 296 297 newWidth = s.stickyWrapper.width(); 298 299 } 300 301 if (newWidth == null) { 302 303 newWidth = s.stickyElement.width(); 304 305 } 306 307 s.stickyElement 308 309 .css('width', newWidth) 310 311 .css('position', 'fixed') 312 313 .css('top', newTop); 314 315 316 317 s.stickyElement.parent().addClass(s.className); 318 319 320 321 if (s.currentTop === null) { 322 323 s.stickyElement.trigger('sticky-start', [s]); 324 325 } else { 326 327 // sticky is started but it have to be repositioned 328 329 s.stickyElement.trigger('sticky-update', [s]); 330 331 } 332 333 334 335 if (s.currentTop === s.topSpacing && s.currentTop > newTop || s.currentTop === null && newTop < s.topSpacing) { 336 337 // just reached bottom || just started to stick but bottom is already reached 338 339 s.stickyElement.trigger('sticky-bottom-reached', [s]); 340 341 } else if(s.currentTop !== null && newTop === s.topSpacing && s.currentTop < newTop) { 342 343 // sticky is started && sticked at topSpacing && overflowing from top just finished 344 345 s.stickyElement.trigger('sticky-bottom-unreached', [s]); 346 347 } 348 349 350 351 s.currentTop = newTop; 352 353 } 354 355 356 357 // Check if sticky has reached end of container and stop sticking 358 359 var stickyWrapperContainer = s.stickyWrapper.parent(); 360 361 var unstick = (s.stickyElement.offset().top + s.stickyElement.outerHeight() >= stickyWrapperContainer.offset().top + stickyWrapperContainer.outerHeight()) && (s.stickyElement.offset().top <= s.topSpacing); 362 363 364 365 if( unstick ) { 366 367 s.stickyElement 368 369 .css('position', 'absolute') 370 371 .css('top', '') 372 373 .css('bottom', 0); 374 375 } else { 376 377 s.stickyElement 378 379 .css('position', 'fixed') 380 381 .css('top', newTop) 382 383 .css('bottom', ''); 384 385 } 386 387 } 388 389 } 390 391 }, 392 393 resizer = function() { 394 395 windowHeight = $window.height(); 396 397 398 399 for (var i = 0, l = sticked.length; i < l; i++) { 400 401 var s = sticked[i]; 402 403 var newWidth = null; 404 405 if (s.getWidthFrom) { 406 407 if (s.responsiveWidth) { 408 409 newWidth = $(s.getWidthFrom).width(); 410 411 } 412 413 } else if(s.widthFromWrapper) { 414 415 newWidth = s.stickyWrapper.width(); 416 417 } 418 419 if (newWidth != null) { 420 421 s.stickyElement.css('width', newWidth); 422 423 } 424 425 } 426 427 }, 428 429 methods = { 430 431 init: function(options) { 432 433 var o = $.extend({}, defaults, options); 434 435 return this.each(function() { 436 437 var stickyElement = $(this); 438 439 440 441 var stickyId = stickyElement.attr('id'); 442 443 var wrapperId = stickyId ? stickyId + '-' + defaults.wrapperClassName : defaults.wrapperClassName; 444
445 var wrapper = $('<div></div>') 446 447 .attr('id', wrapperId) 448 449 .addClass(o.wrapperClassName); 450 451 452 453 stickyElement.wrapAll(wrapper); 454 455 456 457 var stickyWrapper = stickyElement.parent(); 458 459 460 461 if (o.center) { 462 463 stickyWrapper.css({width:stickyElement.outerWidth(),marginLeft:"auto",marginRight:"auto"}); 464 465 } 466 467 468 469 if (stickyElement.css("float") === "right") { 470 471 stickyElement.css({"float":"none"}).parent().css({"float":"right"}); 472 473 } 474 475 476 477 o.stickyElement = stickyElement; 478 479 o.stickyWrapper = stickyWrapper; 480 481 o.currentTop = null; 482 483 484 485 sticked.push(o); 486 487 488 489 methods.setWrapperHeight(this); 490 491 methods.setupChangeListeners(this); 492 493 }); 494 495 }, 496 497 498 499 setWrapperHeight: function(stickyElement) { 500 501 var element = $(stickyElement); 502 503 var stickyWrapper = element.parent(); 504 505 if (stickyWrapper) { 506 507 stickyWrapper.css('height', element.outerHeight()); 508 509 } 510 511 }, 512 513 514 515 setupChangeListeners: function(stickyElement) { 516 517 if (window.MutationObserver) { 518 519 var mutationObserver = new window.MutationObserver(function(mutations) { 520 521 if (mutations[0].addedNodes.length || mutations[0].removedNodes.length) { 522 523 methods.setWrapperHeight(stickyElement); 524 525 } 526 527 }); 528 529 mutationObserver.observe(stickyElement, {subtree: true, childList: true}); 530 531 } else { 532 533 stickyElement.addEventListener('DOMNodeInserted', function() { 534 535 methods.setWrapperHeight(stickyElement); 536 537 }, false); 538 539 stickyElement.addEventListener('DOMNodeRemoved', function() { 540 541 methods.setWrapperHeight(stickyElement); 542 543 }, false); 544 545 } 546 547 }, 548 549 update: scroller, 550 551 unstick: function(options) { 552 553 return this.each(function() { 554 555 var that = this; 556 557 var unstickyElement = $(that); 558 559 560 561 var removeIdx = -1; 562 563 var i = sticked.length; 564 565 while (i-- > 0) { 566 567 if (sticked[i].stickyElement.get(0) === that) { 568 569 splice.call(sticked,i,1); 570 571 removeIdx = i; 572 573 } 574 575 } 576 577 if(removeIdx !== -1) { 578 579 unstickyElement.unwrap(); 580 581 unstickyElement 582 583 .css({ 584 585 'width': '', 586 587 'position': '', 588 589 'top': '', 590 591 'float': '' 592 593 }) 594 595 ; 596 597 } 598 599 }); 600 601 } 602 603 }; 604 605 606 607 // should be more efficient than using $window.scroll(scroller) and $window.resize(resizer): 608 609 if (window.addEventListener) { 610 611 window.addEventListener('scroll', scroller, false); 612 613 window.addEventListener('resize', resizer, false); 614 615 } else if (window.attachEvent) { 616 617 window.attachEvent('onscroll', scroller); 618 619 window.attachEvent('onresize', resizer); 620 621 } 622 623 624 625 $.fn.sticky = function(method) { 626 627 if (methods[method]) { 628 629 return methods[method].apply(this, slice.call(arguments, 1)); 630 631 } else if (typeof method === 'object' || !method ) { 632 633 return methods.init.apply( this, arguments ); 634 635 } else { 636 637 $.error('Method ' + method + ' does not exist on jQuery.sticky'); 638 639 } 640 641 }; 642 643 644 645 $.fn.unstick = function(method) { 646 647 if (methods[method]) { 648 649 return methods[method].apply(this, slice.call(arguments, 1)); 650 651 } else if (typeof method === 'object' || !method ) { 652 653 return methods.unstick.apply( this, arguments ); 654 655 } else { 656 657 $.error('Method ' + method + ' does not exist on jQuery.sticky'); 658 659 } 660 661 }; 662 663 $(function() { 664 665 setTimeout(scroller, 0); 666 667 }); 668 669})); 670 671 672/*! 673 674 * Modernizr v2.8.3 675 676 * www.modernizr.com 677 678 * 679 680 * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton 681 682 * Available under the BSD and MIT licenses: www.modernizr.com/license/ 683 684 */ 685 686window.Modernizr=function(a,b,c){function d(a){t.cssText=a}function e(a,b){return d(x.join(a+";")+(b||""))}function f(a,b){return typeof a===b}function g(a,b){return!!~(""+a).indexOf(b)}function h(a,b){for(var d in a){var e=a[d];if(!g(e,"-")&&t[e]!==c)return"pfx"==b?e:!0}return!1}function i(a,b,d){for(var e in a){var g=b[a[e]];if(g!==c)return d===!1?a[e]:f(g,"function")?g.bind(d||b):g}return!1}function j(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+z.join(d+" ")+d).split(" ");return f(b,"string")||f(b,"undefined")?h(e,b):(e=(a+" "+A.join(d+" ")+d).split(" "),i(e,b,c))}function k(){o.input=function(c){for(var d=0,e=c.length;e>d;d++)E[c[d]]=!!(c[d]in u);return E.list&&(E.list=!(!b.createElement("datalist")||!a.HTMLDataListElement)),E}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),o.inputtypes=function(a){for(var d,e,f,g=0,h=a.length;h>g;g++)u.setAttribute("type",e=a[g]),d="text"!==u.type,d&&(u.value=v,u.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(e)&&u.style.WebkitAppearance!==c?(q.appendChild(u),f=b.defaultView,d=f.getComputedStyle&&"textfield"!==f.getComputedStyle(u,null).WebkitAppearance&&0!==u.offsetHeight,q.removeChild(u)):/^(search|tel)$/.test(e)||(d=/^(url|email)$/.test(e)?u.checkValidity&&u.checkValidity()===!1:u.value!=v)),D[a[g]]=!!d;return D}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var l,m,n="2.8.3",o={},p=!0,q=b.documentElement,r="modernizr",s=b.createElement(r),t=s.style,u=b.createElement("input"),v=":)",w={}.toString,x=" -webkit- -moz- -o- -ms- ".split(" "),y="Webkit Moz O ms",z=y.split(" "),A=y.toLowerCase().split(" "),B={svg:"http://www.w3.org/2000/svg"},C={},D={},E={},F=[],G=F.slice,H=function(a,c,d,e){var f,g,h,i,j=b.createElement("div"),k=b.body,l=k||b.createElement("body");if(parseInt(d,10))for(;d--;)h=b.createElement("div"),h.id=e?e[d]:r+(d+1),j.appendChild(h);return f=["­",'<style id="s',r,'">',a,"</style>"].join(""),j.id=r,(k?j:l).innerHTML+=f,l.appendChild(j),k||(l.style.background="",l.style.overflow="hidden",i=q.style.overflow,q.style.overflow="hidden",q.appendChild(l)),g=c(j,a),k?j.parentNode.removeChild(j):(l.parentNode.removeChild(l),q.style.overflow=i),!!g},I=function(b){var c=a.matchMedia||a.msMatchMedia;
vendor: 9,226 bytes, lines 686-699
686if(c)return c(b)&&c(b).matches||!1;var d;return H("@media "+b+" { #"+r+" { position: absolute; } }",function(b){d="absolute"==(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).position}),d},J=function(){function a(a,e){e=e||b.createElement(d[a]||"div"),a="on"+a;var g=a in e;return g||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(a,""),g=f(e[a],"function"),f(e[a],"undefined")||(e[a]=c),e.removeAttribute(a))),e=null,g}var d={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return a}(),K={}.hasOwnProperty;m=f(K,"undefined")||f(K.call,"undefined")?function(a,b){return b in a&&f(a.constructor.prototype[b],"undefined")}:function(a,b){return K.call(a,b)},Function.prototype.bind||(Function.prototype.bind=function(a){var b=this;if("function"!=typeof b)throw new TypeError;var c=G.call(arguments,1),d=function(){if(this instanceof d){var e=function(){};e.prototype=b.prototype;var f=new e,g=b.apply(f,c.concat(G.call(arguments)));return Object(g)===g?g:f}return b.apply(a,c.concat(G.call(arguments)))};return d}),C.flexbox=function(){return j("flexWrap")},C.flexboxlegacy=function(){return j("boxDirection")},C.canvas=function(){var a=b.createElement("canvas");return!(!a.getContext||!a.getContext("2d"))},C.canvastext=function(){return!(!o.canvas||!f(b.createElement("canvas").getContext("2d").fillText,"function"))},C.webgl=function(){return!!a.WebGLRenderingContext},C.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:H(["@media (",x.join("touch-enabled),("),r,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=9===a.offsetTop}),c},C.geolocation=function(){return"geolocation"in navigator},C.postmessage=function(){return!!a.postMessage},C.websqldatabase=function(){return!!a.openDatabase},C.indexedDB=function(){return!!j("indexedDB",a)},C.hashchange=function(){return J("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},C.history=function(){return!(!a.history||!history.pushState)},C.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},C.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},C.rgba=function(){return d("background-color:rgba(150,255,150,.5)"),g(t.backgroundColor,"rgba")},C.hsla=function(){return d("background-color:hsla(120,40%,100%,.5)"),g(t.backgroundColor,"rgba")||g(t.backgroundColor,"hsla")},C.multiplebgs=function(){return d("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(t.background)},C.backgroundsize=function(){return j("backgroundSize")},C.borderimage=function(){return j("borderImage")},C.borderradius=function(){return j("borderRadius")},C.boxshadow=function(){return j("boxShadow")},C.textshadow=function(){return""===b.createElement("div").style.textShadow},C.opacity=function(){return e("opacity:.55"),/^0.55$/.test(t.opacity)},C.cssanimations=function(){return j("animationName")},C.csscolumns=function(){return j("columnCount")},C.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return d((a+"-webkit- ".split(" ").join(b+a)+x.join(c+a)).slice(0,-a.length)),g(t.backgroundImage,"gradient")},C.cssreflections=function(){return j("boxReflect")},C.csstransforms=function(){return!!j("transform")},C.csstransforms3d=function(){var a=!!j("perspective");return a&&"webkitPerspective"in q.style&&H("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=9===b.offsetLeft&&3===b.offsetHeight}),a},C.csstransitions=function(){return j("transition")},C.fontface=function(){var a;return H('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&0===g.indexOf(d.split(" ")[0])}),a},C.generatedcontent=function(){var a;return H(["#",r,"{font:0/0 a}#",r,':after{content:"',v,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},C.video=function(){var a=b.createElement("video"),c=!1;try{(c=!!a.canPlayType)&&(c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,""))}catch(d){}return c},C.audio=function(){var a=b.createElement("audio"),c=!1;try{(c=!!a.canPlayType)&&(c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,""))}catch(d){}return c},C.localstorage=function(){try{return localStorage.setItem(r,r),localStorage.removeItem(r),!0}catch(a){return!1}},C.sessionstorage=function(){try{return sessionStorage.setItem(r,r),sessionStorage.removeItem(r),!0}catch(a){return!1}},C.webworkers=function(){return!!a.Worker},C.applicationcache=function(){return!!a.applicationCache},C.svg=function(){return!!b.createElementNS&&!!b.createElementNS(B.svg,"svg").createSVGRect},C.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="<svg/>",(a.firstChild&&a.firstChild.namespaceURI)==B.svg},C.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(w.call(b.createElementNS(B.svg,"animate")))},C.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(w.call(b.createElementNS(B.svg,"clipPath")))};for(var L in C)m(C,L)&&(l=L.toLowerCase(),o[l]=C[L](),F.push((o[l]?"":"no-")+l));return o.input||k(),o.addTest=function(a,b){if("object"==typeof a)for(var d in a)m(a,d)&&o.addTest(d,a[d]);else{if(a=a.toLowerCase(),o[a]!==c)return o;b="function"==typeof b?b():b,"undefined"!=typeof p&&p&&(q.className+=" "+(b?"":"no-")+a),o[a]=b}return o},d(""),s=u=null,function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=s.elements;return"string"==typeof a?a.split(" "):a}function e(a){var b=r[a[p]];return b||(b={},q++,a[p]=q,r[q]=b),b}function f(a,c,d){if(c||(c=b),k)return c.createElement(a);d||(d=e(c));var f;return f=d.cache[a]?d.cache[a].cloneNode():o.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!f.canHaveChildren||n.test(a)||f.tagUrn?f:d.frag.appendChild(f)}function g(a,c){if(a||(a=b),k)return a.createDocumentFragment();c=c||e(a);for(var f=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)f.createElement(h[g]);return f}function h(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return s.shivMethods?f(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(s,b.frag)}function i(a){a||(a=b);var d=e(a);return!s.shivCSS||j||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),k||h(a,d),a}var j,k,l="3.7.0",m=a.html5||{},n=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,o=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,p="_html5shiv",q=0,r={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",j="hidden"in a,k=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){j=!0,k=!0}}();var s={elements:m.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:l,shivCSS:m.shivCSS!==!1,supportsUnknownElements:k,shivMethods:m.shivMethods!==!1,type:"default",shivDocument:i,createElement:f,createDocumentFragment:g};a.html5=s,i(b)}(this,b),o._version=n,o._prefixes=x,o._domPrefixes=A,o._cssomPrefixes=z,o.mq=I,o.hasEvent=J,o.testProp=function(a){return h([a])},o.testAllProps=j,o.testStyles=H,o.prefixed=function(a,b,c){return b?j(a,b,c):j(a,"pfx")},q.className=q.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(p?" js "+F.join(" "):""),o}(this,this.document); 687 688 689//! moment.js 690 691//! version : 2.9.0 692 693//! authors : Tim Wood, Iskren Chernev, Moment.js contributors 694 695//! license : MIT 696 697//! momentjs.com 698 699(function(a){function b(a,b,c){switch(arguments.length){case 2:return null!=a?a:b;case 3:return null!=a?a:null!=b?b:c;default:throw new Error("Implement me")}}function c(a,b){return Bb.call(a,b)}function d(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invali
699dFormat:!1,userInvalidated:!1,iso:!1}}function e(a){vb.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+a)}function f(a,b){var c=!0;return o(function(){return c&&(e(a),c=!1),b.apply(this,arguments)},b)}function g(a,b){sc[a]||(e(b),sc[a]=!0)}function h(a,b){return function(c){return r(a.call(this,c),b)}}function i(a,b){return function(c){return this.localeData().ordinal(a.call(this,c),b)}}function j(a,b){var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),f=a.clone().add(e,"months");return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)}function k(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function l(){}function m(a,b){b!==!1&&H(a),p(this,a),this._d=new Date(+a._d),uc===!1&&(uc=!0,vb.updateOffset(this),uc=!1)}function n(a){var b=A(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;this._milliseconds=+k+1e3*j+6e4*i+36e5*h,this._days=+g+7*f,this._months=+e+3*d+12*c,this._data={},this._locale=vb.localeData(),this._bubble()}function o(a,b){for(var d in b)c(b,d)&&(a[d]=b[d]);return c(b,"toString")&&(a.toString=b.toString),c(b,"valueOf")&&(a.valueOf=b.valueOf),a}function p(a,b){var c,d,e;if("undefined"!=typeof b._isAMomentObject&&(a._isAMomentObject=b._isAMomentObject),"undefined"!=typeof b._i&&(a._i=b._i),"undefined"!=typeof b._f&&(a._f=b._f),"undefined"!=typeof b._l&&(a._l=b._l),"undefined"!=typeof b._strict&&(a._strict=b._strict),"undefined"!=typeof b._tzm&&(a._tzm=b._tzm),"undefined"!=typeof b._isUTC&&(a._isUTC=b._isUTC),"undefined"!=typeof b._offset&&(a._offset=b._offset),"undefined"!=typeof b._pf&&(a._pf=b._pf),"undefined"!=typeof b._locale&&(a._locale=b._locale),Kb.length>0)for(c in Kb)d=Kb[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function q(a){return 0>a?Math.ceil(a):Math.floor(a)}function r(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.length<b;)d="0"+d;return(e?c?"+":"":"-")+d}function s(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function t(a,b){var c;return b=M(b,a),a.isBefore(b)?c=s(a,b):(c=s(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c}function u(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||(g(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=vb.duration(c,d),v(this,e,a),this}}function v(a,b,c,d){var e=b._milliseconds,f=b._days,g=b._months;d=null==d?!0:d,e&&a._d.setTime(+a._d+e*c),f&&pb(a,"Date",ob(a,"Date")+f*c),g&&nb(a,ob(a,"Month")+g*c),d&&vb.updateOffset(a,f||g)}function w(a){return"[object Array]"===Object.prototype.toString.call(a)}function x(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function y(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&C(a[d])!==C(b[d]))&&g++;return g+f}function z(a){if(a){var b=a.toLowerCase().replace(/(.)s$/,"$1");a=lc[a]||mc[b]||b}return a}function A(a){var b,d,e={};for(d in a)c(a,d)&&(b=z(d),b&&(e[b]=a[d]));return e}function B(b){var c,d;if(0===b.indexOf("week"))c=7,d="day";else{if(0!==b.indexOf("month"))return;c=12,d="month"}vb[b]=function(e,f){var g,h,i=vb._locale[b],j=[];if("number"==typeof e&&(f=e,e=a),h=function(a){var b=vb().utc().set(d,a);return i.call(vb._locale,b,e||"")},null!=f)return h(f);for(g=0;c>g;g++)j.push(h(g));return j}}function C(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function D(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function E(a,b,c){return jb(vb([a,11,31+b-c]),b,c).week}function F(a){return G(a)?366:365}function G(a){return a%4===0&&a%100!==0||a%400===0}function H(a){var b;a._a&&-2===a._pf.overflow&&(b=a._a[Db]<0||a._a[Db]>11?Db:a._a[Eb]<1||a._a[Eb]>D(a._a[Cb],a._a[Db])?Eb:a._a[Fb]<0||a._a[Fb]>24||24===a._a[Fb]&&(0!==a._a[Gb]||0!==a._a[Hb]||0!==a._a[Ib])?Fb:a._a[Gb]<0||a._a[Gb]>59?Gb:a._a[Hb]<0||a._a[Hb]>59?Hb:a._a[Ib]<0||a._a[Ib]>999?Ib:-1,a._pf._overflowDayOfYear&&(Cb>b||b>Eb)&&(b=Eb),a._pf.overflow=b)}
699function I(b){return null==b._isValid&&(b._isValid=!isNaN(b._d.getTime())&&b._pf.overflow<0&&!b._pf.empty&&!b._pf.invalidMonth&&!b._pf.nullInput&&!b._pf.invalidFormat&&!b._pf.userInvalidated,b._strict&&(b._isValid=b._isValid&&0===b._pf.charsLeftOver&&0===b._pf.unusedTokens.length&&b._pf.bigHour===a)),b._isValid}function J(a){return a?a.toLowerCase().replace("_","-"):a}function K(a){for(var b,c,d,e,f=0;f<a.length;){for(e=J(a[f]).split("-"),b=e.length,c=J(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=L(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&y(e,c,!0)>=b-1)break;b--}f++}return null}function L(a){var b=null;if(!Jb[a]&&Lb)try{b=vb.locale(),require("./locale/"+a),vb.locale(b)}catch(c){}return Jb[a]}function M(a,b){var c,d;return b._isUTC?(c=b.clone(),d=(vb.isMoment(a)||x(a)?+a:+vb(a))-+c,c._d.setTime(+c._d+d),vb.updateOffset(c,!1),c):vb(a).local()}function N(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function O(a){var b,c,d=a.match(Pb);for(b=0,c=d.length;c>b;b++)d[b]=rc[d[b]]?rc[d[b]]:N(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function P(a,b){return a.isValid()?(b=Q(b,a.localeData()),nc[b]||(nc[b]=O(b)),nc[b](a)):a.localeData().invalidDate()}function Q(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Qb.lastIndex=0;d>=0&&Qb.test(a);)a=a.replace(Qb,c),Qb.lastIndex=0,d-=1;return a}function R(a,b){var c,d=b._strict;switch(a){case"Q":return _b;case"DDDD":return bc;case"YYYY":case"GGGG":case"gggg":return d?cc:Tb;case"Y":case"G":case"g":return ec;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return d?dc:Ub;case"S":if(d)return _b;case"SS":if(d)return ac;case"SSS":if(d)return bc;case"DDD":return Sb;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Wb;case"a":case"A":return b._locale._meridiemParse;case"x":return Zb;case"X":return $b;case"Z":case"ZZ":return Xb;case"T":return Yb;case"SSSS":return Vb;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return d?ac:Rb;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return Rb;case"Do":return d?b._locale._ordinalParse:b._locale._ordinalParseLenient;default:return c=new RegExp($(Z(a.replace("\\","")),"i"))}}function S(a){a=a||"";var b=a.match(Xb)||[],c=b[b.length-1]||[],d=(c+"").match(jc)||["-",0,0],e=+(60*d[1])+C(d[2]);return"+"===d[0]?e:-e}function T(a,b,c){var d,e=c._a;switch(a){case"Q":null!=b&&(e[Db]=3*(C(b)-1));break;case"M":case"MM":null!=b&&(e[Db]=C(b)-1);break;case"MMM":case"MMMM":d=c._locale.monthsParse(b,a,c._strict),null!=d?e[Db]=d:c._pf.invalidMonth=b;break;case"D":case"DD":null!=b&&(e[Eb]=C(b));break;case"Do":null!=b&&(e[Eb]=C(parseInt(b.match(/\d{1,2}/)[0],10)));break;case"DDD":case"DDDD":null!=b&&(c._dayOfYear=C(b));break;case"YY":e[Cb]=vb.parseTwoDigitYear(b);break;case"YYYY":case"YYYYY":case"YYYYYY":e[Cb]=C(b);break;case"a":case"A":c._meridiem=b;break;case"h":case"hh":c._pf.bigHour=!0;case"H":case"HH":e[Fb]=C(b);break;case"m":case"mm":e[Gb]=C(b);break;case"s":case"ss":e[Hb]=C(b);break;case"S":case"SS":case"SSS":case"SSSS":e[Ib]=C(1e3*("0."+b));break;case"x":c._d=new Date(C(b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=S(b);break;case"dd":case"ddd":case"dddd":d=c._locale.weekdaysParse(b),null!=d?(c._w=c._w||{},c._w.d=d):c._pf.invalidWeekday=b;break;case"w":case"ww":case"W":case"WW":case"d":case"e":case"E":a=a.substr(0,1);case"gggg":case"GGGG":case"GGGGG":a=a.substr(0,2),b&&(c._w=c._w||{},c._w[a]=C(b));break;case"gg":case"GG":c._w=c._w||{},c._w[a]=vb.parseTwoDigitYear(b)}}function U(a){var c,d,e,f,g,h,i;c=a._w,null!=c.GG||null!=c.W||null!=c.E?(g=1,h=4,d=b(c.GG,a._a[Cb],jb(vb(),1,4).year),e=b(c.W,1),f=b(c.E,1)):(g=a._locale._week.dow,h=a._locale._week.doy,d=b(c.gg,a._a[Cb],jb(vb(),g,h).year),e=b(c.w,1),null!=c.d?(f=c.d,g>f&&++e):f=null!=c.e?c.e+g:g),i=kb(d,e,f,h,g),a._a[Cb]=i.year,a._dayOfYear=i.dayOfYear}function V(a){var c,d,e,f,g=[];if(!a._d){for(e=X(a),a._w&&null==a._a[Eb]&&null==a._a[Db]&&U(a),a._dayOfYear&&(f=b(a._a[Cb],e[Cb]),a._dayOfYear>F(f)&&(a._pf._overflowDayOfYear=!0),d=fb(f,0,a._dayOfYear),a._a[Db]=d.getUTCMonth(),a._a[Eb]=d.getUTCDate()),c=0;3>c&&null==a._a[c];++c)a._a[c]=g[c]=e[c];for(;7>c;c++)a._a[c]=g[c]=null==a._a[c]?2===c?1:0:a._a[c];24===a._a[Fb]&&0===a._a[Gb]&&0===a._a[Hb]&&0===a._a[Ib]&&(a._nextDay=!0,a._a[Fb]=0),a._d=(a._useUTC?fb:eb).apply(null,g),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[Fb]=24)}}function W(a){var b;a._d||(b=A(a._i),a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],V(a))}function X(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function Y(b){if(b._f===vb.ISO_8601)return void ab(b);b._a=[],b._pf.empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,j=0;for(e=Q(b._f,b._locale).match(Pb)||[],c=0;c<e.length;c++)f=e[c],d=(h.match(R(f,b))||[])[0],d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&b._pf.unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),j+=d.length),rc[f]?(d?b._pf.empty=!1:b._pf.unusedTokens.push(f),T(f,d,b)):b._strict&&!d&&b._pf.unusedTokens.push(f);b._pf.charsLeftOver=i-j,h.length>0&&b._pf.unusedInput.push(h),b._pf.bigHour===!0&&b._a[Fb]<=12&&(b._pf.bigHour=a),b._a[Fb]=k(b._locale,b._a[Fb],b._meridiem),V(b),H(b)}function Z(a){return a.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e})}function $(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function _(a){var b,c,e,f,g;
699if(0===a._f.length)return a._pf.invalidFormat=!0,void(a._d=new Date(0/0));for(f=0;f<a._f.length;f++)g=0,b=p({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._pf=d(),b._f=a._f[f],Y(b),I(b)&&(g+=b._pf.charsLeftOver,g+=10*b._pf.unusedTokens.length,b._pf.score=g,(null==e||e>g)&&(e=g,c=b));o(a,c||b)}function ab(a){var b,c,d=a._i,e=fc.exec(d);if(e){for(a._pf.iso=!0,b=0,c=hc.length;c>b;b++)if(hc[b][1].exec(d)){a._f=hc[b][0]+(e[6]||" ");break}for(b=0,c=ic.length;c>b;b++)if(ic[b][1].exec(d)){a._f+=ic[b][0];break}d.match(Xb)&&(a._f+="Z"),Y(a)}else a._isValid=!1}function bb(a){ab(a),a._isValid===!1&&(delete a._isValid,vb.createFromInputFallback(a))}function cb(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function db(b){var c,d=b._i;d===a?b._d=new Date:x(d)?b._d=new Date(+d):null!==(c=Mb.exec(d))?b._d=new Date(+c[1]):"string"==typeof d?bb(b):w(d)?(b._a=cb(d.slice(0),function(a){return parseInt(a,10)}),V(b)):"object"==typeof d?W(b):"number"==typeof d?b._d=new Date(d):vb.createFromInputFallback(b)}function eb(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function fb(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function gb(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function hb(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function ib(a,b,c){var d=vb.duration(a).abs(),e=Ab(d.as("s")),f=Ab(d.as("m")),g=Ab(d.as("h")),h=Ab(d.as("d")),i=Ab(d.as("M")),j=Ab(d.as("y")),k=e<oc.s&&["s",e]||1===f&&["m"]||f<oc.m&&["mm",f]||1===g&&["h"]||g<oc.h&&["hh",g]||1===h&&["d"]||h<oc.d&&["dd",h]||1===i&&["M"]||i<oc.M&&["MM",i]||1===j&&["y"]||["yy",j];return k[2]=b,k[3]=+a>0,k[4]=c,hb.apply({},k)}function jb(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=vb(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function kb(a,b,c,d,e){var f,g,h=fb(a,0,1).getUTCDay();return h=0===h?7:h,c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:F(a-1)+g}}function lb(b){var c,d=b._i,e=b._f;return b._locale=b._locale||vb.localeData(b._l),null===d||e===a&&""===d?vb.invalid({nullInput:!0}):("string"==typeof d&&(b._i=d=b._locale.preparse(d)),vb.isMoment(d)?new m(d,!0):(e?w(e)?_(b):Y(b):db(b),c=new m(b),c._nextDay&&(c.add(1,"d"),c._nextDay=a),c))}function mb(a,b){var c,d;if(1===b.length&&w(b[0])&&(b=b[0]),!b.length)return vb();for(c=b[0],d=1;d<b.length;++d)b[d][a](c)&&(c=b[d]);return c}function nb(a,b){var c;return"string"==typeof b&&(b=a.localeData().monthsParse(b),"number"!=typeof b)?a:(c=Math.min(a.date(),D(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a)}function ob(a,b){return a._d["get"+(a._isUTC?"UTC":"")+b]()}function pb(a,b,c){return"Month"===b?nb(a,c):a._d["set"+(a._isUTC?"UTC":"")+b](c)}function qb(a,b){return function(c){return null!=c?(pb(this,a,c),vb.updateOffset(this,b),this):ob(this,a)}}function rb(a){return 400*a/146097}function sb(a){return 146097*a/400}function tb(a){vb.duration.fn[a]=function(){return this._data[a]}}function ub(a){"undefined"==typeof ender&&(wb=zb.moment,zb.moment=a?f("Accessing Moment through the global scope is deprecated, and will be removed in an upcoming release.",vb):vb)}for(var vb,wb,xb,yb="2.9.0",zb="undefined"==typeof global||"undefined"!=typeof window&&window!==global.window?this:global,Ab=Math.round,Bb=Object.prototype.hasOwnProperty,Cb=0,Db=1,Eb=2,Fb=3,Gb=4,Hb=5,Ib=6,Jb={},Kb=[],Lb="undefined"!=typeof module&&module&&module.exports,Mb=/^\/?Date\((\-?\d+)/i,Nb=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,Ob=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,Pb=/(\[[^\[]*\])|(\\)?(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,Qb=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Rb=/\d\d?/,Sb=/\d{1,3}/,Tb=/\d{1,4}/,Ub=/[+\-]?\d{1,6}/,Vb=/\d+/,Wb=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Xb=/Z|[\+\-]\d\d:?\d\d/gi,Yb=/T/i,Zb=/[\+\-]?\d+/,$b=/[\+\-]?\d+(\.\d{1,3})?/,_b=/\d/,ac=/\d\d/,bc=/\d{3}/,cc=/\d{4}/,dc=/[+-]?\d{6}/,ec=/[+-]?\d+/,fc=/^\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)?)?$/,gc="YYYY-MM-DDTHH:mm:ssZ",hc=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],ic=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],jc=/([\+\-]|\d\d)/gi,kc=("Date|Hours|Minutes|Seconds|Milliseconds".split("|"),{Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6}),lc={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",D:"date",w:"week",W:"isoWeek",M:"month",Q:"quarter",y:"year",DDD:"dayOfYear",e:"weekday",E:"isoWeekday",gg:"weekYear",GG:"isoWeekYear"},mc={dayofyear:"dayOfYear",isoweekday:"isoWeekday",isoweek:"isoWeek",weekyear:"weekYear",isoweekyear:"isoWeekYear"},nc={},oc={s:45,m:45,h:22,d:26,M:11},pc="DDD w W M D d".split(" "),qc="M D H h m s w W".split(" "),rc={M:function(){return this.month()+1},MMM:function(a){return this.localeData().monthsShort(this,a)},MMMM:function(a){return this.localeData().months(this,a)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(a){return this.localeData().weekdaysMin(this,a)},ddd:function(a){return this.localeData().weekdaysShort(this,a)},dddd:function(a){return this.localeData().weekdays(this,a)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return r(this.year()%100,2)},YYYY:function(){return r(this.year(),4)},YYYYY:function(){return r(this.year(),5)},YYYYYY:function(){var a=this.year(),b=a>=0?"+":"-";return b+r(Math.abs(a),6)},gg:function(){return r(this.weekYear()%100,2)},gggg:function(){return r(this.weekYear(),4)},ggggg:function(){return r(this.weekYear(),5)},GG:function(){return r(this.isoWeekYear()%100,2)},GGGG:function(){return r(this.isoWeekYear(),4)},GGGGG:function(){return r(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.localeData().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return C(this.milliseconds()/100)},SS:function(){return r(C(this.milliseconds()/10),2)},SSS:function(){return r(this.milliseconds(),3)},SSSS:function(){return r(this.milliseconds(),3)},Z:function(){var a=this.utcOffset(),b="+";return 0>a&&(a=-a,b="-"),b+r(C(a/60),2)+":"+r(C(a)%60,2)},ZZ:function(){var a=this.utcOffset(),b="+";return 0>a&&(a=-a,b="-"),b+r(C(a/60),2)+r(C(a)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},x:function(){return this.valueOf()},X:function(){return this.unix()},Q:function(){return this.quarter()}},sc={},tc=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"],uc=!1;pc.length;)xb=pc.pop(),rc[xb+"o"]=i(rc[xb],xb);for(;qc.length;)xb=qc.pop(),rc[xb+xb]=h(rc[xb],2);rc.DDDD=h(rc.DDD,3),o(l.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a,b,c){var d,e,f;for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;12>d;d++){if(e=vb.utc([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=vb([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY LT",LLLL:"dddd, MMMM D, YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.apply(b,[c]):d},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",_ordinalParse:/\d{1,2}/,preparse:function(a){return a},postformat:function(a){return a},week:function(a){return jb(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},firstDayOfWeek:function(){return this._week.dow},firstDayOfYear:function(){return this._week.doy},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),vb=function(b,c,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._i=b,g._f=c,g._l=e,g._strict=f,g._isUTC=!1,g._pf=d(),lb(g)},vb.suppressDeprecationWarnings=!1,vb.createFromInputFallback=f("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),vb.min=function(){var a=[].slice.call(arguments,0);return mb("isBefore",a)},vb.max=function(){var a=[].slice.call(arguments,0);return mb("isAfter",a)},vb.utc=function(b,c,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._useUTC=!0,g._isUTC=!0,g._l=e,g._i=b,g._f=c,g._strict=f,g._pf=d(),lb(g).utc()},vb.unix=function(a){return vb(1e3*a)},vb.duration=function(a,b){var d,e,f,g,h=a,i=null;return vb.isDuration(a)?h={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(h={},b?h[b]=a:h.milliseconds=a):(i=Nb.exec(a))?(d="-"===i[1]?-1:1,h={y:0,d:C(i[Eb])*d,h:C(i[Fb])*d,m:C(i[Gb])*d,s:C(i[Hb])*d,ms:C(i[Ib])*d}):(i=Ob.exec(a))?(d="-"===i[1]?-1:1,f=function(a){var b=a&&parseFloat(a.replace(",","."));return(isNaN(b)?0:b)*d},h={y:f(i[2]),M:f(i[3]),d:f(i[4]),h:f(i[5]),m:f(i[6]),s:f(i[7]),w:f(i[8])}):null==h?h={}:"object"==typeof h&&("from"in h||"to"in h)&&(g=t(vb(h.from),vb(h.to)),h={},h.ms=g.milliseconds,h.M=g.months),e=new n(h),vb.isDuration(a)&&c(a,"_locale")&&(e._locale=a._locale),e},vb.version=yb,vb.defaultFormat=gc,vb.ISO_8601=function(){},vb.momentProperties=Kb,vb.updateOffset=function(){},vb.relativeTimeThreshold=function(b,c){return oc[b]===a?!1:c===a?oc[b]:(oc[b]=c,!0)},vb.lang=f("moment.lang is deprecated. Use moment.locale instead.",function(a,b){return vb.locale(a,b)}),vb.locale=function(a,b){var c;return a&&(c="undefined"!=typeof b?vb.defineLocale(a,b):vb.localeData(a),c&&(vb.duration._locale=vb._locale=c)),vb._locale._abbr},vb.defineLocale=function(a,b){return null!==b?(b.abbr=a,Jb[a]||(Jb[a]=new l),Jb[a].set(b),vb.locale(a),Jb[a]):(delete Jb[a],null)},vb.langData=f("moment.langData is deprecated. Use moment.localeData instead.",function(a){return vb.localeData(a)}),vb.localeData=function(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return vb._locale;if(!w(a)){if(b=L(a))return b;a=[a]}return K(a)},vb.isMoment=function(a){return a instanceof m||null!=a&&c(a,"_isAMomentObject")},vb.isDuration=function(a){return a instanceof n};for(xb=tc.length-1;xb>=0;--xb)B(tc[xb]);vb.normalizeUnits=function(a){return z(a)},vb.invalid=function(a){var b=vb.utc(0/0);return null!=a?o(b._pf,a):b._pf.userInvalidated=!0,b},vb.parseZone=function(){return vb.apply(null,arguments).parseZone()},vb.parseTwoDigitYear=function(a){return C(a)+(C(a)>68?1900:2e3)},vb.isDate=x,o(vb.fn=m.prototype,{clone:function(){return vb(this)}
699,valueOf:function(){return+this._d-6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var a=vb(this).utc();return 0<a.year()&&a.year()<=9999?"function"==typeof Date.prototype.toISOString?this.toDate().toISOString():P(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):P(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds()]},isValid:function(){return I(this)},isDSTShifted:function(){return this._a?this.isValid()&&y(this._a,(this._isUTC?vb.utc(this._a):vb(this._a)).toArray())>0:!1},parsingFlags:function(){return o({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(a){return this.utcOffset(0,a)},local:function(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(this._dateUtcOffset(),"m")),this},format:function(a){var b=P(this,a||vb.defaultFormat);return this.localeData().postformat(b)},add:u(1,"add"),subtract:u(-1,"subtract"),diff:function(a,b,c){var d,e,f=M(a,this),g=6e4*(f.utcOffset()-this.utcOffset());return b=z(b),"year"===b||"month"===b||"quarter"===b?(e=j(this,f),"quarter"===b?e/=3:"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:q(e)},from:function(a,b){return vb.duration({to:this,from:a}).locale(this.locale()).humanize(!b)},fromNow:function(a){return this.from(vb(),a)},calendar:function(a){var b=a||vb(),c=M(b,this).startOf("day"),d=this.diff(c,"days",!0),e=-6>d?"sameElse":-1>d?"lastWeek":0>d?"lastDay":1>d?"sameDay":2>d?"nextDay":7>d?"nextWeek":"sameElse";return this.format(this.localeData().calendar(e,this,vb(b)))},isLeapYear:function(){return G(this.year())},isDST:function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},day:function(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=gb(a,this.localeData()),this.add(a-b,"d")):b},month:qb("Month",!0),startOf:function(a){switch(a=z(a)){case"year":this.month(0);case"quarter":case"month":this.date(1);case"week":case"isoWeek":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a?this.weekday(0):"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this},endOf:function(b){return b=z(b),b===a||"millisecond"===b?this:this.startOf(b).add(1,"isoWeek"===b?"week":b).subtract(1,"ms")},isAfter:function(a,b){var c;return b=z("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=vb.isMoment(a)?a:vb(a),+this>+a):(c=vb.isMoment(a)?+a:+vb(a),c<+this.clone().startOf(b))},isBefore:function(a,b){var c;return b=z("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=vb.isMoment(a)?a:vb(a),+a>+this):(c=vb.isMoment(a)?+a:+vb(a),+this.clone().endOf(b)<c)},isBetween:function(a,b,c){return this.isAfter(a,c)&&this.isBefore(b,c)},isSame:function(a,b){var c;return b=z(b||"millisecond"),"millisecond"===b?(a=vb.isMoment(a)?a:vb(a),+this===+a):(c=+vb(a),+this.clone().startOf(b)<=c&&c<=+this.clone().endOf(b))},min:f("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(a){return a=vb.apply(null,arguments),this>a?this:a}),max:f("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(a){return a=vb.apply(null,arguments),a>this?this:a}),zone:f("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",function(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}),utcOffset:function(a,b){var c,d=this._offset||0;return null!=a?("string"==typeof a&&(a=S(a)),Math.abs(a)<16&&(a=60*a),!this._isUTC&&b&&(c=this._dateUtcOffset()),this._offset=a,this._isUTC=!0,null!=c&&this.add(c,"m"),d!==a&&(!b||this._changeInProgress?v(this,vb.duration(a-d,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,vb.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?d:this._dateUtcOffset()},isLocal:function(){return!this._isUTC},isUtcOffset:function(){return this._isUTC},isUtc:function(){return this._isUTC&&0===this._offset},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(S(this._i)),this},hasAlignedHourOffset:function(a){return a=a?vb(a).utcOffset():0,(this.utcOffset()-a)%60===0},daysInMonth:function(){return D(this.year(),this.month())},dayOfYear:function(a){var b=Ab((vb(this).startOf("day")-vb(this).startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}
699,quarter:function(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)},weekYear:function(a){var b=jb(this,this.localeData()._week.dow,this.localeData()._week.doy).year;return null==a?b:this.add(a-b,"y")},isoWeekYear:function(a){var b=jb(this,1,4).year;return null==a?b:this.add(a-b,"y")},week:function(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")},isoWeek:function(a){var b=jb(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")},weekday:function(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},isoWeeksInYear:function(){return E(this.year(),1,4)},weeksInYear:function(){var a=this.localeData()._week;return E(this.year(),a.dow,a.doy)},get:function(a){return a=z(a),this[a]()},set:function(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else a=z(a),"function"==typeof this[a]&&this[a](b);return this},locale:function(b){var c;return b===a?this._locale._abbr:(c=vb.localeData(b),null!=c&&(this._locale=c),this)},lang:f("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(b){return b===a?this.localeData():this.locale(b)}),localeData:function(){return this._locale},_dateUtcOffset:function(){return 15*-Math.round(this._d.getTimezoneOffset()/15)}}),vb.fn.millisecond=vb.fn.milliseconds=qb("Milliseconds",!1),vb.fn.second=vb.fn.seconds=qb("Seconds",!1),vb.fn.minute=vb.fn.minutes=qb("Minutes",!1),vb.fn.hour=vb.fn.hours=qb("Hours",!0),vb.fn.date=qb("Date",!0),vb.fn.dates=f("dates accessor is deprecated. Use date instead.",qb("Date",!0)),vb.fn.year=qb("FullYear",!0),vb.fn.years=f("years accessor is deprecated. Use year instead.",qb("FullYear",!0)),vb.fn.days=vb.fn.day,vb.fn.months=vb.fn.month,vb.fn.weeks=vb.fn.week,vb.fn.isoWeeks=vb.fn.isoWeek,vb.fn.quarters=vb.fn.quarter,vb.fn.toJSON=vb.fn.toISOString,vb.fn.isUTC=vb.fn.isUtc,o(vb.duration.fn=n.prototype,{_bubble:function(){var a,b,c,d=this._milliseconds,e=this._days,f=this._months,g=this._data,h=0;g.milliseconds=d%1e3,a=q(d/1e3),g.seconds=a%60,b=q(a/60),g.minutes=b%60,c=q(b/60),g.hours=c%24,e+=q(c/24),h=q(rb(e)),e-=q(sb(h)),f+=q(e/30),e%=30,h+=q(f/12),f%=12,g.days=e,g.months=f,g.years=h},abs:function(){return this._milliseconds=Math.abs(this._milliseconds),this._days=Math.abs(this._days),this._months=Math.abs(this._months),this._data.milliseconds=Math.abs(this._data.milliseconds),this._data.seconds=Math.abs(this._data.seconds),this._data.minutes=Math.abs(this._data.minutes),this._data.hours=Math.abs(this._data.hours),this._data.months=Math.abs(this._data.months),this._data.years=Math.abs(this._data.years),this},weeks:function(){return q(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*C(this._months/12) 700 701},humanize:function(a){var b=ib(this,!a,this.localeData());return a&&(b=this.localeData().pastFuture(+this,b)),this.localeData().postformat(b)},add:function(a,b){var c=vb.duration(a,b);return this._milliseconds+=c._milliseconds,this._days+=c._days,this._months+=c._months,this._bubble(),this},subtract:function(a,b){var c=vb.duration(a,b);return this._milliseconds-=c._milliseconds,this._days-=c._days,this._months-=c._months,this._bubble(),this},get:function(a){return a=z(a),this[a.toLowerCase()+"s"]()},as:function(a){var b,c;if(a=z(a),"month"===a||"year"===a)return b=this._days+this._milliseconds/864e5,c=this._months+12*rb(b),"month"===a?c:c/12;switch(b=this._days+Math.round(sb(this._months/12)),a){case"week":return b/7+this._milliseconds/6048e5;case"day":return b+this._milliseconds/864e5;case"hour":return 24*b+this._milliseconds/36e5;case"minute":return 24*b*60+this._milliseconds/6e4;case"second":return 24*b*60*60+this._milliseconds/1e3;case"millisecond":return Math.floor(24*b*60*60*1e3)+this._milliseconds;default:throw new Error("Unknown unit "+a)}},lang:vb.fn.lang,locale:vb.fn.locale,toIsoString:f("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",function(){return this.toISOString()}),toISOString:function(){var a=Math.abs(this.years()),b=Math.abs(this.months()),c=Math.abs(this.days()),d=Math.abs(this.hours()),e=Math.abs(this.minutes()),f=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"},localeData:function(){return this._locale},toJSON:function(){return this.toISOString()}}),vb.duration.fn.toString=vb.duration.fn.toISOString;for(xb in kc)c(kc,xb)&&tb(xb.toLowerCase());vb.duration.fn.asMilliseconds=function(){return this.as("ms")},vb.duration.fn.asSeconds=function(){return this.as("s")},vb.duration.fn.asMinutes=function(){return this.as("m")},vb.duration.fn.asHours=function(){return this.as("h")},vb.duration.fn.asDays=function(){return this.as("d")},vb.duration.fn.asWeeks=function(){return this.as("weeks")},vb.duration.fn.asMonths=function(){return this.as("M")},vb.duration.fn.asYears=function(){return this.as("y")},vb.locale("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===C(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),Lb?module.exports=vb:"function"==typeof define&&define.amd?(define(function(a,b,c){return c.config&&c.config()&&c.config().noGlobal===!0&&(zb.moment=wb),vb}),ub(!0)):ub()}).call(this); 702/*! 703 704 * FullCalendar v2.5.0 705 706 * Docs & License: http://fullcalendar.io/ 707 708 * (c) 2015 Adam Shaw 709 710 */ 711 712 713 714(function(factory) { 715 716 if (typeof define === 'function' && define.amd) { 717 718 define([ 'jquery', 'moment' ], factory); 719 720 } 721 722 else if (typeof exports === 'object') { // Node/CommonJS 723 724 module.exports = factory(require('jquery'), require('moment')); 725 726 } 727 728 else { 729 730 factory(jQuery, moment); 731 732 } 733 734})(function($, moment) { 735 736 737 738 ;; 739 740 741 742 var FC = $.fullCalendar = { 743 744 version: "2.5.0", 745 746 internalApiVersion: 1 747 748 }; 749 750 var fcViews = FC.views = {}; 751 752 753 754 755 756 $.fn.fullCalendar = function(options) { 757 758 var args = Array.prototype.slice.call(arguments, 1); // for a possible method call 759 760 var res = this; // what this function will return (this jQuery object by default) 761 762 763 764 this.each(function(i, _element) { // loop each DOM element involved 765 766 var element = $(_element); 767 768 var calendar = element.data('fullCalendar'); // get the existing calendar object (if any) 769 770 var singleRes; // the returned value of this single method call 771 772 773 774 // a method call 775 776 if (typeof options === 'string') { 777 778 if (calendar && $.isFunction(calendar[options])) { 779
780 singleRes = calendar[options].apply(calendar, args); 781 782 if (!i) { 783 784 res = singleRes; // record the first method call result 785 786 } 787 788 if (options === 'destroy') { // for the destroy method, must remove Calendar object data 789 790 element.removeData('fullCalendar'); 791 792 } 793 794 } 795 796 } 797 798 // a new calendar initialization 799 800 else if (!calendar) { // don't initialize twice 801 802 calendar = new Calendar(element, options); 803 804 element.data('fullCalendar', calendar); 805 806 calendar.render(); 807 808 } 809 810 }); 811 812 813 814 return res; 815 816 }; 817 818 819 820 821 822 var complexOptions = [ // names of options that are objects whose properties should be combined 823 824 'header', 825 826 'buttonText', 827 828 'buttonIcons', 829 830 'themeButtonIcons' 831 832 ]; 833 834 835 836 837 838// Merges an array of option objects into a single object 839 840 function mergeOptions(optionObjs) { 841 842 return mergeProps(optionObjs, complexOptions); 843 844 } 845 846 847 848 849 850// Given options specified for the calendar's constructor, massages any legacy options into a non-legacy form. 851 852// Converts View-Option-Hashes into the View-Specific-Options format. 853 854 function massageOverrides(input) { 855 856 var overrides = { views: input.views || {} }; // the output. ensure a `views` hash 857 858 var subObj; 859 860 861 862 // iterate through all option override properties (except `views`) 863 864 $.each(input, function(name, val) { 865 866 if (name != 'views') { 867 868 869 870 // could the value be a legacy View-Option-Hash? 871 872 if ( 873 874 $.isPlainObject(val) && 875 876 !/(time|duration|interval)$/i.test(name) && // exclude duration options. might be given as objects 877 878 $.inArray(name, complexOptions) == -1 // complex options aren't allowed to be View-Option-Hashes 879 880 ) { 881 882 subObj = null; 883 884 885 886 // iterate through the properties of this possible View-Option-Hash value 887 888 $.each(val, function(subName, subVal) { 889 890 891 892 // is the property targeting a view? 893 894 if (/^(month|week|day|default|basic(Week|Day)?|agenda(Week|Day)?)$/.test(subName)) { 895 896 if (!overrides.views[subName]) { // ensure the view-target entry exists 897 898 overrides.views[subName] = {}; 899 900 } 901 902 overrides.views[subName][name] = subVal; // record the value in the `views` object 903 904 } 905 906 else { // a non-View-Option-Hash property 907 908 if (!subObj) { 909 910 subObj = {}; 911 912 } 913 914 subObj[subName] = subVal; // accumulate these unrelated values for later 915 916 } 917 918 }); 919 920 921 922 if (subObj) { // non-View-Option-Hash properties? transfer them as-is 923 924 overrides[name] = subObj; 925 926 } 927 928 } 929 930 else { 931 932 overrides[name] = val; // transfer normal options as-is 933 934 } 935 936 } 937 938 }); 939 940 941 942 return overrides; 943 944 } 945 946 947 948 ;; 949 950 951 952// exports 953 954 FC.intersectRanges = intersectRanges; 955 956 FC.applyAll = applyAll; 957 958 FC.debounce = debounce; 959 960 FC.isInt = isInt; 961 962 FC.htmlEscape = htmlEscape; 963 964 FC.cssToStr = cssToStr; 965 966 FC.proxy = proxy; 967 968 FC.capitaliseFirstLetter = capitaliseFirstLetter; 969 970 971 972 973 974 /* FullCalendar-specific DOM Utilities 975 976 ----------------------------------------------------------------------------------------------------------------------*/ 977 978 979 980 981 982// Given the scrollbar widths of some other container, create borders/margins on rowEls in order to match the left 983 984// and right space that was offset by the scrollbars. A 1-pixel border first, then margin beyond that. 985 986 function compensateScroll(rowEls, scrollbarWidths) { 987 988 if (scrollbarWidths.left) { 989 990 rowEls.css({ 991 992 'border-left-width': 1, 993 994 'margin-left': scrollbarWidths.left - 1 995 996 }); 997 998 } 999 1000 if (scrollbarWidths.right) { 1001 1002 rowEls.css({ 1003 1004 'border-right-width': 1, 1005 1006 'margin-right': scrollbarWidths.right - 1 1007 1008 }); 1009 1010 } 1011 1012 } 1013 1014 1015 1016 1017 1018// Undoes compensateScroll and restores all borders/margins 1019 1020 function uncompensateScroll(rowEls) { 1021 1022 rowEls.css({ 1023 1024 'margin-left': '', 1025 1026 'margin-right': '', 1027 1028 'border-left-width': '', 1029 1030 'border-right-width': '' 1031 1032 }); 1033 1034 } 1035 1036 1037 1038 1039 1040// Make the mouse cursor express that an event is not allowed in the current area 1041 1042 function disableCursor() { 1043 1044 $('body').addClass('fc-not-allowed'); 1045 1046 } 1047 1048 1049 1050 1051 1052// Returns the mouse cursor to its original look 1053 1054 function enableCursor() { 1055 1056 $('body').removeClass('fc-not-allowed'); 1057 1058 } 1059 1060 1061 1062 1063 1064// Given a total available height to fill, have `els` (essentially child rows) expand to accomodate. 1065 1066// By default, all elements that are shorter than the recommended height are expanded uniformly, not considering 1067 1068// any other els that are already too tall. if `shouldRedistribute` is on, it considers these tall rows and 1069 1070// reduces the available height. 1071 1072 function distributeHeight(els, availableHeight, shouldRedistribute) { 1073 1074 1075 1076 // *FLOORING NOTE*: we floor in certain places because zoom can give inaccurate floating-point dimensions, 1077 1078 // and it is better to be shorter than taller, to avoid creating unnecessary scrollbars. 1079 1080 1081 1082 var minOffset1 = Math.floor(availableHeight / els.length); // for non-last element 1083 1084 var minOffset2 = Math.floor(availableHeight - minOffset1 * (els.length - 1)); // for last element *FLOORING NOTE* 1085 1086 var flexEls = []; // elements that are allowed to expand. array of DOM nodes 1087 1088 var flexOffsets = []; // amount of vertical space it takes up 1089 1090 var flexHeights = []; // actual css height 1091 1092 var usedHeight = 0; 1093 1094 1095 1096 undistributeHeight(els); // give all elements their natural height 1097 1098 1099 1100 // find elements that are below the recommended height (expandable). 1101 1102 // important to query for heights in a single first pass (to avoid reflow oscillation). 1103 1104 els.each(function(i, el) { 1105 1106 var minOffset = i === els.length - 1 ? minOffset2 : minOffset1; 1107 1108 var naturalOffset = $(el).outerHeight(true); 1109 1110 1111 1112 if (naturalOffset < minOffset) { 1113 1114 flexEls.push(el); 1115 1116 flexOffsets.push(naturalOffset); 1117 1118 flexHeights.push($(el).height()); 1119 1120 } 1121 1122 else { 1123 1124 // this element stretches past recommended height (non-expandable). mark the space as occupied. 1125 1126 usedHeight += naturalOffset; 1127 1128 } 1129 1130 }); 1131 1132 1133 1134 // readjust the recommended height to only consider the height available to non-maxed-out rows. 1135 1136 if (shouldRedistribute) { 1137 1138 availableHeight -= usedHeight; 1139 1140 minOffset1 = Math.floor(availableHeight / flexEls.length); 1141 1142 minOffset2 = Math.floor(availableHeight - minOffset1 * (flexEls.length - 1)); // *FLOORING NOTE* 1143 1144 } 1145 1146 1147 1148 // assign heights to all expandable elements 1149 1150 $(flexEls).each(function(i, el) { 1151 1152 var minOffset = i === flexEls.length - 1 ? minOffset2 : minOffset1; 1153 1154 var naturalOffset = flexOffsets[i]; 1155 1156 var naturalHeight = flexHeights[i]; 1157 1158 var newHeight = minOffset - (naturalOffset - naturalHeight); // subtract the margin/padding 1159 1160 1161 1162 if (naturalOffset < minOffset) { // we check this again because redistribution might have changed things 1163 1164 $(el).height(newHeight); 1165 1166 } 1167 1168 }); 1169 1170 } 1171 1172 1173 1174 1175 1176// Undoes distrubuteHeight, restoring all els to their natural height 1177 1178 function undistributeHeight(els) { 1179 1180 els.height(''); 1181 1182 } 1183 1184 1185 1186 1187 1188// Given `els`, a jQuery set of <td> cells, find the cell with the largest natural width and set the widths of all the 1189 1190// cells to be that width. 1191 1192// PREREQUISITE: if you want a cell to take up width, it needs to have a single inner element w/ display:inline 1193 1194 function matchCellWidths(els) { 1195 1196 var maxInnerWidth = 0; 1197 1198 1199 1200 els.find('> *').each(function(i, innerEl) { 1201 1202 var innerWidth = $(innerEl).outerWidth(); 1203 1204 if (innerWidth > maxInnerWidth) { 1205 1206 maxInnerWidth = innerWidth; 1207 1208 } 1209 1210 }); 1211 1212 1213 1214 maxInnerWidth++; // sometimes not accurate of width the text needs to stay on one line. insurance 1215 1216 1217 1218 els.width(maxInnerWidth); 1219 1220 1221
1222 return maxInnerWidth; 1223 1224 } 1225 1226 1227 1228 1229 1230// Turns a container element into a scroller if its contents is taller than the allotted height. 1231 1232// Returns true if the element is now a scroller, false otherwise. 1233 1234// NOTE: this method is best because it takes weird zooming dimensions into account 1235 1236 function setPotentialScroller(containerEl, height) { 1237 1238 containerEl.height(height).addClass('fc-scroller'); 1239 1240 1241 1242 // are scrollbars needed? 1243 1244 if (containerEl[0].scrollHeight - 1 > containerEl[0].clientHeight) { // !!! -1 because IE is often off-by-one :( 1245 1246 return true; 1247 1248 } 1249 1250 1251 1252 unsetScroller(containerEl); // undo 1253 1254 return false; 1255 1256 } 1257 1258 1259 1260 1261 1262// Takes an element that might have been a scroller, and turns it back into a normal element. 1263 1264 function unsetScroller(containerEl) { 1265 1266 containerEl.height('').removeClass('fc-scroller'); 1267 1268 } 1269 1270 1271 1272 1273 1274 /* General DOM Utilities 1275 1276 ----------------------------------------------------------------------------------------------------------------------*/ 1277 1278 1279 1280 FC.getOuterRect = getOuterRect; 1281 1282 FC.getClientRect = getClientRect; 1283 1284 FC.getContentRect = getContentRect; 1285 1286 FC.getScrollbarWidths = getScrollbarWidths; 1287 1288 1289 1290 1291 1292// borrowed from https://github.com/jquery/jquery-ui/blob/1.11.0/ui/core.js#L51 1293 1294 function getScrollParent(el) { 1295 1296 var position = el.css('position'), 1297 1298 scrollParent = el.parents().filter(function() { 1299 1300 var parent = $(this); 1301 1302 return (/(auto|scroll)/).test( 1303 1304 parent.css('overflow') + parent.css('overflow-y') + parent.css('overflow-x') 1305 1306 ); 1307 1308 }).eq(0); 1309 1310 1311 1312 return position === 'fixed' || !scrollParent.length ? $(el[0].ownerDocument || document) : scrollParent; 1313 1314 } 1315 1316 1317 1318 1319 1320// Queries the outer bounding area of a jQuery element. 1321 1322// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive). 1323 1324 function getOuterRect(el) { 1325 1326 var offset = el.offset(); 1327 1328 1329 1330 return { 1331 1332 left: offset.left, 1333 1334 right: offset.left + el.outerWidth(), 1335 1336 top: offset.top, 1337 1338 bottom: offset.top + el.outerHeight() 1339 1340 }; 1341 1342 } 1343 1344 1345 1346 1347 1348// Queries the area within the margin/border/scrollbars of a jQuery element. Does not go within the padding. 1349 1350// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive). 1351 1352// NOTE: should use clientLeft/clientTop, but very unreliable cross-browser. 1353 1354 function getClientRect(el) { 1355 1356 var offset = el.offset(); 1357 1358 var scrollbarWidths = getScrollbarWidths(el); 1359 1360 var left = offset.left + getCssFloat(el, 'border-left-width') + scrollbarWidths.left; 1361 1362 var top = offset.top + getCssFloat(el, 'border-top-width') + scrollbarWidths.top; 1363 1364 1365 1366 return { 1367 1368 left: left, 1369 1370 right: left + el[0].clientWidth, // clientWidth includes padding but NOT scrollbars 1371 1372 top: top, 1373 1374 bottom: top + el[0].clientHeight // clientHeight includes padding but NOT scrollbars 1375 1376 }; 1377 1378 } 1379 1380 1381 1382 1383 1384// Queries the area within the margin/border/padding of a jQuery element. Assumed not to have scrollbars. 1385 1386// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive). 1387 1388 function getContentRect(el) { 1389 1390 var offset = el.offset(); // just outside of border, margin not included 1391 1392 var left = offset.left + getCssFloat(el, 'border-left-width') + getCssFloat(el, 'padding-left'); 1393 1394 var top = offset.top + getCssFloat(el, 'border-top-width') + getCssFloat(el, 'padding-top'); 1395 1396 1397 1398 return { 1399 1400 left: left, 1401 1402 right: left + el.width(), 1403 1404 top: top, 1405 1406 bottom: top + el.height() 1407 1408 }; 1409 1410 } 1411 1412 1413 1414 1415 1416// Returns the computed left/right/top/bottom scrollbar widths for the given jQuery element. 1417 1418// NOTE: should use clientLeft/clientTop, but very unreliable cross-browser. 1419 1420 function getScrollbarWidths(el) { 1421 1422 var leftRightWidth = el.innerWidth() - el[0].clientWidth; // the paddings cancel out, leaving the scrollbars 1423 1424 var widths = { 1425 1426 left: 0, 1427 1428 right: 0, 1429 1430 top: 0, 1431
1432 bottom: el.innerHeight() - el[0].clientHeight // the paddings cancel out, leaving the bottom scrollbar 1433 1434 }; 1435 1436 1437 1438 if (getIsLeftRtlScrollbars() && el.css('direction') == 'rtl') { // is the scrollbar on the left side? 1439 1440 widths.left = leftRightWidth; 1441 1442 } 1443 1444 else { 1445 1446 widths.right = leftRightWidth; 1447 1448 } 1449 1450 1451 1452 return widths; 1453 1454 } 1455 1456 1457 1458 1459 1460// Logic for determining if, when the element is right-to-left, the scrollbar appears on the left side 1461 1462 1463 1464 var _isLeftRtlScrollbars = null; 1465 1466 1467 1468 function getIsLeftRtlScrollbars() { // responsible for caching the computation 1469 1470 if (_isLeftRtlScrollbars === null) { 1471 1472 _isLeftRtlScrollbars = computeIsLeftRtlScrollbars(); 1473 1474 } 1475 1476 return _isLeftRtlScrollbars; 1477 1478 } 1479 1480 1481 1482 function computeIsLeftRtlScrollbars() { // creates an offscreen test element, then removes it 1483 1484 var el = $('<div><div/></div>') 1485 1486 .css({ 1487 1488 position: 'absolute', 1489 1490 top: -1000, 1491 1492 left: 0, 1493 1494 border: 0, 1495 1496 padding: 0, 1497 1498 overflow: 'scroll', 1499 1500 direction: 'rtl' 1501 1502 }) 1503 1504 .appendTo('body'); 1505 1506 var innerEl = el.children(); 1507 1508 var res = innerEl.offset().left > el.offset().left; // is the inner div shifted to accommodate a left scrollbar? 1509 1510 el.remove(); 1511 1512 return res; 1513 1514 } 1515 1516 1517 1518 1519 1520// Retrieves a jQuery element's computed CSS value as a floating-point number. 1521 1522// If the queried value is non-numeric (ex: IE can return "medium" for border width), will just return zero. 1523 1524 function getCssFloat(el, prop) { 1525 1526 return parseFloat(el.css(prop)) || 0; 1527 1528 } 1529 1530 1531 1532 1533 1534// Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac) 1535 1536 function isPrimaryMouseButton(ev) { 1537 1538 return ev.which == 1 && !ev.ctrlKey; 1539 1540 } 1541 1542 1543 1544 1545 1546 /* Geometry 1547 1548 ----------------------------------------------------------------------------------------------------------------------*/ 1549 1550 1551 1552 FC.intersectRects = intersectRects; 1553 1554 1555 1556// Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false 1557 1558 function intersectRects(rect1, rect2) { 1559 1560 var res = { 1561 1562 left: Math.max(rect1.left, rect2.left), 1563 1564 right: Math.min(rect1.right, rect2.right), 1565 1566 top: Math.max(rect1.top, rect2.top), 1567 1568 bottom: Math.min(rect1.bottom, rect2.bottom) 1569 1570 }; 1571 1572 1573 1574 if (res.left < res.right && res.top < res.bottom) { 1575 1576 return res; 1577 1578 } 1579 1580 return false; 1581 1582 } 1583 1584 1585 1586 1587 1588// Returns a new point that will have been moved to reside within the given rectangle 1589 1590 function constrainPoint(point, rect) { 1591 1592 return { 1593 1594 left: Math.min(Math.max(point.left, rect.left), rect.right), 1595 1596 top: Math.min(Math.max(point.top, rect.top), rect.bottom) 1597 1598 }; 1599 1600 } 1601 1602 1603 1604 1605 1606// Returns a point that is the center of the given rectangle 1607 1608 function getRectCenter(rect) { 1609 1610 return { 1611 1612 left: (rect.left + rect.right) / 2, 1613 1614 top: (rect.top + rect.bottom) / 2 1615 1616 }; 1617 1618 } 1619 1620 1621 1622 1623 1624// Subtracts point2's coordinates from point1's coordinates, returning a delta 1625 1626 function diffPoints(point1, point2) { 1627 1628 return { 1629 1630 left: point1.left - point2.left, 1631 1632 top: point1.top - point2.top 1633 1634 }; 1635 1636 } 1637 1638 1639 1640 1641 1642 /* Object Ordering by Field 1643 1644 ----------------------------------------------------------------------------------------------------------------------*/ 1645 1646 1647 1648 FC.parseFieldSpecs = parseFieldSpecs; 1649 1650 FC.compareByFieldSpecs = compareByFieldSpecs; 1651 1652 FC.compareByFieldSpec = compareByFieldSpec; 1653 1654 FC.flexibleCompare = flexibleCompare; 1655 1656 1657 1658 1659 1660 function parseFieldSpecs(input) { 1661 1662 var specs = []; 1663 1664 var tokens = []; 1665 1666 var i, token; 1667 1668 1669 1670 if (typeof input === 'string') { 1671 1672 tokens = input.split(/\s*,\s*/); 1673 1674 } 1675 1676 else if (typeof input === 'function') { 1677 1678 tokens = [ input ]; 1679 1680 } 1681 1682 else if ($.isArray(input)) { 1683 1684 tokens = input; 1685 1686 } 1687 1688 1689 1690 for (i = 0; i < tokens.length; i++) { 1691 1692 token = tokens[i]; 1693 1694 1695 1696 if (typeof token === 'string') { 1697 1698 specs.push( 1699 1700 token.charAt(0) == '-' ? 1701 1702 { field: token.substring(1), order: -1 } : 1703 1704 { field: token, order: 1 } 1705 1706 ); 1707 1708 } 1709 1710 else if (typeof token === 'function') { 1711 1712 specs.push({ func: token }); 1713 1714 } 1715 1716 } 1717 1718 1719 1720 return specs; 1721 1722 } 1723 1724 1725 1726 1727 1728 function compareByFieldSpecs(obj1, obj2, fieldSpecs) { 1729 1730 var i; 1731 1732 var cmp; 1733 1734 1735 1736 for (i = 0; i < fieldSpecs.length; i++) { 1737 1738 cmp = compareByFieldSpec(obj1, obj2, fieldSpecs[i]); 1739 1740 if (cmp) { 1741 1742 return cmp; 1743 1744 } 1745 1746 } 1747 1748 1749 1750 return 0; 1751 1752 } 1753 1754 1755 1756 1757 1758 function compareByFieldSpec(obj1, obj2, fieldSpec) { 1759 1760 if (fieldSpec.func) { 1761 1762 return fieldSpec.func(obj1, obj2); 1763 1764 } 1765 1766 return flexibleCompare(obj1[fieldSpec.field], obj2[fieldSpec.field]) * 1767 1768 (fieldSpec.order || 1); 1769 1770 } 1771 1772 1773 1774 1775 1776 function flexibleCompare(a, b) { 1777 1778 if (!a && !b) { 1779 1780 return 0; 1781 1782 } 1783 1784 if (b == null) { 1785 1786 return -1; 1787 1788 } 1789 1790 if (a == null) { 1791 1792 return 1; 1793 1794 } 1795 1796 if ($.type(a) === 'string' || $.type(b) === 'string') { 1797 1798 return String(a).localeCompare(String(b)); 1799 1800 } 1801 1802 return a - b; 1803 1804 } 1805 1806 1807 1808 1809 1810 /* FullCalendar-specific Misc Utilities 1811 1812 ----------------------------------------------------------------------------------------------------------------------*/ 1813 1814 1815 1816 1817 1818// Computes the intersection of the two ranges. Returns undefined if no intersection. 1819 1820// Expects all dates to be normalized to the same timezone beforehand. 1821 1822// TODO: move to date section? 1823 1824 function intersectRanges(subjectRange, constraintRange) { 1825 1826 var subjectStart = subjectRange.start; 1827 1828 var subjectEnd = subjectRange.end; 1829 1830 var constraintStart = constraintRange.start; 1831 1832 var constraintEnd = constraintRange.end; 1833 1834 var segStart, segEnd; 1835 1836 var isStart, isEnd; 1837 1838 1839 1840 if (subjectEnd > constraintStart && subjectStart < constraintEnd) { // in bounds at all? 1841 1842 1843 1844 if (subjectStart >= constraintStart) { 1845 1846 segStart = subjectStart.clone(); 1847 1848 isStart = true; 1849 1850 } 1851 1852 else { 1853 1854 segStart = constraintStart.clone(); 1855 1856 isStart = false; 1857 1858 } 1859 1860 1861 1862 if (subjectEnd <= constraintEnd) { 1863 1864 segEnd = subjectEnd.clone(); 1865 1866 isEnd = true; 1867 1868 } 1869 1870 else { 1871 1872 segEnd = constraintEnd.clone(); 1873 1874 isEnd = false;
1875 1876 } 1877 1878 1879 1880 return { 1881 1882 start: segStart, 1883 1884 end: segEnd, 1885 1886 isStart: isStart, 1887 1888 isEnd: isEnd 1889 1890 }; 1891 1892 } 1893 1894 } 1895 1896 1897 1898 1899 1900 /* Date Utilities 1901 1902 ----------------------------------------------------------------------------------------------------------------------*/ 1903 1904 1905 1906 FC.computeIntervalUnit = computeIntervalUnit; 1907 1908 FC.divideRangeByDuration = divideRangeByDuration; 1909 1910 FC.divideDurationByDuration = divideDurationByDuration; 1911 1912 FC.multiplyDuration = multiplyDuration; 1913 1914 FC.durationHasTime = durationHasTime; 1915 1916 1917 1918 var dayIDs = [ 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat' ]; 1919 1920 var intervalUnits = [ 'year', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond' ]; 1921 1922 1923 1924 1925 1926// Diffs the two moments into a Duration where full-days are recorded first, then the remaining time. 1927 1928// Moments will have their timezones normalized. 1929 1930 function diffDayTime(a, b) { 1931 1932 return moment.duration({ 1933 1934 days: a.clone().stripTime().diff(b.clone().stripTime(), 'days'), 1935 1936 ms: a.time() - b.time() // time-of-day from day start. disregards timezone 1937 1938 }); 1939 1940 } 1941 1942 1943 1944 1945 1946// Diffs the two moments via their start-of-day (regardless of timezone). Produces whole-day durations. 1947 1948 function diffDay(a, b) { 1949 1950 return moment.duration({ 1951 1952 days: a.clone().stripTime().diff(b.clone().stripTime(), 'days') 1953 1954 }); 1955 1956 } 1957 1958 1959 1960 1961 1962// Diffs two moments, producing a duration, made of a whole-unit-increment of the given unit. Uses rounding. 1963 1964 function diffByUnit(a, b, unit) { 1965 1966 return moment.duration( 1967 1968 Math.round(a.diff(b, unit, true)), // returnFloat=true 1969 1970 unit 1971 1972 ); 1973 1974 } 1975 1976 1977 1978 1979 1980// Computes the unit name of the largest whole-unit period of time. 1981 1982// For example, 48 hours will be "days" whereas 49 hours will be "hours". 1983 1984// Accepts start/end, a range object, or an original duration object. 1985 1986 function computeIntervalUnit(start, end) { 1987 1988 var i, unit; 1989 1990 var val; 1991 1992 1993 1994 for (i = 0; i < intervalUnits.length; i++) { 1995 1996 unit = intervalUnits[i]; 1997 1998 val = computeRangeAs(unit, start, end); 1999 2000 2001 2002 if (val >= 1 && isInt(val)) { 2003 2004 break; 2005 2006 } 2007 2008 } 2009 2010 2011 2012 return unit; // will be "milliseconds" if nothing else matches 2013 2014 } 2015 2016 2017 2018 2019 2020// Computes the number of units (like "hours") in the given range. 2021 2022// Range can be a {start,end} object, separate start/end args, or a Duration. 2023 2024// Results are based on Moment's .as() and .diff() methods, so results can depend on internal handling 2025 2026// of month-diffing logic (which tends to vary from version to version). 2027 2028 function computeRangeAs(unit, start, end) { 2029 2030 2031 2032 if (end != null) { // given start, end 2033 2034 return end.diff(start, unit, true); 2035 2036 } 2037 2038 else if (moment.isDuration(start)) { // given duration 2039 2040 return start.as(unit); 2041 2042 } 2043 2044 else { // given { start, end } range object 2045 2046 return start.end.diff(start.start, unit, true); 2047 2048 } 2049 2050 } 2051 2052 2053 2054 2055 2056// Intelligently divides a range (specified by a start/end params) by a duration 2057 2058 function divideRangeByDuration(start, end, dur) { 2059 2060 var months; 2061 2062 2063 2064 if (durationHasTime(dur)) { 2065 2066 return (end - start) / dur; 2067 2068 } 2069 2070 months = dur.asMonths(); 2071 2072 if (Math.abs(months) >= 1 && isInt(months)) { 2073 2074 return end.diff(start, 'months', true) / months; 2075 2076 } 2077 2078 return end.diff(start, 'days', true) / dur.asDays(); 2079 2080 } 2081 2082 2083 2084 2085 2086// Intelligently divides one duration by another 2087 2088 function divideDurationByDuration(dur1, dur2) { 2089 2090 var months1, months2; 2091 2092 2093 2094 if (durationHasTime(dur1) || durationHasTime(dur2)) { 2095 2096 return dur1 / dur2; 2097 2098 } 2099 2100 months1 = dur1.asMonths(); 2101 2102 months2 = dur2.asMonths(); 2103 2104 if ( 2105 2106 Math.abs(months1) >= 1 && isInt(months1) && 2107 2108 Math.abs(months2) >= 1 && isInt(months2) 2109 2110 ) { 2111 2112 return months1 / months2; 2113 2114 } 2115 2116 return dur1.asDays() / dur2.asDays(); 2117 2118 } 2119 2120 2121 2122 2123 2124// Intelligently multiplies a duration by a number 2125 2126 function multiplyDuration(dur, n) { 2127 2128 var months; 2129 2130 2131 2132 if (durationHasTime(dur)) { 2133 2134 return moment.duration(dur * n); 2135 2136 } 2137 2138 months = dur.asMonths(); 2139 2140 if (Math.abs(months) >= 1 && isInt(months)) { 2141 2142 return moment.duration({ months: months * n }); 2143 2144 } 2145 2146 return moment.duration({ days: dur.asDays() * n }); 2147 2148 } 2149 2150 2151 2152 2153 2154// Returns a boolean about whether the given duration has any time parts (hours/minutes/seconds/ms) 2155 2156 function durationHasTime(dur) { 2157 2158 return Boolean(dur.hours() || dur.minutes() || dur.seconds() || dur.milliseconds()); 2159 2160 } 2161 2162 2163 2164 2165 2166 function isNativeDate(input) { 2167 2168 return Object.prototype.toString.call(input) === '[object Date]' || input instanceof Date; 2169 2170 } 2171 2172 2173 2174 2175 2176// Returns a boolean about whether the given input is a time string, like "06:40:00" or "06:00" 2177
2178 function isTimeString(str) { 2179 2180 return /^\d+\:\d+(?:\:\d+\.?(?:\d{3})?)?$/.test(str); 2181 2182 } 2183 2184 2185 2186 2187 2188 /* Logging and Debug 2189 2190 ----------------------------------------------------------------------------------------------------------------------*/ 2191 2192 2193 2194 FC.log = function() { 2195 2196 var console = window.console; 2197 2198 2199 2200 if (console && console.log) { 2201 2202 return console.log.apply(console, arguments); 2203 2204 } 2205 2206 }; 2207 2208 2209 2210 FC.warn = function() { 2211 2212 var console = window.console; 2213 2214 2215 2216 if (console && console.warn) { 2217 2218 return console.warn.apply(console, arguments); 2219 2220 } 2221 2222 else { 2223 2224 return FC.log.apply(FC, arguments); 2225 2226 } 2227 2228 }; 2229 2230 2231 2232 2233 2234 /* General Utilities 2235 2236 ----------------------------------------------------------------------------------------------------------------------*/ 2237 2238 2239 2240 var hasOwnPropMethod = {}.hasOwnProperty; 2241 2242 2243 2244 2245 2246// Merges an array of objects into a single object. 2247 2248// The second argument allows for an array of property names who's object values will be merged together. 2249 2250 function mergeProps(propObjs, complexProps) { 2251 2252 var dest = {}; 2253 2254 var i, name; 2255 2256 var complexObjs; 2257 2258 var j, val; 2259 2260 var props; 2261 2262 2263 2264 if (complexProps) { 2265 2266 for (i = 0; i < complexProps.length; i++) { 2267 2268 name = complexProps[i]; 2269 2270 complexObjs = []; 2271 2272 2273 2274 // collect the trailing object values, stopping when a non-object is discovered 2275 2276 for (j = propObjs.length - 1; j >= 0; j--) { 2277 2278 val = propObjs[j][name]; 2279 2280 2281 2282 if (typeof val === 'object') { 2283 2284 complexObjs.unshift(val); 2285 2286 } 2287 2288 else if (val !== undefined) { 2289 2290 dest[name] = val; // if there were no objects, this value will be used 2291 2292 break; 2293 2294 } 2295 2296 } 2297 2298 2299 2300 // if the trailing values were objects, use the merged value 2301 2302 if (complexObjs.length) { 2303 2304 dest[name] = mergeProps(complexObjs); 2305 2306 } 2307 2308 } 2309 2310 } 2311 2312 2313 2314 // copy values into the destination, going from last to first 2315 2316 for (i = propObjs.length - 1; i >= 0; i--) { 2317 2318 props = propObjs[i]; 2319 2320 2321 2322 for (name in props) { 2323 2324 if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign 2325 2326 dest[name] = props[name]; 2327 2328 } 2329 2330 } 2331 2332 } 2333 2334 2335 2336 return dest; 2337 2338 } 2339 2340 2341 2342 2343 2344// Create an object that has the given prototype. Just like Object.create 2345 2346 function createObject(proto) { 2347 2348 var f = function() {}; 2349 2350 f.prototype = proto; 2351 2352 return new f(); 2353 2354 } 2355 2356 2357 2358 2359 2360 function copyOwnProps(src, dest) { 2361 2362 for (var name in src) { 2363 2364 if (hasOwnProp(src, name)) { 2365 2366 dest[name] = src[name]; 2367 2368 } 2369 2370 } 2371 2372 } 2373 2374 2375 2376 2377 2378// Copies over certain methods with the same names as Object.prototype methods. Overcomes an IE<=8 bug: 2379 2380// https://developer.mozilla.org/en-US/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug 2381 2382 function copyNativeMethods(src, dest) { 2383 2384 var names = [ 'constructor', 'toString', 'valueOf' ]; 2385 2386 var i, name; 2387 2388 2389 2390 for (i = 0; i < names.length; i++) { 2391 2392 name = names[i]; 2393 2394 2395 2396 if (src[name] !== Object.prototype[name]) { 2397 2398 dest[name] = src[name]; 2399 2400 } 2401 2402 } 2403 2404 } 2405 2406 2407 2408 2409 2410 function hasOwnProp(obj, name) { 2411 2412 return hasOwnPropMethod.call(obj, name); 2413 2414 } 2415 2416 2417 2418 2419 2420// Is the given value a non-object non-function value? 2421 2422 function isAtomic(val) { 2423 2424 return /undefined|null|boolean|number|string/.test($.type(val)); 2425 2426 } 2427 2428 2429 2430 2431 2432 function applyAll(functions, thisObj, args) { 2433 2434 if ($.isFunction(functions)) { 2435 2436 functions = [ functions ]; 2437 2438 } 2439 2440 if (functions) { 2441 2442 var i; 2443 2444 var ret; 2445 2446 for (i=0; i<functions.length; i++) { 2447 2448 ret = functions[i].apply(thisObj, args) || ret; 2449 2450 } 2451 2452 return ret; 2453 2454 } 2455 2456 } 2457 2458 2459 2460 2461 2462 function firstDefined() { 2463 2464 for (var i=0; i<arguments.length; i++) { 2465 2466 if (arguments[i] !== undefined) { 2467 2468 return arguments[i]; 2469 2470 } 2471 2472 } 2473 2474 } 2475 2476 2477 2478 2479 2480 function htmlEscape(s) { 2481 2482 return (s + '').replace(/&/g, '&') 2483 2484 .replace(/</g, '<') 2485 2486 .replace(/>/g, '>') 2487 2488 .replace(/'/g, ''') 2489 2490 .replace(/"/g, '"') 2491 2492 .replace(/\n/g, '<br />'); 2493 2494 } 2495 2496 2497 2498 2499 2500 function stripHtmlEntities(text) { 2501 2502 return text.replace(/&.*?;/g, ''); 2503 2504 } 2505 2506 2507 2508 2509 2510// Given a hash of CSS properties, returns a string of CSS. 2511 2512// Uses property names as-is (no camel-case conversion). Will not make statements for null/undefined values. 2513 2514 function cssToStr(cssProps) { 2515 2516 var statements = []; 2517 2518 2519 2520 $.each(cssProps, function(name, val) { 2521 2522 if (val != null) { 2523 2524 statements.push(name + ':' + val); 2525 2526 } 2527 2528 }); 2529 2530 2531 2532 return statements.join(';'); 2533 2534 } 2535 2536 2537 2538 2539 2540 function capitaliseFirstLetter(str) { 2541 2542 return str.charAt(0).toUpperCase() + str.slice(1); 2543 2544 } 2545 2546 2547 2548 2549 2550 function compareNumbers(a, b) { // for .sort() 2551 2552 return a - b; 2553 2554 } 2555 2556 2557 2558 2559 2560 function isInt(n) { 2561 2562 return n % 1 === 0; 2563 2564 } 2565 2566 2567 2568 2569
2570// Returns a method bound to the given object context. 2571 2572// Just like one of the jQuery.proxy signatures, but without the undesired behavior of treating the same method with 2573 2574// different contexts as identical when binding/unbinding events. 2575 2576 function proxy(obj, methodName) { 2577 2578 var method = obj[methodName]; 2579 2580 2581 2582 return function() { 2583 2584 return method.apply(obj, arguments); 2585 2586 }; 2587 2588 } 2589 2590 2591 2592 2593 2594// Returns a function, that, as long as it continues to be invoked, will not 2595 2596// be triggered. The function will be called after it stops being called for 2597 2598// N milliseconds. 2599 2600// https://github.com/jashkenas/underscore/blob/1.6.0/underscore.js#L714 2601 2602 function debounce(func, wait) { 2603 2604 var timeoutId; 2605 2606 var args; 2607 2608 var context; 2609 2610 var timestamp; // of most recent call 2611 2612 var later = function() { 2613 2614 var last = +new Date() - timestamp; 2615 2616 if (last < wait && last > 0) { 2617 2618 timeoutId = setTimeout(later, wait - last); 2619 2620 } 2621 2622 else { 2623 2624 timeoutId = null; 2625 2626 func.apply(context, args); 2627 2628 if (!timeoutId) { 2629 2630 context = args = null; 2631 2632 } 2633 2634 } 2635 2636 }; 2637 2638 2639 2640 return function() { 2641 2642 context = this; 2643 2644 args = arguments; 2645 2646 timestamp = +new Date(); 2647 2648 if (!timeoutId) { 2649 2650 timeoutId = setTimeout(later, wait); 2651 2652 } 2653 2654 }; 2655 2656 } 2657 2658 2659 2660 ;; 2661 2662 2663 2664 var ambigDateOfMonthRegex = /^\s*\d{4}-\d\d$/; 2665 2666 var ambigTimeOrZoneRegex = 2667 2668 /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/; 2669 2670 var newMomentProto = moment.fn; // where we will attach our new methods 2671 2672 var oldMomentProto = $.extend({}, newMomentProto); // copy of original moment methods 2673 2674 var allowValueOptimization; 2675 2676 var setUTCValues; // function defined below 2677 2678 var setLocalValues; // function defined below 2679 2680 2681 2682 2683 2684// Creating 2685 2686// ------------------------------------------------------------------------------------------------- 2687 2688 2689 2690// Creates a new moment, similar to the vanilla moment(...) constructor, but with 2691 2692// extra features (ambiguous time, enhanced formatting). When given an existing moment, 2693 2694// it will function as a clone (and retain the zone of the moment). Anything else will 2695 2696// result in a moment in the local zone. 2697 2698 FC.moment = function() { 2699 2700 return makeMoment(arguments); 2701 2702 }; 2703 2704 2705 2706// Sames as FC.moment, but forces the resulting moment to be in the UTC timezone. 2707 2708 FC.moment.utc = function() { 2709 2710 var mom = makeMoment(arguments, true); 2711 2712 2713 2714 // Force it into UTC because makeMoment doesn't guarantee it 2715 2716 // (if given a pre-existing moment for example) 2717 2718 if (mom.hasTime()) { // don't give ambiguously-timed moments a UTC zone 2719 2720 mom.utc(); 2721 2722 } 2723 2724 2725 2726 return mom; 2727 2728 }; 2729 2730 2731 2732// Same as FC.moment, but when given an ISO8601 string, the timezone offset is preserved. 2733 2734// ISO8601 strings with no timezone offset will become ambiguously zoned. 2735 2736 FC.moment.parseZone = function() { 2737 2738 return makeMoment(arguments, true, true); 2739 2740 }; 2741 2742 2743 2744// Builds an enhanced moment from args. When given an existing moment, it clones. When given a 2745 2746// native Date, or called with no arguments (the current time), the resulting moment will be local. 2747 2748// Anything else needs to be "parsed" (a string or an array), and will be affected by: 2749 2750// parseAsUTC - if there is no zone information, should we parse the input in UTC? 2751 2752// parseZone - if there is zone information, should we force the zone of the moment? 2753 2754 function makeMoment(args, parseAsUTC, parseZone) { 2755 2756 var input = args[0]; 2757 2758 var isSingleString = args.length == 1 && typeof input === 'string'; 2759 2760 var isAmbigTime; 2761 2762 var isAmbigZone; 2763 2764 var ambigMatch; 2765 2766 var mom; 2767 2768 2769 2770 if (moment.isMoment(input)) { 2771 2772 mom = moment.apply(null, args); // clone it 2773 2774 transferAmbigs(input, mom); // the ambig flags weren't transfered with the clone 2775 2776 } 2777 2778 else if (isNativeDate(input) || input === undefined) { 2779 2780 mom = moment.apply(null, args); // will be local 2781 2782 } 2783 2784 else { // "parsing" is required 2785 2786 isAmbigTime = false; 2787 2788 isAmbigZone = false; 2789 2790 2791 2792 if (isSingleString) { 2793 2794 if (ambigDateOfMonthRegex.test(input)) { 2795 2796 // accept strings like '2014-05', but convert to the first of the month 2797 2798 input += '-01'; 2799 2800 args = [ input ]; // for when we pass it on to moment's constructor 2801 2802 isAmbigTime = true; 2803 2804 isAmbigZone = true; 2805 2806 } 2807 2808 else if ((ambigMatch = ambigTimeOrZoneRegex.exec(input))) { 2809 2810 isAmbigTime = !ambigMatch[5]; // no time part? 2811 2812 isAmbigZone = true; 2813 2814 } 2815 2816 } 2817 2818 else if ($.isArray(input)) { 2819 2820 // arrays have no timezone information, so assume ambiguous zone 2821 2822 isAmbigZone = true; 2823 2824 } 2825 2826 // otherwise, probably a string with a format 2827 2828 2829 2830 if (parseAsUTC || isAmbigTime) { 2831 2832 mom = moment.utc.apply(moment, args); 2833 2834 } 2835 2836 else { 2837
2838 mom = moment.apply(null, args); 2839 2840 } 2841 2842 2843 2844 if (isAmbigTime) { 2845 2846 mom._ambigTime = true; 2847 2848 mom._ambigZone = true; // ambiguous time always means ambiguous zone 2849 2850 } 2851 2852 else if (parseZone) { // let's record the inputted zone somehow 2853 2854 if (isAmbigZone) { 2855 2856 mom._ambigZone = true; 2857 2858 } 2859 2860 else if (isSingleString) { 2861 2862 if (mom.utcOffset) { 2863 2864 mom.utcOffset(input); // if not a valid zone, will assign UTC 2865 2866 } 2867 2868 else { 2869 2870 mom.zone(input); // for moment-pre-2.9 2871 2872 } 2873 2874 } 2875 2876 } 2877 2878 } 2879 2880 2881 2882 mom._fullCalendar = true; // flag for extended functionality 2883 2884 2885 2886 return mom; 2887 2888 } 2889 2890 2891 2892 2893 2894// A clone method that works with the flags related to our enhanced functionality. 2895 2896// In the future, use moment.momentProperties 2897 2898 newMomentProto.clone = function() { 2899 2900 var mom = oldMomentProto.clone.apply(this, arguments); 2901 2902 2903 2904 // these flags weren't transfered with the clone 2905 2906 transferAmbigs(this, mom); 2907 2908 if (this._fullCalendar) { 2909 2910 mom._fullCalendar = true; 2911 2912 } 2913 2914 2915 2916 return mom; 2917 2918 }; 2919 2920 2921 2922 2923 2924// Week Number 2925 2926// ------------------------------------------------------------------------------------------------- 2927 2928 2929 2930 2931 2932// Returns the week number, considering the locale's custom week number calcuation 2933 2934// `weeks` is an alias for `week` 2935 2936 newMomentProto.week = newMomentProto.weeks = function(input) { 2937 2938 var weekCalc = (this._locale || this._lang) // works pre-moment-2.8 2939 2940 ._fullCalendar_weekCalc; 2941 2942 2943 2944 if (input == null && typeof weekCalc === 'function') { // custom function only works for getter 2945 2946 return weekCalc(this); 2947 2948 } 2949 2950 else if (weekCalc === 'ISO') { 2951 2952 return oldMomentProto.isoWeek.apply(this, arguments); // ISO getter/setter 2953 2954 } 2955 2956 2957 2958 return oldMomentProto.week.apply(this, arguments); // local getter/setter 2959 2960 }; 2961 2962 2963 2964 2965 2966// Time-of-day 2967 2968// ------------------------------------------------------------------------------------------------- 2969 2970 2971 2972// GETTER 2973 2974// Returns a Duration with the hours/minutes/seconds/ms values of the moment. 2975 2976// If the moment has an ambiguous time, a duration of 00:00 will be returned. 2977 2978// 2979 2980// SETTER 2981 2982// You can supply a Duration, a Moment, or a Duration-like argument. 2983 2984// When setting the time, and the moment has an ambiguous time, it then becomes unambiguous. 2985 2986 newMomentProto.time = function(time) { 2987 2988 2989 2990 // Fallback to the original method (if there is one) if this moment wasn't created via FullCalendar. 2991 2992 // `time` is a generic enough method name where this precaution is necessary to avoid collisions w/ other plugins. 2993 2994 if (!this._fullCalendar) { 2995 2996 return oldMomentProto.time.apply(this, arguments); 2997 2998 } 2999 3000 3001 3002 if (time == null) { // getter 3003 3004 return moment.duration({ 3005 3006 hours: this.hours(), 3007 3008 minutes: this.minutes(), 3009 3010 seconds: this.seconds(), 3011 3012 milliseconds: this.milliseconds() 3013 3014 }); 3015 3016 } 3017 3018 else { // setter 3019 3020 3021 3022 this._ambigTime = false; // mark that the moment now has a time 3023 3024 3025 3026 if (!moment.isDuration(time) && !moment.isMoment(time)) { 3027 3028 time = moment.duration(time); 3029 3030 } 3031 3032 3033 3034 // The day value should cause overflow (so 24 hours becomes 00:00:00 of next day). 3035 3036 // Only for Duration times, not Moment times. 3037 3038 var dayHours = 0; 3039 3040 if (moment.isDuration(time)) { 3041 3042 dayHours = Math.floor(time.asDays()) * 24; 3043 3044 } 3045 3046 3047 3048 // We need to set the individual fields. 3049 3050 // Can't use startOf('day') then add duration. In case of DST at start of day. 3051 3052 return this.hours(dayHours + time.hours()) 3053 3054 .minutes(time.minutes()) 3055 3056 .seconds(time.seconds()) 3057 3058 .milliseconds(time.milliseconds()); 3059 3060 } 3061 3062 }; 3063 3064 3065 3066// Converts the moment to UTC, stripping out its time-of-day and timezone offset, 3067 3068// but preserving its YMD. A moment with a stripped time will display no time 3069 3070// nor timezone offset when .format() is called. 3071 3072 newMomentProto.stripTime = function() { 3073 3074 var a; 3075 3076 3077 3078 if (!this._ambigTime) { 3079 3080 3081 3082 // get the values before any conversion happens 3083 3084 a = this.toArray(); // array of y/m/d/h/m/s/ms 3085 3086 3087 3088 // TODO: use keepLocalTime in the future 3089 3090 this.utc(); // set the internal UTC flag (will clear the ambig flags) 3091 3092 setUTCValues(this, a.slice(0, 3)); // set the year/month/date. time will be zero 3093 3094 3095 3096 // Mark the time as ambiguous. This needs to happen after the .utc() call, which might call .utcOffset(), 3097 3098 // which clears all ambig flags. Same with setUTCValues with moment-timezone. 3099 3100 this._ambigTime = true; 3101 3102 this._ambigZone = true; // if ambiguous time, also ambiguous timezone offset 3103 3104 } 3105 3106 3107 3108 return this; // for chaining 3109 3110 }; 3111 3112 3113
3114// Returns if the moment has a non-ambiguous time (boolean) 3115 3116 newMomentProto.hasTime = function() { 3117 3118 return !this._ambigTime; 3119 3120 }; 3121 3122 3123 3124 3125 3126// Timezone 3127 3128// ------------------------------------------------------------------------------------------------- 3129 3130 3131 3132// Converts the moment to UTC, stripping out its timezone offset, but preserving its 3133 3134// YMD and time-of-day. A moment with a stripped timezone offset will display no 3135 3136// timezone offset when .format() is called. 3137 3138// TODO: look into Moment's keepLocalTime functionality 3139 3140 newMomentProto.stripZone = function() { 3141 3142 var a, wasAmbigTime; 3143 3144 3145 3146 if (!this._ambigZone) { 3147 3148 3149 3150 // get the values before any conversion happens 3151 3152 a = this.toArray(); // array of y/m/d/h/m/s/ms 3153 3154 wasAmbigTime = this._ambigTime; 3155 3156 3157 3158 this.utc(); // set the internal UTC flag (might clear the ambig flags, depending on Moment internals) 3159 3160 setUTCValues(this, a); // will set the year/month/date/hours/minutes/seconds/ms 3161 3162 3163 3164 // the above call to .utc()/.utcOffset() unfortunately might clear the ambig flags, so restore 3165 3166 this._ambigTime = wasAmbigTime || false; 3167 3168 3169 3170 // Mark the zone as ambiguous. This needs to happen after the .utc() call, which might call .utcOffset(), 3171 3172 // which clears the ambig flags. Same with setUTCValues with moment-timezone. 3173 3174 this._ambigZone = true; 3175 3176 } 3177 3178 3179 3180 return this; // for chaining 3181 3182 }; 3183 3184 3185 3186// Returns of the moment has a non-ambiguous timezone offset (boolean) 3187 3188 newMomentProto.hasZone = function() { 3189 3190 return !this._ambigZone; 3191 3192 }; 3193 3194 3195 3196 3197 3198// this method implicitly marks a zone 3199 3200 newMomentProto.local = function() { 3201 3202 var a = this.toArray(); // year,month,date,hours,minutes,seconds,ms as an array 3203 3204 var wasAmbigZone = this._ambigZone; 3205 3206 3207 3208 oldMomentProto.local.apply(this, arguments); 3209 3210 3211 3212 // ensure non-ambiguous 3213 3214 // this probably already happened via local() -> utcOffset(), but don't rely on Moment's internals 3215 3216 this._ambigTime = false; 3217 3218 this._ambigZone = false; 3219 3220 3221 3222 if (wasAmbigZone) { 3223 3224 // If the moment was ambiguously zoned, the date fields were stored as UTC. 3225 3226 // We want to preserve these, but in local time. 3227 3228 // TODO: look into Moment's keepLocalTime functionality 3229 3230 setLocalValues(this, a); 3231 3232 } 3233 3234 3235 3236 return this; // for chaining 3237 3238 }; 3239 3240 3241 3242 3243 3244// implicitly marks a zone 3245 3246 newMomentProto.utc = function() { 3247 3248 oldMomentProto.utc.apply(this, arguments); 3249 3250 3251 3252 // ensure non-ambiguous 3253 3254 // this probably already happened via utc() -> utcOffset(), but don't rely on Moment's internals 3255 3256 this._ambigTime = false; 3257 3258 this._ambigZone = false; 3259 3260 3261 3262 return this; 3263 3264 }; 3265 3266 3267 3268 3269 3270// methods for arbitrarily manipulating timezone offset. 3271 3272// should clear time/zone ambiguity when called. 3273 3274 $.each([ 3275 3276 'zone', // only in moment-pre-2.9. deprecated afterwards 3277 3278 'utcOffset' 3279 3280 ], function(i, name) { 3281 3282 if (oldMomentProto[name]) { // original method exists? 3283 3284 3285 3286 // this method implicitly marks a zone (will probably get called upon .utc() and .local()) 3287 3288 newMomentProto[name] = function(tzo) { 3289 3290 3291 3292 if (tzo != null) { // setter 3293 3294 // these assignments needs to happen before the original zone method is called. 3295 3296 // I forget why, something to do with a browser crash. 3297 3298 this._ambigTime = false; 3299 3300 this._ambigZone = false; 3301 3302 } 3303 3304 3305 3306 return oldMomentProto[name].apply(this, arguments); 3307 3308 }; 3309 3310 } 3311 3312 }); 3313 3314 3315 3316 3317 3318// Formatting 3319 3320// ------------------------------------------------------------------------------------------------- 3321 3322 3323 3324 newMomentProto.format = function() { 3325 3326 if (this._fullCalendar && arguments[0]) { // an enhanced moment? and a format string provided? 3327 3328 return formatDate(this, arguments[0]); // our extended formatting 3329 3330 } 3331 3332 if (this._ambigTime) { 3333 3334 return oldMomentFormat(this, 'YYYY-MM-DD'); 3335 3336 } 3337 3338 if (this._ambigZone) { 3339 3340 return oldMomentFormat(this, 'YYYY-MM-DD[T]HH:mm:ss'); 3341 3342 } 3343 3344 return oldMomentProto.format.apply(this, arguments); 3345 3346 }; 3347 3348 3349 3350 newMomentProto.toISOString = function() { 3351 3352 if (this._ambigTime) { 3353 3354 return oldMomentFormat(this, 'YYYY-MM-DD'); 3355 3356 } 3357 3358 if (this._ambigZone) { 3359 3360 return oldMomentFormat(this, 'YYYY-MM-DD[T]HH:mm:ss'); 3361 3362 } 3363 3364 return oldMomentProto.toISOString.apply(this, arguments); 3365 3366 }; 3367 3368 3369 3370 3371 3372// Querying 3373 3374// ------------------------------------------------------------------------------------------------- 3375 3376 3377 3378// Is the moment within the specified range? `end` is exclusive. 3379 3380// FYI, this method is not a standard Moment method, so always do our enhanced logic. 3381 3382 newMomentProto.isWithin = function(start, end) { 3383 3384 var a = commonlyAmbiguate([ this, start, end ]); 3385 3386 return a[0] >= a[1] && a[0] < a[2]; 3387 3388 }; 3389 3390 3391 3392// When isSame is called with units, timezone ambiguity is normalized before the comparison happens. 3393 3394// If no units specified, the two moments must be identically the same, with matching ambig flags. 3395 3396 newMomentProto.isSame = function(input, units) { 3397 3398 var a; 3399 3400 3401 3402 // only do custom logic if this is an enhanced moment 3403 3404 if (!this._fullCalendar) { 3405 3406 return oldMomentProto.isSame.apply(this, arguments); 3407 3408 } 3409 3410 3411 3412 if (units) { 3413 3414 a = commonlyAmbiguate([ this, input ], true); // normalize timezones but don't erase times 3415 3416 return oldMomentProto.isSame.call(a[0], a[1], units); 3417 3418 } 3419 3420 else { 3421 3422 input = FC.moment.parseZone(input); // normalize input 3423 3424 return oldMomentProto.isSame.call(this, input) && 3425 3426 Boolean(this._ambigTime) === Boolean(input._ambigTime) && 3427 3428 Boolean(this._ambigZone) === Boolean(input._ambigZone); 3429 3430 } 3431 3432 }; 3433 3434 3435 3436// Make these query methods work with ambiguous moments 3437 3438 $.each([ 3439 3440 'isBefore', 3441 3442 'isAfter' 3443 3444 ], function(i, methodName) { 3445 3446 newMomentProto[methodName] = function(input, units) { 3447 3448 var a; 3449 3450 3451 3452 // only do custom logic if this is an enhanced moment 3453 3454 if (!this._fullCalendar) { 3455 3456 return oldMomentProto[methodName].apply(this, arguments); 3457 3458 } 3459 3460 3461 3462 a = commonlyAmbiguate([ this, input ]); 3463 3464 return oldMomentProto[methodName].call(a[0], a[1], units); 3465 3466 }; 3467 3468 }); 3469 3470 3471 3472 3473 3474// Misc Internals 3475 3476// ------------------------------------------------------------------------------------------------- 3477 3478 3479 3480// given an array of moment-like inputs, return a parallel array w/ moments similarly ambiguated. 3481 3482// for example, of one moment has ambig time, but not others, all moments will have their time stripped. 3483 3484// set `preserveTime` to `true` to keep times, but only normalize zone ambiguity. 3485 3486// returns the original moments if no modifications are necessary. 3487 3488 function commonlyAmbiguate(inputs, preserveTime) { 3489 3490 var anyAmbigTime = false;
3491 3492 var anyAmbigZone = false; 3493 3494 var len = inputs.length; 3495 3496 var moms = []; 3497 3498 var i, mom; 3499 3500 3501 3502 // parse inputs into real moments and query their ambig flags 3503 3504 for (i = 0; i < len; i++) { 3505 3506 mom = inputs[i]; 3507 3508 if (!moment.isMoment(mom)) { 3509 3510 mom = FC.moment.parseZone(mom); 3511 3512 } 3513 3514 anyAmbigTime = anyAmbigTime || mom._ambigTime; 3515 3516 anyAmbigZone = anyAmbigZone || mom._ambigZone; 3517 3518 moms.push(mom); 3519 3520 } 3521 3522 3523 3524 // strip each moment down to lowest common ambiguity 3525 3526 // use clones to avoid modifying the original moments 3527 3528 for (i = 0; i < len; i++) { 3529 3530 mom = moms[i]; 3531 3532 if (!preserveTime && anyAmbigTime && !mom._ambigTime) { 3533 3534 moms[i] = mom.clone().stripTime(); 3535 3536 } 3537 3538 else if (anyAmbigZone && !mom._ambigZone) { 3539 3540 moms[i] = mom.clone().stripZone(); 3541 3542 } 3543 3544 } 3545 3546 3547 3548 return moms; 3549 3550 } 3551 3552 3553 3554// Transfers all the flags related to ambiguous time/zone from the `src` moment to the `dest` moment 3555 3556// TODO: look into moment.momentProperties for this. 3557 3558 function transferAmbigs(src, dest) { 3559 3560 if (src._ambigTime) { 3561 3562 dest._ambigTime = true; 3563 3564 } 3565 3566 else if (dest._ambigTime) { 3567 3568 dest._ambigTime = false; 3569 3570 } 3571 3572 3573 3574 if (src._ambigZone) { 3575 3576 dest._ambigZone = true; 3577 3578 } 3579 3580 else if (dest._ambigZone) { 3581 3582 dest._ambigZone = false; 3583 3584 } 3585 3586 } 3587 3588 3589 3590 3591 3592// Sets the year/month/date/etc values of the moment from the given array. 3593 3594// Inefficient because it calls each individual setter. 3595 3596 function setMomentValues(mom, a) { 3597 3598 mom.year(a[0] || 0) 3599 3600 .month(a[1] || 0) 3601 3602 .date(a[2] || 0) 3603 3604 .hours(a[3] || 0) 3605 3606 .minutes(a[4] || 0) 3607 3608 .seconds(a[5] || 0) 3609 3610 .milliseconds(a[6] || 0); 3611 3612 } 3613 3614 3615 3616// Can we set the moment's internal date directly? 3617 3618 allowValueOptimization = '_d' in moment() && 'updateOffset' in moment; 3619 3620 3621 3622// Utility function. Accepts a moment and an array of the UTC year/month/date/etc values to set. 3623 3624// Assumes the given moment is already in UTC mode. 3625 3626 setUTCValues = allowValueOptimization ? function(mom, a) { 3627 3628 // simlate what moment's accessors do 3629 3630 mom._d.setTime(Date.UTC.apply(Date, a)); 3631 3632 moment.updateOffset(mom, false); // keepTime=false 3633 3634 } : setMomentValues; 3635 3636 3637 3638// Utility function. Accepts a moment and an array of the local year/month/date/etc values to set. 3639 3640// Assumes the given moment is already in local mode. 3641 3642 setLocalValues = allowValueOptimization ? function(mom, a) { 3643 3644 // simlate what moment's accessors do 3645 3646 mom._d.setTime(+new Date( // FYI, there is now way to apply an array of args to a constructor 3647 3648 a[0] || 0, 3649 3650 a[1] || 0, 3651 3652 a[2] || 0, 3653 3654 a[3] || 0, 3655 3656 a[4] || 0, 3657 3658 a[5] || 0, 3659 3660 a[6] || 0 3661 3662 )); 3663 3664 moment.updateOffset(mom, false); // keepTime=false 3665 3666 } : setMomentValues; 3667 3668 3669 3670 ;; 3671 3672 3673 3674// Single Date Formatting 3675 3676// ------------------------------------------------------------------------------------------------- 3677 3678 3679 3680 3681 3682// call this if you want Moment's original format method to be used 3683 3684 function oldMomentFormat(mom, formatStr) { 3685 3686 return oldMomentProto.format.call(mom, formatStr); // oldMomentProto defined in moment-ext.js 3687 3688 } 3689 3690 3691 3692 3693 3694// Formats `date` with a Moment formatting string, but allow our non-zero areas and 3695 3696// additional token. 3697 3698 function formatDate(date, formatStr) { 3699 3700 return formatDateWithChunks(date, getFormatStringChunks(formatStr)); 3701 3702 } 3703 3704 3705 3706 3707 3708 function formatDateWithChunks(date, chunks) { 3709 3710 var s = ''; 3711 3712 var i; 3713 3714 3715 3716 for (i=0; i<chunks.length; i++) { 3717 3718 s += formatDateWithChunk(date, chunks[i]); 3719 3720 } 3721 3722 3723 3724 return s; 3725 3726 } 3727 3728 3729 3730 3731 3732// addition formatting tokens we want recognized 3733 3734 var tokenOverrides = { 3735 3736 t: function(date) { // "a" or "p" 3737 3738 return oldMomentFormat(date, 'a').charAt(0); 3739 3740 }, 3741 3742 T: function(date) { // "A" or "P" 3743 3744 return oldMomentFormat(date, 'A').charAt(0); 3745 3746 } 3747 3748 }; 3749 3750 3751 3752 3753 3754 function formatDateWithChunk(date, chunk) { 3755 3756 var token; 3757 3758 var maybeStr; 3759 3760 3761 3762 if (typeof chunk === 'string') { // a literal string 3763 3764 return chunk; 3765 3766 } 3767 3768 else if ((token = chunk.token)) { // a token, like "YYYY" 3769 3770 if (tokenOverrides[token]) { 3771 3772 return tokenOverrides[token](date); // use our custom token 3773 3774 } 3775 3776 return oldMomentFormat(date, token); 3777 3778 } 3779 3780 else if (chunk.maybe) { // a grouping of other chunks that must be non-zero 3781 3782 maybeStr = formatDateWithChunks(date, chunk.maybe); 3783 3784 if (maybeStr.match(/[1-9]/)) { 3785 3786 return maybeStr; 3787 3788 } 3789 3790 } 3791 3792 3793 3794 return ''; 3795 3796 } 3797 3798 3799 3800 3801 3802// Date Range Formatting 3803 3804// ------------------------------------------------------------------------------------------------- 3805 3806// TODO: make it work with timezone offset 3807 3808 3809 3810// Using a formatting string meant for a single date, generate a range str
3810ing, like 3811 3812// "Sep 2 - 9 2013", that intelligently inserts a separator where the dates differ. 3813 3814// If the dates are the same as far as the format string is concerned, just return a single 3815 3816// rendering of one date, without any separator. 3817 3818 function formatRange(date1, date2, formatStr, separator, isRTL) { 3819 3820 var localeData; 3821 3822 3823 3824 date1 = FC.moment.parseZone(date1); 3825 3826 date2 = FC.moment.parseZone(date2); 3827 3828 3829 3830 localeData = (date1.localeData || date1.lang).call(date1); // works with moment-pre-2.8 3831 3832 3833 3834 // Expand localized format strings, like "LL" -> "MMMM D YYYY" 3835 3836 formatStr = localeData.longDateFormat(formatStr) || formatStr; 3837 3838 // BTW, this is not important for `formatDate` because it is impossible to put custom tokens 3839 3840 // or non-zero areas in Moment's localized format strings. 3841 3842 3843 3844 separator = separator || ' - '; 3845 3846 3847 3848 return formatRangeWithChunks( 3849 3850 date1, 3851 3852 date2, 3853 3854 getFormatStringChunks(formatStr), 3855 3856 separator, 3857 3858 isRTL 3859 3860 ); 3861 3862 } 3863 3864 FC.formatRange = formatRange; // expose 3865 3866 3867 3868 3869 3870 function formatRangeWithChunks(date1, date2, chunks, separator, isRTL) { 3871 3872 var unzonedDate1 = date1.clone().stripZone(); // for formatSimilarChunk 3873 3874 var unzonedDate2 = date2.clone().stripZone(); // " 3875 3876 var chunkStr; // the rendering of the chunk 3877 3878 var leftI; 3879 3880 var leftStr = ''; 3881 3882 var rightI; 3883 3884 var rightStr = ''; 3885 3886 var middleI; 3887 3888 var middleStr1 = ''; 3889 3890 var middleStr2 = ''; 3891 3892 var middleStr = ''; 3893 3894 3895 3896 // Start at the leftmost side of the formatting string and continue until you hit a token 3897 3898 // that is not the same between dates. 3899 3900 for (leftI=0; leftI<chunks.length; leftI++) { 3901 3902 chunkStr = formatSimilarChunk(date1, date2, unzonedDate1, unzonedDate2, chunks[leftI]); 3903 3904 if (chunkStr === false) { 3905 3906 break; 3907 3908 } 3909 3910 leftStr += chunkStr; 3911 3912 } 3913 3914 3915 3916 // Similarly, start at the rightmost side of the formatting string and move left 3917 3918 for (rightI=chunks.length-1; rightI>leftI; rightI--) { 3919 3920 chunkStr = formatSimilarChunk(date1, date2, unzonedDate1, unzonedDate2, chunks[rightI]); 3921 3922 if (chunkStr === false) { 3923 3924 break; 3925 3926 } 3927 3928 rightStr = chunkStr + rightStr; 3929 3930 } 3931 3932 3933 3934 // The area in the middle is different for both of the dates. 3935 3936 // Collect them distinctly so we can jam them together later. 3937 3938 for (middleI=leftI; middleI<=rightI; middleI++) { 3939 3940 middleStr1 += formatDateWithChunk(date1, chunks[middleI]); 3941 3942 middleStr2 += formatDateWithChunk(date2, chunks[middleI]); 3943 3944 } 3945 3946 3947 3948 if (middleStr1 || middleStr2) { 3949 3950 if (isRTL) { 3951 3952 middleStr = middleStr2 + separator + middleStr1; 3953 3954 } 3955 3956 else { 3957 3958 middleStr = middleStr1 + separator + middleStr2; 3959 3960 } 3961 3962 } 3963 3964 3965 3966 return leftStr + middleStr + rightStr; 3967 3968 } 3969 3970 3971 3972 3973 3974 var similarUnitMap = { 3975 3976 Y: 'year', 3977 3978 M: 'month', 3979 3980 D: 'day', // day of month 3981 3982 d: 'day', // day of week 3983 3984 // prevents a separator between anything time-related... 3985 3986 A: 'second', // AM/PM 3987 3988 a: 'second', // am/pm 3989 3990 T: 'second', // A/P 3991
3992 t: 'second', // a/p 3993 3994 H: 'second', // hour (24) 3995 3996 h: 'second', // hour (12) 3997 3998 m: 'second', // minute 3999 4000 s: 'second' // second 4001 4002 }; 4003 4004// TODO: week maybe? 4005 4006 4007 4008 4009 4010// Given a formatting chunk, and given that both dates are similar in the regard the 4011 4012// formatting chunk is concerned, format date1 against `chunk`. Otherwise, return `false`. 4013 4014 function formatSimilarChunk(date1, date2, unzonedDate1, unzonedDate2, chunk) { 4015 4016 var token; 4017 4018 var unit; 4019 4020 4021 4022 if (typeof chunk === 'string') { // a literal string 4023 4024 return chunk; 4025 4026 } 4027 4028 else if ((token = chunk.token)) { 4029 4030 unit = similarUnitMap[token.charAt(0)]; 4031 4032 4033 4034 // are the dates the same for this unit of measurement? 4035 4036 // use the unzoned dates for this calculation because unreliable when near DST (bug #2396) 4037 4038 if (unit && unzonedDate1.isSame(unzonedDate2, unit)) { 4039 4040 return oldMomentFormat(date1, token); // would be the same if we used `date2` 4041 4042 // BTW, don't support custom tokens 4043 4044 } 4045 4046 } 4047 4048 4049 4050 return false; // the chunk is NOT the same for the two dates 4051 4052 // BTW, don't support splitting on non-zero areas 4053 4054 } 4055 4056 4057 4058 4059 4060// Chunking Utils 4061 4062// ------------------------------------------------------------------------------------------------- 4063 4064 4065 4066 4067 4068 var formatStringChunkCache = {}; 4069 4070 4071 4072 4073 4074 function getFormatStringChunks(formatStr) { 4075 4076 if (formatStr in formatStringChunkCache) { 4077 4078 return formatStringChunkCache[formatStr]; 4079 4080 } 4081 4082 return (formatStringChunkCache[formatStr] = chunkFormatString(formatStr)); 4083 4084 } 4085 4086 4087 4088 4089 4090// Break the formatting string into an array of chunks 4091 4092 function chunkFormatString(formatStr) { 4093 4094 var chunks = []; 4095 4096 var chunker = /\[([^\]]*)\]|\(([^\)]*)\)|(LTS|LT|(\w)\4*o?)|([^\w\[\(]+)/g; // TODO: more descrimination 4097 4098 var match; 4099 4100 4101 4102 while ((match = chunker.exec(formatStr))) { 4103 4104 if (match[1]) { // a literal string inside [ ... ] 4105 4106 chunks.push(match[1]); 4107 4108 } 4109 4110 else if (match[2]) { // non-zero formatting inside ( ... ) 4111 4112 chunks.push({ maybe: chunkFormatString(match[2]) }); 4113 4114 } 4115 4116 else if (match[3]) { // a formatting token 4117 4118 chunks.push({ token: match[3] }); 4119 4120 } 4121 4122 else if (match[5]) { // an unenclosed literal string 4123 4124 chunks.push(match[5]); 4125 4126 } 4127 4128 } 4129 4130 4131 4132 return chunks; 4133 4134 } 4135 4136 4137 4138 ;; 4139 4140 4141 4142 FC.Class = Class; // export 4143 4144 4145 4146// Class that all other classes will inherit from 4147 4148 function Class() { } 4149 4150 4151 4152 4153 4154// Called on a class to create a subclass. 4155 4156// Last argument contains instance methods. Any argument before the last are considered mixins. 4157 4158 Class.extend = function() { 4159 4160 var len = arguments.length; 4161 4162 var i; 4163 4164 var members; 4165 4166 4167 4168 for (i = 0; i < len; i++) { 4169 4170 members = arguments[i]; 4171 4172 if (i < len - 1) { // not the last argument? 4173 4174 mixIntoClass(this, members); 4175 4176 } 4177 4178 } 4179 4180 4181 4182 return extendClass(this, members || {}); // members will be undefined if no arguments 4183 4184 }; 4185 4186 4187 4188 4189 4190// Adds new member variables/methods to the class's prototype. 4191 4192// Can be called with another class, or a plain object hash containing new members. 4193 4194 Class.mixin = function(members) { 4195 4196 mixIntoClass(this, members); 4197 4198 }; 4199 4200 4201 4202 4203 4204 function extendClass(superClass, members) { 4205 4206 var subClass; 4207 4208 4209 4210 // ensure a constructor for the subclass, forwarding all arguments to the super-constructor if it doesn't exist 4211 4212 if (hasOwnProp(members, 'constructor')) { 4213 4214 subClass = members.constructor; 4215 4216 } 4217 4218 if (typeof subClass !== 'function') { 4219 4220 subClass = members.constructor = function() { 4221 4222 superClass.apply(this, arguments); 4223 4224 }; 4225 4226 } 4227 4228 4229 4230 // build the base prototype for the subclass, which is an new object chained to the superclass's prototype 4231 4232 subClass.prototype = createObject(superClass.prototype); 4233 4234 4235 4236 // copy each member variable/method onto the the subclass's prototype 4237 4238 copyOwnProps(members, subClass.prototype); 4239 4240 copyNativeMethods(members, subClass.prototype); // hack for IE8 4241 4242 4243 4244 // copy over all class variables/methods to the subclass, such as `extend` and `mixin` 4245 4246 copyOwnProps(superClass, subClass); 4247 4248 4249 4250 return subClass; 4251 4252 } 4253 4254 4255 4256 4257 4258 function mixIntoClass(theClass, members) { 4259 4260 copyOwnProps(members.prototype || members, theClass.prototype); // TODO: copyNativeMethods? 4261 4262 } 4263 4264 ;; 4265 4266 4267 4268 var Emitter = FC.Emitter = Class.extend({ 4269 4270 4271 4272 callbackHash: null, 4273 4274 4275 4276 4277 4278 on: function(name, callback) { 4279 4280 this.getCallbacks(name).add(callback); 4281 4282 return this; // for chaining 4283 4284 }, 4285 4286 4287 4288 4289 4290 off: function(name, callback) { 4291 4292 this.getCallbacks(name).remove(callback); 4293 4294 return this; // for chaining 4295 4296 }, 4297 4298 4299 4300 4301 4302 trigger: function(name) { // args... 4303 4304 var args = Array.prototype.slice.call(arguments, 1); 4305 4306 4307 4308 this.triggerWith(name, this, args); 4309 4310 4311 4312 return this; // for chaining 4313 4314 }, 4315 4316 4317 4318 4319
4320 triggerWith: function(name, context, args) { 4321 4322 var callbacks = this.getCallbacks(name); 4323 4324 4325 4326 callbacks.fireWith(context, args); 4327 4328 4329 4330 return this; // for chaining 4331 4332 }, 4333 4334 4335 4336 4337 4338 getCallbacks: function(name) { 4339 4340 var callbacks; 4341 4342 4343 4344 if (!this.callbackHash) { 4345 4346 this.callbackHash = {}; 4347 4348 } 4349 4350 4351 4352 callbacks = this.callbackHash[name]; 4353 4354 if (!callbacks) { 4355 4356 callbacks = this.callbackHash[name] = $.Callbacks(); 4357 4358 } 4359 4360 4361 4362 return callbacks; 4363 4364 } 4365 4366 4367 4368 }); 4369 4370 ;; 4371 4372 4373 4374 /* A rectangular panel that is absolutely positioned over other content 4375 4376 ------------------------------------------------------------------------------------------------------------------------ 4377 4378 Options: 4379 4380 - className (string) 4381 4382 - content (HTML string or jQuery element set) 4383 4384 - parentEl 4385 4386 - top 4387 4388 - left 4389 4390 - right (the x coord of where the right edge should be. not a "CSS" right) 4391 4392 - autoHide (boolean) 4393 4394 - show (callback) 4395 4396 - hide (callback) 4397 4398 */ 4399 4400 4401 4402 var Popover = Class.extend({ 4403 4404 4405 4406 isHidden: true, 4407 4408 options: null, 4409 4410 el: null, // the container element for the popover. generated by this object 4411 4412 documentMousedownProxy: null, // document mousedown handler bound to `this` 4413 4414 margin: 10, // the space required between the popover and the edges of the scroll container 4415 4416 4417 4418 4419 4420 constructor: function(options) { 4421 4422 this.options = options || {}; 4423 4424 }, 4425 4426 4427 4428 4429 4430 // Shows the popover on the specified position. Renders it if not already 4431 4432 show: function() { 4433 4434 if (this.isHidden) { 4435 4436 if (!this.el) { 4437 4438 this.render(); 4439 4440 } 4441 4442 this.el.show(); 4443 4444 this.position(); 4445 4446 this.isHidden = false; 4447 4448 this.trigger('show'); 4449 4450 } 4451 4452 }, 4453 4454 4455 4456 4457 4458 // Hides the popover, through CSS, but does not remove it from the DOM 4459 4460 hide: function() { 4461 4462 if (!this.isHidden) { 4463 4464 this.el.hide(); 4465 4466 this.isHidden = true; 4467 4468 this.trigger('hide'); 4469 4470 } 4471 4472 }, 4473 4474 4475 4476 4477 4478 // Creates `this.el` and renders content inside of it 4479 4480 render: function() { 4481 4482 var _this = this; 4483 4484 var options = this.options; 4485 4486 4487 4488 this.el = $('<div class="fc-popover"/>') 4489 4490 .addClass(options.className || '') 4491 4492 .css({ 4493 4494 // position initially to the top left to avoid creating scrollbars 4495 4496 top: 0, 4497 4498 left: 0 4499 4500 }) 4501 4502 .append(options.content) 4503 4504 .appendTo(options.parentEl); 4505 4506 4507 4508 // when a click happens on anything inside with a 'fc-close' className, hide the popover 4509 4510 this.el.on('click', '.fc-close', function() { 4511 4512 _this.hide(); 4513 4514 }); 4515 4516 4517 4518 if (options.autoHide) { 4519 4520 $(document).on('mousedown', this.documentMousedownProxy = proxy(this, 'documentMousedown')); 4521 4522 } 4523 4524 }, 4525 4526 4527 4528 4529 4530 // Triggered when the user clicks *anywhere* in the document, for the autoHide feature 4531 4532 documentMousedown: function(ev) { 4533 4534 // only hide the popover if the click happened outside the popover 4535 4536 if (this.el && !$(ev.target).closest(this.el).length) { 4537 4538 this.hide(); 4539 4540 } 4541 4542 }, 4543 4544 4545 4546 4547 4548 // Hides and unregisters any handlers 4549 4550 removeElement: function() { 4551 4552 this.hide(); 4553 4554 4555 4556 if (this.el) { 4557 4558 this.el.remove(); 4559 4560 this.el = null; 4561 4562 } 4563 4564 4565 4566 $(document).off('mousedown', this.documentMousedownProxy); 4567 4568 }, 4569 4570 4571 4572 4573 4574 // Positions the popover optimally, using the top/left/right options 4575 4576 position: function() { 4577 4578 var options = this.options; 4579 4580 var origin = this.el.offsetParent().offset(); 4581 4582 var width = this.el.outerWidth(); 4583 4584 var height = this.el.outerHeight(); 4585 4586 var windowEl = $(window); 4587 4588 var viewportEl = getScrollParent(this.el); 4589 4590 var viewportTop; 4591 4592 var viewportLeft; 4593 4594 var viewportOffset; 4595 4596 var top; // the "position" (not "offset") values for the popover 4597 4598 var left; // 4599 4600 4601 4602 // compute top and left 4603 4604 top = options.top || 0; 4605 4606 if (options.left !== undefined) { 4607 4608 left = options.left; 4609 4610 } 4611 4612 else if (options.right !== undefined) { 4613 4614 left = options.right - width; // derive the left value from the right value 4615 4616 } 4617 4618 else { 4619 4620 left = 0; 4621 4622 } 4623 4624 4625 4626 if (viewportEl.is(window) || viewportEl.is(document)) { // normalize getScrollParent's result 4627 4628 viewportEl = windowEl; 4629 4630 viewportTop = 0; // the window is always at the top left 4631 4632 viewportLeft = 0; // (and .offset() won't work if called here) 4633 4634 } 4635 4636 else { 4637 4638 viewportOffset = viewportEl.offset(); 4639 4640 viewportTop = viewportOffset.top; 4641 4642 viewportLeft = viewportOffset.left; 4643 4644 } 4645 4646 4647 4648 // if the window is scrolled, it causes the visible area to be further down 4649 4650 viewportTop += windowEl.scrollTop(); 4651 4652 viewportLeft += windowEl.scrollLeft(); 4653 4654 4655 4656 // constrain to the view port. if constrained by two edges, give precedence to top/left 4657 4658 if (options.viewportConstrain !== false) { 4659 4660 top = Math.min(top, viewportTop + viewportEl.outerHeight() - height - this.margin); 4661 4662 top = Math.max(top, viewportTop + this.margin); 4663 4664 left = Math.min(left, viewportLeft + viewportEl.outerWidth() - width - this.margin); 4665 4666 left = Math.max(left, viewportLeft + this.margin); 4667 4668 } 4669 4670 4671 4672 this.el.css({ 4673 4674 top: top - origin.top, 4675 4676 left: left - origin.left 4677 4678 }); 4679 4680 }, 4681 4682 4683 4684 4685 4686 // Triggers a callback. Calls a function in the option hash of the same name. 4687 4688 // Arguments beyond the first `name` are forwarded on. 4689 4690 // TODO: better code reuse for this. Repeat code 4691 4692 trigger: function(name) { 4693 4694 if (this.options[name]) { 4695 4696 this.options[name].apply(this, Array.prototype.slice.call(arguments, 1)); 4697 4698 } 4699 4700 } 4701 4702 4703 4704 }); 4705 4706 4707 4708 ;; 4709 4710 4711 4712 /* 4713
4714 A cache for the left/right/top/bottom/width/height values for one or more elements. 4715 4716 Works with both offset (from topleft document) and position (from offsetParent). 4717 4718 4719 4720 options: 4721 4722 - els 4723 4724 - isHorizontal 4725 4726 - isVertical 4727 4728 */ 4729 4730 var CoordCache = FC.CoordCache = Class.extend({ 4731 4732 4733 4734 els: null, // jQuery set (assumed to be siblings) 4735 4736 forcedOffsetParentEl: null, // options can override the natural offsetParent 4737 4738 origin: null, // {left,top} position of offsetParent of els 4739 4740 boundingRect: null, // constrain cordinates to this rectangle. {left,right,top,bottom} or null 4741 4742 isHorizontal: false, // whether to query for left/right/width 4743 4744 isVertical: false, // whether to query for top/bottom/height 4745 4746 4747 4748 // arrays of coordinates (offsets from topleft of document) 4749 4750 lefts: null, 4751 4752 rights: null, 4753 4754 tops: null, 4755 4756 bottoms: null, 4757 4758 4759 4760 4761 4762 constructor: function(options) { 4763 4764 this.els = $(options.els); 4765 4766 this.isHorizontal = options.isHorizontal; 4767 4768 this.isVertical = options.isVertical; 4769 4770 this.forcedOffsetParentEl = options.offsetParent ? $(options.offsetParent) : null; 4771 4772 }, 4773 4774 4775 4776 4777 4778 // Queries the els for coordinates and stores them. 4779 4780 // Call this method before using and of the get* methods below. 4781 4782 build: function() { 4783 4784 var offsetParentEl = this.forcedOffsetParentEl || this.els.eq(0).offsetParent(); 4785 4786 4787 4788 this.origin = offsetParentEl.offset(); 4789
4790 this.boundingRect = this.queryBoundingRect(); 4791 4792 4793 4794 if (this.isHorizontal) { 4795 4796 this.buildElHorizontals(); 4797 4798 } 4799 4800 if (this.isVertical) { 4801 4802 this.buildElVerticals(); 4803 4804 } 4805 4806 }, 4807 4808 4809 4810 4811 4812 // Destroys all internal data about coordinates, freeing memory 4813 4814 clear: function() { 4815 4816 this.origin = null; 4817 4818 this.boundingRect = null; 4819 4820 this.lefts = null; 4821 4822 this.rights = null; 4823 4824 this.tops = null; 4825 4826 this.bottoms = null; 4827 4828 }, 4829 4830 4831 4832 4833 4834 // Compute and return what the elements' bounding rectangle is, from the user's perspective. 4835 4836 // Right now, only returns a rectangle if constrained by an overflow:scroll element. 4837 4838 queryBoundingRect: function() { 4839 4840 var scrollParentEl = getScrollParent(this.els.eq(0)); 4841 4842 4843 4844 if (!scrollParentEl.is(document)) { 4845 4846 return getClientRect(scrollParentEl); 4847 4848 } 4849 4850 }, 4851 4852 4853 4854 4855 4856 // Populates the left/right internal coordinate arrays 4857 4858 buildElHorizontals: function() { 4859 4860 var lefts = []; 4861 4862 var rights = []; 4863 4864 4865 4866 this.els.each(function(i, node) { 4867 4868 var el = $(node); 4869 4870 var left = el.offset().left; 4871 4872 var width = el.outerWidth(); 4873 4874 4875 4876 lefts.push(left); 4877 4878 rights.push(left + width); 4879 4880 }); 4881 4882 4883 4884 this.lefts = lefts; 4885 4886 this.rights = rights; 4887 4888 }, 4889 4890 4891 4892 4893 4894 // Populates the top/bottom internal coordinate arrays 4895 4896 buildElVerticals: function() { 4897 4898 var tops = []; 4899 4900 var bottoms = []; 4901 4902 4903 4904 this.els.each(function(i, node) { 4905 4906 var el = $(node); 4907 4908 var top = el.offset().top; 4909 4910 var height = el.outerHeight(); 4911 4912 4913 4914 tops.push(top); 4915 4916 bottoms.push(top + height); 4917 4918 }); 4919 4920 4921 4922 this.tops = tops; 4923 4924 this.bottoms = bottoms; 4925 4926 }, 4927 4928 4929 4930 4931 4932 // Given a left offset (from document left), returns the index of the el that it horizontally intersects. 4933 4934 // If no intersection is made, or outside of the boundingRect, returns undefined. 4935 4936 getHorizontalIndex: function(leftOffset) { 4937 4938 var boundingRect = this.boundingRect; 4939 4940 var lefts = this.lefts; 4941 4942 var rights = this.rights; 4943 4944 var len = lefts.length; 4945 4946 var i; 4947 4948 4949 4950 if (!boundingRect || (leftOffset >= boundingRect.left && leftOffset < boundingRect.right)) { 4951 4952 for (i = 0; i < len; i++) { 4953 4954 if (leftOffset >= lefts[i] && leftOffset < rights[i]) { 4955 4956 return i; 4957 4958 } 4959 4960 } 4961 4962 } 4963 4964 }, 4965 4966 4967 4968 4969 4970 // Given a top offset (from document top), returns the index of the el that it vertically intersects. 4971 4972 // If no intersection is made, or outside of the boundingRect, returns undefined. 4973 4974 getVerticalIndex: function(topOffset) { 4975 4976 var boundingRect = this.boundingRect; 4977 4978 var tops = this.tops; 4979 4980 var bottoms = this.bottoms; 4981 4982 var len = tops.length; 4983 4984 var i; 4985 4986 4987 4988 if (!boundingRect || (topOffset >= boundingRect.top && topOffset < boundingRect.bottom)) { 4989 4990 for (i = 0; i < len; i++) { 4991 4992 if (topOffset >= tops[i] && topOffset < bottoms[i]) { 4993 4994 return i; 4995 4996 } 4997 4998 } 4999 5000 } 5001 5002 }, 5003 5004 5005 5006 5007 5008 // Gets the left offset (from document left) of the element at the given index 5009 5010 getLeftOffset: function(leftIndex) { 5011 5012 return this.lefts[leftIndex]; 5013 5014 }, 5015 5016 5017 5018 5019 5020 // Gets the left position (from offsetParent left) of the element at the given index 5021 5022 getLeftPosition: function(leftIndex) { 5023 5024 return this.lefts[leftIndex] - this.origin.left; 5025 5026 }, 5027 5028 5029 5030 5031 5032 // Gets the right offset (from document left) of the element at the given index. 5033 5034 // This value is NOT relative to the document's right edge, like the CSS concept of "right" would be. 5035 5036 getRightOffset: function(leftIndex) { 5037 5038 return this.rights[leftIndex]; 5039 5040 }, 5041 5042 5043 5044 5045 5046 // Gets the right position (from offsetParent left) of the element at the given index. 5047 5048 // This value is NOT relative to the offsetParent's right edge, like the CSS concept of "right" would be. 5049 5050 getRightPosition: function(leftIndex) { 5051 5052 return this.rights[leftIndex] - this.origin.left; 5053 5054 }, 5055 5056 5057 5058 5059 5060 // Gets the width of the element at the given index 5061 5062 getWidth: function(leftIndex) { 5063 5064 return this.rights[leftIndex] - this.lefts[leftIndex]; 5065 5066 }, 5067 5068 5069 5070 5071 5072 // Gets the top offset (from document top) of the element at the given index 5073 5074 getTopOffset: function(topIndex) { 5075 5076 return this.tops[topIndex]; 5077 5078 }, 5079 5080 5081 5082 5083 5084 // Gets the top position (from offsetParent top) of the element at the given position 5085 5086 getTopPosition: function(topIndex) { 5087 5088 return this.tops[topIndex] - this.origin.top; 5089 5090 }, 5091 5092 5093 5094 // Gets the bottom offset (from the document top) of the element at the given index. 5095 5096 // This value is NOT relative to the offsetParent's bottom edge, like the CSS concept of "bottom" would be. 5097 5098 getBottomOffset: function(topIndex) { 5099 5100 return this.bottoms[topIndex]; 5101 5102 }, 5103 5104 5105 5106 5107 5108 // Gets the bottom position (from the offsetParent top) of the element at the given index. 5109 5110 // This value is NOT relative to the offsetParent's bottom edge, like the CSS concept of "bottom" would be. 5111 5112 getBottomPosition: function(topIndex) { 5113 5114 return this.bottoms[topIndex] - this.origin.top; 5115 5116 }, 5117 5118 5119 5120 5121 5122 // Gets the height of the element at the given index 5123 5124 getHeight: function(topIndex) { 5125 5126 return this.bottoms[topIndex] - this.tops[topIndex]; 5127 5128 } 5129 5130 5131 5132 }); 5133 5134 5135 5136 ;; 5137 5138 5139 5140 /* Tracks a drag's mouse movement, firing various handlers 5141 5142 ----------------------------------------------------------------------------------------------------------------------*/ 5143 5144// TODO: use Emitter 5145 5146 5147 5148 var DragListener = FC.DragListener = Class.extend({ 5149 5150 5151 5152 options: null, 5153 5154 5155 5156 isListening: false, 5157 5158 isDragging: false, 5159 5160 5161
5162 // coordinates of the initial mousedown 5163 5164 originX: null, 5165 5166 originY: null, 5167 5168 5169 5170 // handler attached to the document, bound to the DragListener's `this` 5171 5172 mousemoveProxy: null, 5173 5174 mouseupProxy: null, 5175 5176 5177 5178 // for IE8 bug-fighting behavior, for now 5179 5180 subjectEl: null, // the element being draged. optional 5181 5182 subjectHref: null, 5183 5184 5185 5186 scrollEl: null, 5187 5188 scrollBounds: null, // { top, bottom, left, right } 5189 5190 scrollTopVel: null, // pixels per second 5191 5192 scrollLeftVel: null, // pixels per second 5193 5194 scrollIntervalId: null, // ID of setTimeout for scrolling animation loop 5195 5196 scrollHandlerProxy: null, // this-scoped function for handling when scrollEl is scrolled 5197 5198 5199 5200 scrollSensitivity: 30, // pixels from edge for scrolling to start 5201 5202 scrollSpeed: 200, // pixels per second, at maximum speed 5203 5204 scrollIntervalMs: 50, // millisecond wait between scroll increment 5205 5206 5207 5208 5209 5210 constructor: function(options) { 5211 5212 options = options || {}; 5213 5214 this.options = options; 5215 5216 this.subjectEl = options.subjectEl; 5217 5218 }, 5219 5220 5221 5222 5223 5224 // Call this when the user does a mousedown. Will probably lead to startListening 5225 5226 mousedown: function(ev) { 5227 5228 if (isPrimaryMouseButton(ev)) { 5229 5230 5231 5232 ev.preventDefault(); // prevents native selection in most browsers 5233 5234 5235 5236 this.startListening(ev); 5237 5238 5239 5240 // start the drag immediately if there is no minimum distance for a drag start 5241 5242 if (!this.options.distance) { 5243 5244 this.startDrag(ev); 5245 5246 } 5247 5248 } 5249 5250 }, 5251 5252 5253 5254 5255 5256 // Call this to start tracking mouse movements 5257 5258 startListening: function(ev) { 5259 5260 var scrollParent; 5261 5262 5263 5264 if (!this.isListening) { 5265 5266 5267 5268 // grab scroll container and attach handler 5269 5270 if (ev && this.options.scroll) { 5271 5272 scrollParent = getScrollParent($(ev.target)); 5273 5274 if (!scrollParent.is(window) && !scrollParent.is(document)) { 5275 5276 this.scrollEl = scrollParent; 5277 5278 5279 5280 // scope to `this`, and use `debounce` to make sure rapid calls don't happen 5281 5282 this.scrollHandlerProxy = debounce(proxy(this, 'scrollHandler'), 100); 5283 5284 this.scrollEl.on('scroll', this.scrollHandlerProxy); 5285 5286 } 5287 5288 } 5289 5290 5291 5292 $(document) 5293 5294 .on('mousemove', this.mousemoveProxy = proxy(this, 'mousemove')) 5295 5296 .on('mouseup', this.mouseupProxy = proxy(this, 'mouseup')) 5297 5298 .on('selectstart', this.preventDefault); // prevents native selection in IE<=8 5299 5300 5301 5302 if (ev) { 5303 5304 this.originX = ev.pageX; 5305 5306 this.originY = ev.pageY; 5307 5308 } 5309 5310 else { 5311 5312 // if no starting information was given, origin will be the topleft corner of the screen. 5313 5314 // if so, dx/dy in the future will be the absolute coordinates. 5315 5316 this.originX = 0; 5317 5318 this.originY = 0; 5319 5320 } 5321 5322 5323 5324 this.isListening = true; 5325 5326 this.listenStart(ev); 5327 5328 } 5329 5330 }, 5331 5332 5333 5334 5335 5336 // Called when drag listening has started (but a real drag has not necessarily began) 5337 5338 listenStart: function(ev) { 5339 5340 this.trigger('listenStart', ev); 5341 5342 }, 5343 5344 5345 5346 5347 5348 // Called when the user moves the mouse 5349 5350 mousemove: function(ev) { 5351 5352 var dx = ev.pageX - this.originX; 5353 5354 var dy = ev.pageY - this.originY; 5355 5356 var minDistance; 5357 5358 var distanceSq; // current distance from the origin, squared 5359 5360 5361 5362 if (!this.isDragging) { // if not already dragging... 5363 5364 // then start the drag if the minimum distance criteria is met 5365 5366 minDistance = this.options.distance || 1; 5367 5368 distanceSq = dx * dx + dy * dy; 5369 5370 if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem 5371 5372 this.startDrag(ev); 5373 5374 } 5375 5376 } 5377 5378 5379 5380 if (this.isDragging) { 5381 5382 this.drag(dx, dy, ev); // report a drag, even if this mousemove initiated the drag 5383 5384 } 5385 5386 }, 5387 5388 5389 5390 5391 5392 // Call this to initiate a legitimate drag. 5393 5394 // This function is called internally from this class, but can also be called explicitly from outside 5395 5396 startDrag: function(ev) { 5397 5398 5399 5400 if (!this.isListening) { // startDrag must have manually initiated 5401 5402 this.startListening(); 5403 5404 } 5405 5406 5407 5408 if (!this.isDragging) { 5409 5410 this.isDragging = true; 5411 5412 this.dragStart(ev); 5413 5414 } 5415 5416 }, 5417 5418 5419 5420 5421 5422 // Called when the actual drag has started (went beyond minDistance) 5423 5424 dragStart: function(ev) { 5425 5426 var subjectEl = this.subjectEl; 5427 5428 5429 5430 this.trigger('dragStart', ev); 5431 5432 5433 5434 // remove a mousedown'd <a>'s href so it is not visited (IE8 bug) 5435 5436 if ((this.subjectHref = subjectEl ? subjectEl.attr('href') : null)) { 5437 5438 subjectEl.removeAttr('href'); 5439 5440 } 5441 5442 }, 5443 5444 5445 5446 5447 5448 // Called while the mouse is being moved and when we know a legitimate drag is taking place 5449 5450 drag: function(dx, dy, ev) { 5451 5452 this.trigger('drag', dx, dy, ev); 5453 5454 this.updateScroll(ev); // will possibly cause scrolling 5455 5456 }, 5457 5458 5459 5460 5461 5462 // Called when the user does a mouseup 5463 5464 mouseup: function(ev) { 5465 5466 this.stopListening(ev); 5467 5468 }, 5469 5470 5471 5472 5473 5474 // Called when the drag is over. Will not cause listening to stop however. 5475 5476 // A concluding 'cellOut' event will NOT be triggered. 5477 5478 stopDrag: function(ev) { 5479 5480 if (this.isDragging) { 5481 5482 this.stopScrolling(); 5483 5484 this.dragStop(ev); 5485 5486 this.isDragging = false;
5487 5488 } 5489 5490 }, 5491 5492 5493 5494 5495 5496 // Called when dragging has been stopped 5497 5498 dragStop: function(ev) { 5499 5500 var _this = this; 5501 5502 5503 5504 this.trigger('dragStop', ev); 5505 5506 5507 5508 // restore a mousedown'd <a>'s href (for IE8 bug) 5509 5510 setTimeout(function() { // must be outside of the click's execution 5511 5512 if (_this.subjectHref) { 5513 5514 _this.subjectEl.attr('href', _this.subjectHref); 5515 5516 } 5517 5518 }, 0); 5519 5520 }, 5521 5522 5523 5524 5525 5526 // Call this to stop listening to the user's mouse events 5527 5528 stopListening: function(ev) { 5529 5530 this.stopDrag(ev); // if there's a current drag, kill it 5531 5532 5533 5534 if (this.isListening) { 5535 5536 5537 5538 // remove the scroll handler if there is a scrollEl 5539 5540 if (this.scrollEl) { 5541 5542 this.scrollEl.off('scroll', this.scrollHandlerProxy); 5543 5544 this.scrollHandlerProxy = null; 5545 5546 } 5547 5548 5549 5550 $(document) 5551 5552 .off('mousemove', this.mousemoveProxy) 5553 5554 .off('mouseup', this.mouseupProxy) 5555 5556 .off('selectstart', this.preventDefault); 5557 5558 5559 5560 this.mousemoveProxy = null; 5561 5562 this.mouseupProxy = null; 5563 5564 5565 5566 this.isListening = false; 5567 5568 this.listenStop(ev); 5569 5570 } 5571 5572 }, 5573 5574 5575 5576 5577 5578 // Called when drag listening has stopped 5579 5580 listenStop: function(ev) { 5581 5582 this.trigger('listenStop', ev); 5583 5584 }, 5585 5586 5587 5588 5589 5590 // Triggers a callback. Calls a function in the option hash of the same name. 5591 5592 // Arguments beyond the first `name` are forwarded on. 5593 5594 trigger: function(name) { 5595 5596 if (this.options[name]) { 5597 5598 this.options[name].apply(this, Array.prototype.slice.call(arguments, 1)); 5599 5600 } 5601 5602 }, 5603 5604 5605 5606 5607 5608 // Stops a given mouse event from doing it's native browser action. In our case, text selection. 5609 5610 preventDefault: function(ev) { 5611 5612 ev.preventDefault(); 5613 5614 }, 5615 5616 5617 5618 5619 5620 /* Scrolling 5621 5622 ------------------------------------------------------------------------------------------------------------------*/ 5623 5624 5625 5626 5627 5628 // Computes and stores the bounding rectangle of scrollEl 5629 5630 computeScrollBounds: function() { 5631 5632 var el = this.scrollEl; 5633 5634 5635 5636 this.scrollBounds = el ? getOuterRect(el) : null; 5637 5638 // TODO: use getClientRect in future. but prevents auto scrolling when on top of scrollbars 5639 5640 }, 5641 5642 5643 5644 5645 5646 // Called when the dragging is in progress and scrolling should be updated 5647 5648 updateScroll: function(ev) { 5649 5650 var sensitivity = this.scrollSensitivity; 5651 5652 var bounds = this.scrollBounds; 5653 5654 var topCloseness, bottomCloseness; 5655 5656 var leftCloseness, rightCloseness; 5657 5658 var topVel = 0; 5659 5660 var leftVel = 0; 5661 5662 5663 5664 if (bounds) { // only scroll if scrollEl exists 5665 5666 5667 5668 // compute closeness to edges. valid range is from 0.0 - 1.0 5669 5670 topCloseness = (sensitivity - (ev.pageY - bounds.top)) / sensitivity; 5671 5672 bottomCloseness = (sensitivity - (bounds.bottom - ev.pageY)) / sensitivity; 5673 5674 leftCloseness = (sensitivity - (ev.pageX - bounds.left)) / sensitivity; 5675 5676 rightCloseness = (sensitivity - (bounds.right - ev.pageX)) / sensitivity; 5677 5678 5679 5680 // translate vertical closeness into velocity. 5681 5682 // mouse must be completely in bounds for velocity to happen. 5683 5684 if (topCloseness >= 0 && topCloseness <= 1) { 5685 5686 topVel = topCloseness * this.scrollSpeed * -1; // negative. for scrolling up 5687 5688 } 5689 5690 else if (bottomCloseness >= 0 && bottomCloseness <= 1) { 5691 5692 topVel = bottomCloseness * this.scrollSpeed; 5693 5694 } 5695 5696 5697 5698 // translate horizontal closeness into velocity 5699 5700 if (leftCloseness >= 0 && leftCloseness <= 1) { 5701 5702 leftVel = leftCloseness * this.scrollSpeed * -1; // negative. for scrolling left 5703 5704 } 5705 5706 else if (rightCloseness >= 0 && rightCloseness <= 1) { 5707 5708 leftVel = rightCloseness * this.scrollSpeed; 5709 5710 } 5711 5712 } 5713 5714 5715 5716 this.setScrollVel(topVel, leftVel); 5717 5718 }, 5719 5720 5721 5722 5723 5724 // Sets the speed-of-scrolling for the scrollEl 5725 5726 setScrollVel: function(topVel, leftVel) { 5727 5728 5729 5730 this.scrollTopVel = topVel; 5731 5732 this.scrollLeftVel = leftVel; 5733 5734 5735 5736 this.constrainScrollVel(); // massages into realistic values 5737 5738 5739 5740 // if there is non-zero velocity, and an animation loop hasn't already started, then START 5741 5742 if ((this.scrollTopVel || this.scrollLeftVel) && !this.scrollIntervalId) { 5743 5744 this.scrollIntervalId = setInterval( 5745 5746 proxy(this, 'scrollIntervalFunc'), // scope to `this` 5747 5748 this.scrollIntervalMs 5749 5750 ); 5751 5752 } 5753 5754 }, 5755 5756 5757 5758 5759 5760 // Forces scrollTopVel and scrollLeftVel to be zero if scrolling has already gone all the way 5761 5762 constrainScrollVel: function() { 5763 5764 var el = this.scrollEl; 5765 5766 5767 5768 if (this.scrollTopVel < 0) { // scrolling up? 5769 5770 if (el.scrollTop() <= 0) { // already scrolled all the way up? 5771 5772 this.scrollTopVel = 0; 5773 5774 } 5775 5776 } 5777 5778 else if (this.scrollTopVel > 0) { // scrolling down? 5779 5780 if (el.scrollTop() + el[0].clientHeight >= el[0].scrollHeight) { // already scrolled all the way down? 5781 5782 this.scrollTopVel = 0; 5783 5784 } 5785 5786 } 5787 5788 5789 5790 if (this.scrollLeftVel < 0) { // scrolling left? 5791 5792 if (el.scrollLeft() <= 0) { // already scrolled all the left? 5793 5794 this.scrollLeftVel = 0; 5795 5796 } 5797 5798 } 5799 5800 else if (this.scrollLeftVel > 0) { // scrolling right? 5801 5802 if (el.scrollLeft() + el[0].clientWidth >= el[0].scrollWidth) { // already scrolled all the way right? 5803 5804 this.scrollLeftVel = 0; 5805 5806 } 5807 5808 } 5809 5810 }, 5811 5812 5813 5814 5815 5816 // This function gets called during every iteration of the scrolling animation loop 5817 5818 scrollIntervalFunc: function() { 5819 5820 var el = this.scrollEl; 5821 5822 var frac = this.scrollIntervalMs / 1000; // considering animation frequency, what the vel should be mult'd by 5823 5824 5825 5826 // change the value of scrollEl's scroll 5827 5828 if (this.scrollTopVel) { 5829 5830 el.scrollTop(el.scrollTop() + this.scrollTopVel * frac); 5831 5832 } 5833 5834 if (this.scrollLeftVel) { 5835 5836 el.scrollLeft(el.scrollLeft() + this.scrollLeftVel * frac); 5837 5838 } 5839 5840 5841 5842 this.constrainScrollVel(); // since the scroll values changed, recompute the velocities 5843 5844 5845 5846 // if scrolled all the way, which causes the vels to be zero, stop the animation loop 5847 5848 if (!this.scrollTopVel && !this.scrollLeftVel) { 5849 5850 this.stopScrolling(); 5851 5852 } 5853 5854 }, 5855 5856 5857 5858 5859 5860 // Kills any existing scrolling animation loop 5861 5862 stopScrolling: function() { 5863 5864 if (this.scrollIntervalId) { 5865 5866 clearInterval(this.scrollIntervalId); 5867 5868 this.scrollIntervalId = null; 5869 5870 5871 5872 // when all done with scrolling, recompute positions since they probably changed 5873 5874 this.scrollStop(); 5875 5876 } 5877 5878 }, 5879 5880 5881 5882 5883 5884 // Get called when the scrollEl is scrolled (NOTE: this is delayed via debounce) 5885 5886 scrollHandler: function() { 5887
5888 // recompute all coordinates, but *only* if this is *not* part of our scrolling animation 5889 5890 if (!this.scrollIntervalId) { 5891 5892 this.scrollStop(); 5893 5894 } 5895 5896 }, 5897 5898 5899 5900 5901 5902 // Called when scrolling has stopped, whether through auto scroll, or the user scrolling 5903 5904 scrollStop: function() { 5905 5906 } 5907 5908 5909 5910 }); 5911 5912 5913 5914 ;; 5915 5916 5917 5918 /* Tracks mouse movements over a component and raises events about which hit the mouse is over. 5919 5920 ------------------------------------------------------------------------------------------------------------------------ 5921 5922 options: 5923 5924 - subjectEl 5925 5926 - subjectCenter 5927 5928 */ 5929 5930 5931 5932 var HitDragListener = DragListener.extend({ 5933 5934 5935 5936 component: null, // converts coordinates to hits 5937 5938 // methods: prepareHits, releaseHits, queryHit 5939 5940 5941 5942 origHit: null, // the hit the mouse was over when listening started 5943 5944 hit: null, // the hit the mouse is over 5945 5946 coordAdjust: null, // delta that will be added to the mouse coordinates when computing collisions 5947 5948 5949 5950 5951 5952 constructor: function(component, options) { 5953 5954 DragListener.call(this, options); // call the super-constructor 5955 5956 5957 5958 this.component = component; 5959 5960 }, 5961 5962 5963 5964 5965 5966 // Called when drag listening starts (but a real drag has not necessarily began). 5967 5968 // ev might be undefined if dragging was started manually. 5969 5970 listenStart: function(ev) { 5971 5972 var subjectEl = this.subjectEl; 5973 5974 var subjectRect; 5975 5976 var origPoint; 5977 5978 var point; 5979 5980 5981 5982 DragListener.prototype.listenStart.apply(this, arguments); // call the super-method 5983 5984 5985 5986 this.computeCoords(); 5987 5988 5989 5990 if (ev) { 5991 5992 origPoint = { left: ev.pageX, top: ev.pageY }; 5993 5994 point = origPoint; 5995 5996 5997 5998 // constrain the point to bounds of the element being dragged 5999 6000 if (subjectEl) { 6001 6002 subjectRect = getOuterRect(subjectEl); // used for centering as well 6003 6004 point = constrainPoint(point, subjectRect); 6005 6006 } 6007 6008 6009 6010 this.origHit = this.queryHit(point.left, point.top); 6011 6012 6013 6014 // treat the center of the subject as the collision point? 6015 6016 if (subjectEl && this.options.subjectCenter) { 6017 6018 6019 6020 // only consider the area the subject overlaps the hit. best for large subjects. 6021 6022 // TODO: skip this if hit didn't supply left/right/top/bottom 6023 6024 if (this.origHit) { 6025 6026 subjectRect = intersectRects(this.origHit, subjectRect) || 6027 6028 subjectRect; // in case there is no intersection 6029 6030 } 6031 6032 6033 6034 point = getRectCenter(subjectRect); 6035 6036 } 6037 6038 6039 6040 this.coordAdjust = diffPoints(point, origPoint); // point - origPoint 6041 6042 } 6043 6044 else { 6045 6046 this.origHit = null; 6047 6048 this.coordAdjust = null; 6049 6050 } 6051 6052 }, 6053 6054 6055 6056 6057 6058 // Recomputes the drag-critical positions of elements 6059 6060 computeCoords: function() { 6061 6062 this.component.prepareHits(); 6063 6064 this.computeScrollBounds(); // why is this here??? 6065 6066 }, 6067 6068 6069 6070 6071 6072 // Called when the actual drag has started 6073 6074 dragStart: function(ev) { 6075 6076 var hit; 6077 6078 6079 6080 DragListener.prototype.dragStart.apply(this, arguments); // call the super-method 6081 6082 6083 6084 // might be different from this.origHit if the min-distance is large 6085 6086 hit = this.queryHit(ev.pageX, ev.pageY); 6087 6088 6089 6090 // report the initial hit the mouse is over 6091 6092 // especially important if no min-distance and drag starts immediately 6093 6094 if (hit) { 6095 6096 this.hitOver(hit); 6097 6098 } 6099 6100 }, 6101 6102 6103 6104 6105 6106 // Called when the drag moves 6107 6108 drag: function(dx, dy, ev) { 6109 6110 var hit; 6111 6112 6113 6114 DragListener.prototype.drag.apply(this, arguments); // call the super-method 6115 6116 6117 6118 hit = this.queryHit(ev.pageX, ev.pageY); 6119 6120 6121 6122 if (!isHitsEqual(hit, this.hit)) { // a different hit than before? 6123 6124 if (this.hit) { 6125 6126 this.hitOut(); 6127 6128 } 6129 6130 if (hit) { 6131 6132 this.hitOver(hit); 6133 6134 } 6135 6136 } 6137 6138 }, 6139 6140 6141 6142 6143 6144 // Called when dragging has been stopped 6145 6146 dragStop: function() { 6147 6148 this.hitDone(); 6149 6150 DragListener.prototype.dragStop.apply(this, arguments); // call the super-method 6151 6152 }, 6153 6154 6155 6156 6157 6158 // Called when a the mouse has just moved over a new hit 6159 6160 hitOver: function(hit) { 6161 6162 var isOrig = isHitsEqual(hit, this.origHit); 6163 6164 6165 6166 this.hit = hit; 6167 6168 6169 6170 this.trigger('hitOver', this.hit, isOrig, this.origHit); 6171 6172 }, 6173 6174 6175 6176 6177 6178 // Called when the mouse has just moved out of a hit 6179 6180 hitOut: function() { 6181 6182 if (this.hit) { 6183 6184 this.trigger('hitOut', this.hit); 6185 6186 this.hitDone(); 6187 6188 this.hit = null; 6189 6190 } 6191 6192 }, 6193 6194 6195 6196 6197 6198 // Called after a hitOut. Also called before a dragStop 6199 6200 hitDone: function() { 6201 6202 if (this.hit) { 6203 6204 this.trigger('hitDone', this.hit); 6205 6206 } 6207 6208 }, 6209 6210 6211 6212 6213 6214 // Called when drag listening has stopped 6215 6216 listenStop: function() { 6217 6218 DragListener.prototype.listenStop.apply(this, arguments); // call the super-method 6219 6220 6221 6222 this.origHit = null; 6223 6224 this.hit = null; 6225 6226 6227 6228 this.component.releaseHits(); 6229 6230 }, 6231 6232 6233 6234 6235 6236 // Called when scrolling has stopped, whether through auto scroll, or the user scrolling 6237 6238 scrollStop: function() { 6239 6240 DragListener.prototype.scrollStop.apply(this, arguments); // call the super-method 6241 6242 6243 6244 this.computeCoords(); // hits' absolute positions will be in new places. recompute 6245 6246 }, 6247 6248 6249 6250 6251 6252 // Gets the hit underneath the coordinates for the given mouse event 6253 6254 queryHit: function(left, top) { 6255 6256 6257 6258 if (this.coordAdjust) { 6259 6260 left += this.coordAdjust.left; 6261 6262 top += this.coordAdjust.top; 6263 6264 } 6265 6266 6267 6268 return this.component.queryHit(left, top); 6269 6270 } 6271 6272 6273 6274 }); 6275 6276 6277 6278 6279 6280// Returns `true` if the hits are identically equal. `false` otherwise. Must be from the same component. 6281 6282// Two null values will be considered equal, as two "out of the component" states are the same. 6283 6284 function isHitsEqual(hit0, hit1) { 6285 6286 6287 6288 if (!hit0 && !hit1) { 6289 6290 return true; 6291 6292 } 6293 6294 6295 6296 if (hit0 && hit1) { 6297 6298 return hit0.component === hit1.component && 6299 6300 isHitPropsWithin(hit0, hit1) && 6301 6302 isHitPropsWithin(hit1, hit0); // ensures all props are identical 6303 6304 } 6305 6306 6307 6308 return false;
6309 6310 } 6311 6312 6313 6314 6315 6316// Returns true if all of subHit's non-standard properties are within superHit 6317 6318 function isHitPropsWithin(subHit, superHit) { 6319 6320 for (var propName in subHit) { 6321 6322 if (!/^(component|left|right|top|bottom)$/.test(propName)) { 6323 6324 if (subHit[propName] !== superHit[propName]) { 6325 6326 return false; 6327 6328 } 6329 6330 } 6331 6332 } 6333 6334 return true; 6335 6336 } 6337 6338 6339 6340 ;; 6341 6342 6343 6344 /* Creates a clone of an element and lets it track the mouse as it moves 6345 6346 ----------------------------------------------------------------------------------------------------------------------*/ 6347 6348 6349 6350 var MouseFollower = Class.extend({ 6351 6352 6353 6354 options: null, 6355 6356 6357 6358 sourceEl: null, // the element that will be cloned and made to look like it is dragging 6359 6360 el: null, // the clone of `sourceEl` that will track the mouse 6361 6362 parentEl: null, // the element that `el` (the clone) will be attached to 6363 6364 6365 6366 // the initial position of el, relative to the offset parent. made to match the initial offset of sourceEl 6367 6368 top0: null, 6369 6370 left0: null, 6371 6372 6373 6374 // the initial position of the mouse 6375 6376 mouseY0: null, 6377 6378 mouseX0: null, 6379 6380 6381 6382 // the number of pixels the mouse has moved from its initial position 6383 6384 topDelta: null, 6385 6386 leftDelta: null, 6387 6388 6389 6390 mousemoveProxy: null, // document mousemove handler, bound to the MouseFollower's `this` 6391 6392 6393 6394 isFollowing: false, 6395 6396 isHidden: false, 6397 6398 isAnimating: false, // doing the revert animation? 6399 6400 6401 6402 constructor: function(sourceEl, options) { 6403 6404 this.options = options = options || {}; 6405 6406 this.sourceEl = sourceEl; 6407 6408 this.parentEl = options.parentEl ? $(options.parentEl) : sourceEl.parent(); // default to sourceEl's parent 6409 6410 }, 6411 6412 6413 6414 6415 6416 // Causes the element to start following the mouse 6417 6418 start: function(ev) { 6419 6420 if (!this.isFollowing) { 6421 6422 this.isFollowing = true; 6423 6424 6425 6426 this.mouseY0 = ev.pageY; 6427 6428 this.mouseX0 = ev.pageX; 6429 6430 this.topDelta = 0; 6431 6432 this.leftDelta = 0; 6433 6434 6435 6436 if (!this.isHidden) { 6437 6438 this.updatePosition(); 6439 6440 } 6441 6442 6443 6444 $(document).on('mousemove', this.mousemoveProxy = proxy(this, 'mousemove')); 6445 6446 } 6447 6448 }, 6449 6450 6451 6452 6453 6454 // Causes the element to stop following the mouse. If shouldRevert is true, will animate back to original position. 6455 6456 // `callback` gets invoked when the animation is complete. If no animation, it is invoked immediately. 6457 6458 stop: function(shouldRevert, callback) { 6459 6460 var _this = this; 6461 6462 var revertDuration = this.options.revertDuration; 6463 6464 6465 6466 function complete() { 6467 6468 this.isAnimating = false; 6469 6470 _this.removeElement(); 6471 6472 6473 6474 this.top0 = this.left0 = null; // reset state for future updatePosition calls 6475 6476 6477 6478 if (callback) { 6479 6480 callback(); 6481 6482 } 6483 6484 } 6485 6486 6487 6488 if (this.isFollowing && !this.isAnimating) { // disallow more than one stop animation at a time 6489 6490 this.isFollowing = false; 6491 6492 6493 6494 $(document).off('mousemove', this.mousemoveProxy); 6495 6496 6497 6498 if (shouldRevert && revertDuration && !this.isHidden) { // do a revert animation? 6499 6500 this.isAnimating = true; 6501 6502 this.el.animate({ 6503 6504 top: this.top0, 6505 6506 left: this.left0 6507 6508 }, {
6509 6510 duration: revertDuration, 6511 6512 complete: complete 6513 6514 }); 6515 6516 } 6517 6518 else { 6519 6520 complete(); 6521 6522 } 6523 6524 } 6525 6526 }, 6527 6528 6529 6530 6531 6532 // Gets the tracking element. Create it if necessary 6533 6534 getEl: function() { 6535 6536 var el = this.el; 6537 6538 6539 6540 if (!el) { 6541 6542 this.sourceEl.width(); // hack to force IE8 to compute correct bounding box 6543 6544 el = this.el = this.sourceEl.clone() 6545 6546 .css({ 6547 6548 position: 'absolute', 6549 6550 visibility: '', // in case original element was hidden (commonly through hideEvents()) 6551 6552 display: this.isHidden ? 'none' : '', // for when initially hidden 6553 6554 margin: 0, 6555 6556 right: 'auto', // erase and set width instead 6557 6558 bottom: 'auto', // erase and set height instead 6559 6560 width: this.sourceEl.width(), // explicit height in case there was a 'right' value 6561 6562 height: this.sourceEl.height(), // explicit width in case there was a 'bottom' value 6563 6564 opacity: this.options.opacity || '', 6565 6566 zIndex: this.options.zIndex 6567 6568 }) 6569 6570 .appendTo(this.parentEl); 6571 6572 } 6573 6574 6575 6576 return el; 6577 6578 }, 6579 6580 6581 6582 6583 6584 // Removes the tracking element if it has already been created 6585 6586 removeElement: function() { 6587 6588 if (this.el) { 6589 6590 this.el.remove(); 6591 6592 this.el = null; 6593 6594 } 6595 6596 }, 6597 6598 6599 6600 6601 6602 // Update the CSS position of the tracking element 6603 6604 updatePosition: function() { 6605 6606 var sourceOffset; 6607 6608 var origin; 6609 6610 6611 6612 this.getEl(); // ensure this.el 6613 6614 6615 6616 // make sure origin info was computed 6617 6618 if (this.top0 === null) { 6619 6620 this.sourceEl.width(); // hack to force IE8 to compute correct bounding box 6621 6622 sourceOffset = this.sourceEl.offset(); 6623 6624 origin = this.el.offsetParent().offset(); 6625 6626 this.top0 = sourceOffset.top - origin.top; 6627 6628 this.left0 = sourceOffset.left - origin.left; 6629 6630 } 6631 6632 6633 6634 this.el.css({ 6635 6636 top: this.top0 + this.topDelta, 6637 6638 left: this.left0 + this.leftDelta 6639 6640 }); 6641 6642 }, 6643 6644 6645 6646 6647 6648 // Gets called when the user moves the mouse 6649 6650 mousemove: function(ev) { 6651 6652 this.topDelta = ev.pageY - this.mouseY0; 6653 6654 this.leftDelta = ev.pageX - this.mouseX0; 6655 6656 6657 6658 if (!this.isHidden) { 6659 6660 this.updatePosition(); 6661 6662 } 6663 6664 }, 6665 6666 6667 6668 6669 6670 // Temporarily makes the tracking element invisible. Can be called before following starts 6671 6672 hide: function() { 6673 6674 if (!this.isHidden) { 6675 6676 this.isHidden = true; 6677 6678 if (this.el) { 6679 6680 this.el.hide(); 6681 6682 } 6683 6684 } 6685 6686 }, 6687 6688 6689 6690 6691 6692 // Show the tracking element after it has been temporarily hidden 6693 6694 show: function() { 6695 6696 if (this.isHidden) { 6697 6698 this.isHidden = false; 6699 6700 this.updatePosition(); 6701 6702 this.getEl().show(); 6703 6704 } 6705 6706 } 6707 6708 6709 6710 }); 6711 6712 6713 6714 ;; 6715 6716 6717 6718 /* An abstract class comprised of a "grid" of areas that each represent a specific datetime 6719 6720 ----------------------------------------------------------------------------------------------------------------------*/ 6721 6722 6723 6724 var Grid = FC.Grid = Class.extend({ 6725 6726 6727 6728 view: null, // a View object 6729 6730 isRTL: null, // shortcut to the view's isRTL option 6731 6732 6733 6734 start: null, 6735 6736 end: null, 6737 6738 6739 6740 el: null, // the containing element 6741 6742 elsByFill: null, // a hash of jQuery element sets used for rendering each fill. Keyed by fill name. 6743 6744 6745 6746 externalDragStartProxy: null, // binds the Grid's scope to externalDragStart (in DayGrid.events) 6747 6748 6749 6750 // derived from options 6751 6752 eventTimeFormat: null, 6753 6754 displayEventTime: null, 6755 6756 displayEventEnd: null, 6757 6758 6759 6760 minResizeDuration: null, // TODO: hack. set by subclasses. minumum event resize duration 6761 6762 6763 6764 // if defined, holds the unit identified (ex: "year" or "month") that determines the level of granularity 6765 6766 // of the date areas. if not defined, assumes to be day and time granularity. 6767 6768 // TODO: port isTimeScale into same system? 6769 6770 largeUnit: null, 6771 6772 6773 6774 6775 6776 constructor: function(view) { 6777 6778 this.view = view; 6779 6780 this.isRTL = view.opt('isRTL'); 6781 6782 6783 6784 this.elsByFill = {}; 6785 6786 this.externalDragStartProxy = proxy(this, 'externalDragStart'); 6787 6788 }, 6789 6790 6791 6792 6793 6794 /* Options 6795 6796 ------------------------------------------------------------------------------------------------------------------*/ 6797 6798 6799 6800 6801 6802 // Generates the format string used for event time text, if not explicitly defined by 'timeFormat' 6803 6804 computeEventTimeFormat: function() { 6805 6806 return this.view.opt('smallTimeFormat'); 6807 6808 }, 6809 6810 6811 6812 6813 6814 // Determines whether events should have their end times displayed, if not explicitly defined by 'displayEventTime'. 6815 6816 // Only applies to non-all-day events. 6817 6818 computeDisplayEventTime: function() { 6819 6820 return true; 6821 6822 }, 6823 6824 6825 6826 6827 6828 // Determines whether events should have their end times displayed, if not explicitly defined by 'displayEventEnd' 6829 6830 computeDisplayEventEnd: function() { 6831 6832 return true; 6833 6834 }, 6835 6836 6837 6838 6839 6840 /* Dates 6841 6842 ------------------------------------------------------------------------------------------------------------------*/ 6843 6844 6845 6846 6847 6848 // Tells the grid about what period of time to display. 6849 6850 // Any date-related internal data should be generated. 6851 6852 setRange: function(range) { 6853 6854 this.start = range.start.clone(); 6855 6856 this.end = range.end.clone(); 6857 6858 6859 6860 this.rangeUpdated(); 6861 6862 this.processRangeOptions(); 6863 6864 }, 6865 6866 6867 6868 6869 6870 // Called when internal variables that rely on the range should be updated 6871 6872 rangeUpdated: function() { 6873 6874 }, 6875 6876 6877 6878 6879 6880 // Updates values that rely on options and also relate to range 6881 6882 processRangeOptions: function() { 6883 6884 var view = this.view; 6885 6886 var displayEventTime; 6887 6888 var displayEventEnd; 6889 6890 6891 6892 this.eventTimeFormat = 6893 6894 view.opt('eventTimeFormat') || 6895 6896 view.opt('timeFormat') || // deprecated 6897 6898 this.computeEventTimeFormat(); 6899 6900 6901 6902 displayEventTime = view.opt('displayEventTime'); 6903 6904 if (displayEventTime == null) { 6905 6906 displayEventTime = this.computeDisplayEventTime(); // might be based off of range 6907 6908 } 6909 6910 6911 6912 displayEventEnd = view.opt('displayEventEnd'); 6913 6914 if (displayEventEnd == null) { 6915 6916 displayEventEnd = this.computeDisplayEventEnd(); // might be based off of range 6917 6918 } 6919 6920 6921 6922 this.displayEventTime = displayEventTime; 6923 6924 this.displayEventEnd = displayEventEnd; 6925 6926 }, 6927 6928 6929 6930 6931 6932 // Converts a span (has unzoned start/end and any other grid-specific location information) 6933 6934 // into an array of segments (pieces of events whose format is decided by the grid). 6935 6936 spanToSegs: function(span) { 6937 6938 // subclasses must implement 6939 6940 }, 6941 6942 6943 6944 6945 6946 // Diffs the two dates, returning a duration, based on granularity of the grid 6947 6948 // TODO: port isTimeScale into this system? 6949 6950 diffDates: function(a, b) { 6951 6952 if (this.largeUnit) { 6953 6954 return diffByUnit(a, b, this.largeUnit); 6955 6956 } 6957 6958 else { 6959 6960 return diffDayTime(a, b); 6961 6962 } 6963 6964 }, 6965 6966 6967 6968 6969 6970 /* Hit Area 6971 6972 ------------------------------------------------------------------------------------------------------------------*/ 6973 6974 6975 6976 6977 6978 // Called before one or more queryHit calls might happen. Should prepare any cached coordinates for queryHit 6979 6980 prepareHits: function() { 6981 6982 }, 6983 6984 6985 6986 6987 6988 // Called when queryHit calls have subsided. Good place to clear any coordinate caches. 6989 6990 releaseHits: function() { 6991 6992 }, 6993 6994 6995 6996 6997 6998 // Given coordinates from the topleft of the document, return data about the date-related area underneath. 6999 7000 // Can return an object with arbitrary properties (although to
7000p/right/left/bottom are encouraged). 7001 7002 // Must have a `grid` property, a reference to this current grid. TODO: avoid this 7003 7004 // The returned object will be processed by getHitSpan and getHitEl. 7005 7006 queryHit: function(leftOffset, topOffset) { 7007 7008 }, 7009 7010 7011 7012 7013 7014 // Given position-level information about a date-related area within the grid, 7015 7016 // should return an object with at least a start/end date. Can provide other information as well. 7017 7018 getHitSpan: function(hit) { 7019 7020 }, 7021 7022 7023 7024 7025 7026 // Given position-level information about a date-related area within the grid, 7027 7028 // should return a jQuery element that best represents it. passed to dayClick callback. 7029 7030 getHitEl: function(hit) { 7031 7032 }, 7033 7034 7035 7036 7037 7038 /* Rendering 7039 7040 ------------------------------------------------------------------------------------------------------------------*/ 7041 7042 7043 7044 7045 7046 // Sets the container element that the grid should render inside of. 7047 7048 // Does other DOM-related initializations. 7049 7050 setElement: function(el) { 7051 7052 var _this = this; 7053 7054 7055 7056 this.el = el; 7057 7058 7059 7060 // attach a handler to the grid's root element. 7061 7062 // jQuery will take care of unregistering them when removeElement gets called. 7063 7064 el.on('mousedown', function(ev) { 7065 7066 if ( 7067 7068 !$(ev.target).is('.fc-event-container *, .fc-more') && // not an an event element, or "more.." link 7069 7070 !$(ev.target).closest('.fc-popover').length // not on a popover (like the "more.." events one) 7071 7072 ) { 7073 7074 _this.dayMousedown(ev); 7075 7076 } 7077 7078 }); 7079 7080 7081 7082 // attach event-element-related handlers. in Grid.events 7083 7084 // same garbage collection note as above. 7085 7086 this.bindSegHandlers(); 7087 7088 7089 7090 this.bindGlobalHandlers(); 7091 7092 }, 7093 7094 7095 7096 7097 7098 // Removes the grid's container element from the DOM. Undoes any other DOM-related attachments. 7099 7100 // DOES NOT remove any content beforehand (doesn't clear events or call unrenderDates), unlike View 7101 7102 removeElement: function() { 7103 7104 this.unbindGlobalHandlers(); 7105 7106 7107 7108 this.el.remove(); 7109 7110 7111 7112 // NOTE: we don't null-out this.el for the same reasons we don't do it within View::removeElement 7113 7114 }, 7115 7116 7117 7118 7119 7120 // Renders the basic structure of grid view before any content is rendered 7121 7122 renderSkeleton: function() { 7123 7124 // subclasses should implement 7125 7126 }, 7127 7128 7129 7130 7131 7132 // Renders the grid's date-related content (like areas that represent days/times). 7133 7134 // Assumes setRange has already been called and the skeleton has already been rendered. 7135 7136 renderDates: function() { 7137 7138 // subclasses should implement 7139 7140 }, 7141 7142 7143 7144 7145 7146 // Unrenders the grid's date-related content 7147 7148 unrenderDates: function() { 7149 7150 // subclasses should implement 7151 7152 }, 7153 7154 7155 7156 7157 7158 /* Handlers 7159 7160 ------------------------------------------------------------------------------------------------------------------*/ 7161 7162 7163 7164 7165 7166 // Binds DOM handlers to elements that reside outside the grid, such as the document 7167 7168 bindGlobalHandlers: function() { 7169 7170 $(document).on('dragstart sortstart', this.externalDragStartProxy); // jqui 7171 7172 }, 7173 7174 7175 7176 7177 7178 // Unbinds DOM handlers from elements that reside outside the grid 7179 7180 unbindGlobalHandlers: function() { 7181 7182 $(document).off('dragstart sortstart', this.externalDragStartProxy); // jqui 7183 7184 }, 7185 7186 7187 7188 7189 7190 // Process a mousedown on an element that represents a day. For day clicking and selecting. 7191 7192 dayMousedown: function(ev) { 7193 7194 var _this = this; 7195 7196 var view = this.view; 7197 7198 var isSelectable = view.opt('selectable'); 7199 7200 var dayClickHit; // null if invalid dayClick 7201 7202 var selectionSpan; // null if invalid selection 7203 7204 7205 7206 // this listener tracks a mousedown on a day element, and a subsequent drag. 7207 7208 // if the drag ends on the same day, it is a 'dayClick'. 7209 7210 // if 'selectable' is enabled, this listener also detects selections. 7211 7212 var dragListener = new HitDragListener(this, { 7213 7214 //distance: 5, // needs more work if we want dayClick to fire correctly 7215 7216 scroll: view.opt('dragScroll'), 7217 7218 dragStart: function() { 7219 7220 view.unselect(); // since we could be rendering a new selection, we want to clear any old one 7221 7222 }, 7223 7224 hitOver: function(hit, isOrig, origHit) { 7225 7226 if (origHit) { // click needs to have started on a hit 7227 7228 dayClickHit = isOrig ? hit : null; // single-hit selection is a day click 7229 7230 if (isSelectable) { 7231 7232 selectionSpan = _this.computeSelection( 7233 7234 _this.getHitSpan(origHit), 7235 7236 _this.getHitSpan(hit) 7237 7238 ); 7239 7240 if (selectionSpan) { 7241 7242 _this.renderSelection(selectionSpan); 7243 7244 } 7245 7246 else if (selectionSpan === false) { 7247
7248 disableCursor(); 7249 7250 } 7251 7252 } 7253 7254 } 7255 7256 }, 7257 7258 hitOut: function() { 7259 7260 dayClickHit = null; 7261 7262 selectionSpan = null; 7263 7264 _this.unrenderSelection(); 7265 7266 enableCursor(); 7267 7268 }, 7269 7270 listenStop: function(ev) { 7271 7272 if (dayClickHit) { 7273 7274 view.triggerDayClick( 7275 7276 _this.getHitSpan(dayClickHit), 7277 7278 _this.getHitEl(dayClickHit), 7279 7280 ev 7281 7282 ); 7283 7284 } 7285 7286 if (selectionSpan) { 7287 7288 // the selection will already have been rendered. just report it 7289 7290 view.reportSelection(selectionSpan, ev); 7291 7292 } 7293 7294 enableCursor(); 7295 7296 } 7297 7298 }); 7299 7300 7301 7302 dragListener.mousedown(ev); // start listening, which will eventually initiate a dragStart 7303 7304 }, 7305 7306 7307 7308 7309 7310 /* Event Helper 7311 7312 ------------------------------------------------------------------------------------------------------------------*/ 7313 7314 // TODO: should probably move this to Grid.events, like we did event dragging / resizing 7315 7316 7317 7318 7319 7320 // Renders a mock event at the given event location, which contains zoned start/end properties. 7321 7322 renderEventLocationHelper: function(eventLocation, sourceSeg) { 7323 7324 var fakeEvent = this.fabricateHelperEvent(eventLocation, sourceSeg); 7325 7326 7327 7328 this.renderHelper(fakeEvent, sourceSeg); // do the actual rendering 7329 7330 }, 7331 7332 7333 7334 7335 7336 // Builds a fake event given zoned event date properties and a segment is should be inspired from. 7337 7338 // The range's end can be null, in which case the mock event that is rendered will have a null end time. 7339 7340 // `sourceSeg` is the internal segment object involved in the drag. If null, something external is dragging. 7341 7342 fabricateHelperEvent: function(eventLocation, sourceSeg) { 7343 7344 var fakeEvent = sourceSeg ? createObject(sourceSeg.event) : {}; // mask the original event object if possible 7345 7346 7347 7348 fakeEvent.start = eventLocation.start.clone(); 7349 7350 fakeEvent.end = eventLocation.end ? eventLocation.end.clone() : null; 7351 7352 fakeEvent.allDay = null; // force it to be freshly computed by normalizeEventDates 7353 7354 this.view.calendar.normalizeEventDates(fakeEvent); 7355 7356 7357 7358 // this extra className will be useful for differentiating real events from mock events in CSS 7359 7360 fakeEvent.className = (fakeEvent.className || []).concat('fc-helper'); 7361 7362 7363 7364 // if something external is being dragged in, don't render a resizer 7365 7366 if (!sourceSeg) { 7367 7368 fakeEvent.editable = false; 7369 7370 } 7371 7372 7373 7374 return fakeEvent; 7375 7376 }, 7377 7378 7379 7380 7381 7382 // Renders a mock event. Given zoned event date properties. 7383 7384 renderHelper: function(eventLocation, sourceSeg) { 7385 7386 // subclasses must implement 7387 7388 }, 7389 7390 7391 7392 7393 7394 // Unrenders a mock event 7395 7396 unrenderHelper: function() { 7397 7398 // subclasses must implement 7399 7400 }, 7401 7402 7403 7404 7405 7406 /* Selection 7407 7408 ------------------------------------------------------------------------------------------------------------------*/ 7409 7410 7411 7412 7413 7414 // Renders a visual indication of a selection. Will highlight by default but can be overridden by subclasses. 7415 7416 // Given a span (unzoned start/end and other misc data) 7417 7418 renderSelection: function(span) { 7419 7420 this.renderHighlight(span); 7421 7422 }, 7423 7424 7425 7426 7427 7428 // Unrenders any visual indications of a selection. Will unrender a highlight by default. 7429 7430 unrenderSelection: function() { 7431 7432 this.unrenderHighlight(); 7433 7434 }, 7435 7436 7437 7438 7439 7440 // Given the first and last date-spans of a selection, returns another date-span object. 7441 7442 // Subclasses can override and provide additional data in the span object. Will be passed to renderSelection(). 7443 7444 // Will return false if the selection is invalid and this should be indicated to the user. 7445 7446 // Will return null/undefined if a selection invalid but no error should be reported. 7447 7448 computeSelection: function(span0, span1) { 7449 7450 var span = this.computeSelectionSpan(span0, span1); 7451 7452 7453 7454 if (span && !this.view.calendar.isSelectionSpanAllowed(span)) { 7455 7456 return false; 7457 7458 } 7459 7460 7461 7462 return span; 7463 7464 }, 7465 7466 7467 7468 7469 7470 // Given two spans, must return the combination of the two. 7471 7472 // TODO: do this separation of concerns (combining VS validation) for event dnd/resize too. 7473 7474 computeSelectionSpan: function(span0, span1) { 7475 7476 var dates = [ span0.start, span0.end, span1.start, span1.end ]; 7477 7478 7479 7480 dates.sort(compareNumbers); // sorts chronologically. works with Moments 7481 7482 7483 7484 return { start: dates[0].clone(), end: dates[3].clone() }; 7485 7486 }, 7487 7488 7489 7490 7491 7492 /* Highlight 7493 7494 ------------------------------------------------------------------------------------------------------------------*/ 7495 7496 7497 7498 7499 7500 // Renders an emphasis on the given date range. Given a span (unzoned start/end and other misc data) 7501 7502 renderHighlight: function(span) { 7503 7504 this.renderFill('highlight', this.spanToSegs(span)); 7505 7506 }, 7507 7508 7509 7510 7511 7512 // Unrenders the emphasis on a date range 7513 7514 unrenderHighlight: function() { 7515 7516 this.unrenderFill('highlight'); 7517 7518 }, 7519 7520 7521 7522 7523 7524 // Generates an array of classNames for rendering the highlight. Used by the fill system. 7525 7526 highlightSegClasses: function() { 7527 7528 return [ 'fc-highlight' ]; 7529 7530 }, 7531 7532 7533 7534 7535 7536 /* Fill System (highlight, background events, business hours) 7537 7538 ------------------------------------------------------------------------------------------------------------------*/ 7539 7540 7541 7542 7543 7544 // Renders a set of rectangles over the given segments of time. 7545 7546 // MUST RETURN a subset of segs, the segs that were actually rendered. 7547 7548 // Responsible for populating this.elsByFill. TODO: better API for expressing this requirement 7549 7550 renderFill: function(type, segs) { 7551 7552 // subclasses must implement 7553 7554 }, 7555 7556 7557 7558 7559 7560 // Unrenders a specific type of fill that is currently rendered on the grid 7561 7562 unrenderFill: function(type) { 7563 7564 var el = this.elsByFill[type]; 7565 7566 7567 7568 if (el) { 7569 7570 el.remove(); 7571 7572 delete this.elsByFill[type]; 7573 7574 } 7575 7576 }, 7577 7578 7579 7580 7581 7582 // Renders and assigns an `el` property for each fill segment. Generic enough to work with different types. 7583 7584 // Only returns segments that successfully rendered. 7585 7586 // To be harnessed by renderFill (implemented by subclasses). 7587 7588 // Analagous to renderFgSegEls. 7589 7590 renderFillSegEls: function(type, segs) { 7591 7592 var _this = this; 7593 7594 var segElMethod = this[type + 'SegEl']; 7595 7596 var html = ''; 7597 7598 var renderedSegs = []; 7599 7600 var i; 7601 7602 7603 7604 if (segs.length) { 7605 7606 7607 7608 // build a large concatenation of segment HTML 7609 7610 for (i = 0; i < segs.length; i++) { 7611 7612 html += this.fillSegHtml(type, segs[i]); 7613 7614 } 7615 7616 7617 7618 // Grab individual elements from the combined HTML string. Use each as the default rendering. 7619 7620 // Then, compute the 'el' for each segment. 7621 7622 $(html).each(function(i, node) { 7623 7624 var seg = segs[i]; 7625 7626 var el = $(node); 7627 7628 7629 7630 // allow custom filter methods per-type 7631 7632 if (segElMethod) { 7633 7634 el = segElMethod.call(_this, seg, el); 7635 7636 } 7637 7638 7639 7640 if (el) { // custom filters did not cancel the render 7641 7642 el = $(el); // allow custom filter to return raw DOM node 7643 7644 7645 7646 // correct element type? (would be bad if a non-TD were inserted into a table for example) 7647 7648 if (el.is(_this.fillSegTag)) { 7649 7650 seg.el = el; 7651 7652 renderedSegs.push(seg); 7653 7654 } 7655 7656 } 7657 7658 }); 7659 7660 } 7661 7662 7663 7664 return renderedSegs; 7665 7666 }, 7667 7668 7669 7670 7671 7672 fillSegTag: 'div', // subclasses can override 7673 7674 7675 7676 7677 7678 // Builds the HTML needed for one fill segment. Generic enought o work with different types. 7679 7680 fillSegHtml: function(type, seg) { 7681 7682 7683 7684 // custom hooks per-type 7685 7686 var classesMethod = this[type + 'SegClasses']; 7687 7688 var cssMethod = this[type + 'SegCss']; 7689 7690 7691 7692 var classes = classesMethod ? classesMethod.call(this, seg) : []; 7693 7694 var css = cssToStr(cssMethod ? cssMethod.call(this, seg) : {}); 7695 7696 7697 7698 return '<' + this.fillSegTag + 7699 7700 (classes.length ? ' class="' + classes.join(' ') + '"' : '') + 7701 7702 (css ? ' style="' + css + '"' : '') + 7703 7704 ' />'; 7705 7706 }, 7707 7708 7709 7710 7711 7712 7713 7714 /* Generic rendering utilities for subclasses 7715 7716 ------------------------------------------------------------------------------------------------------------------*/ 7717 7718 7719 7720 7721 7722 // Computes HTML classNames for a single-day element 7723 7724 getDayClasses: function(date) { 7725 7726 var view = this.view; 7727 7728 var today = view.calendar.getNow().stripTime(); 7729 7730 var classes = [ 'fc-' + dayIDs[date.day()] ]; 7731 7732 7733 7734 if ( 7735 7736 view.intervalDuration.as('months') == 1 && 7737 7738 date.month() != view.intervalStart.month() 7739 7740 ) { 7741 7742 classes.push('fc-other-month'); 7743 7744 } 7745 7746 7747 7748 if (date.isSame(today, 'day')) { 7749 7750 classes.push( 7751 7752 'fc-today', 7753 7754 view.highlightStateClass 7755 7756 ); 7757 7758 } 7759 7760 else if (date < today) { 7761 7762 classes.push('fc-past'); 7763 7764 } 7765 7766 else { 7767 7768 classes.push('fc-future'); 7769 7770 } 7771 7772 7773 7774 return classes; 7775 7776 } 7777 7778 7779 7780 }); 7781 7782 7783 7784 ;; 7785 7786 7787 7788 /* Event-rendering and event-interaction methods for the abstract Grid class 7789 7790 ----------------------------------------------------------------------------------------------------------------------*/ 7791 7792 7793 7794 Grid.mixin({ 7795 7796 7797 7798 mousedOverSeg: null, // the segment object the user's mouse is over. null if over nothing 7799 7800 isDraggingSeg: false, // is a segment being dragged? boolean 7801 7802 isResizingSeg: false, // is a segment being resized? boolean 7803
7804 isDraggingExternal: false, // jqui-dragging an external element? boolean 7805 7806 segs: null, // the event segments currently rendered in the grid 7807 7808 7809 7810 7811 7812 // Renders the given events onto the grid 7813 7814 renderEvents: function(events) { 7815 7816 var bgEvents = []; 7817 7818 var fgEvents = []; 7819 7820 var i; 7821 7822 7823 7824 for (i = 0; i < events.length; i++) { 7825 7826 (isBgEvent(events[i]) ? bgEvents : fgEvents).push(events[i]); 7827 7828 } 7829 7830 7831 7832 this.segs = [].concat( // record all segs 7833 7834 this.renderBgEvents(bgEvents), 7835 7836 this.renderFgEvents(fgEvents) 7837 7838 ); 7839 7840 }, 7841 7842 7843 7844 7845 7846 renderBgEvents: function(events) { 7847 7848 var segs = this.eventsToSegs(events); 7849 7850 7851 7852 // renderBgSegs might return a subset of segs, segs that were actually rendered 7853 7854 return this.renderBgSegs(segs) || segs; 7855 7856 }, 7857 7858 7859 7860 7861 7862 renderFgEvents: function(events) { 7863 7864 var segs = this.eventsToSegs(events); 7865 7866 7867 7868 // renderFgSegs might return a subset of segs, segs that were actually rendered 7869 7870 return this.renderFgSegs(segs) || segs; 7871 7872 }, 7873 7874 7875 7876 7877 7878 // Unrenders all events currently rendered on the grid 7879 7880 unrenderEvents: function() { 7881 7882 this.triggerSegMouseout(); // trigger an eventMouseout if user's mouse is over an event 7883 7884 7885 7886 this.unrenderFgSegs(); 7887 7888 this.unrenderBgSegs(); 7889 7890 7891 7892 this.segs = null; 7893 7894 }, 7895 7896 7897 7898 7899 7900 // Retrieves all rendered segment objects currently rendered on the grid 7901 7902 getEventSegs: function() { 7903 7904 return this.segs || []; 7905 7906 }, 7907 7908 7909 7910 7911 7912 /* Foreground Segment Rendering 7913 7914 ------------------------------------------------------------------------------------------------------------------*/ 7915 7916 7917 7918 7919 7920 // Renders foreground event segments onto the grid. May return a subset of segs that were rendered. 7921 7922 renderFgSegs: function(segs) { 7923 7924 // subclasses must implement 7925 7926 }, 7927 7928 7929 7930 7931 7932 // Unrenders all currently rendered foreground segments 7933 7934 unrenderFgSegs: function() { 7935 7936 // subclasses must implement 7937 7938 }, 7939 7940 7941 7942 7943 7944 // Renders and assigns an `el` property for each foreground event segment. 7945 7946 // Only returns segments that successfully rendered. 7947 7948 // A utility that subclasses may use. 7949 7950 renderFgSegEls: function(segs, disableResizing) { 7951 7952 var view = this.view; 7953 7954 var html = ''; 7955 7956 var renderedSegs = []; 7957 7958 var i; 7959 7960 7961 7962 if (segs.length) { // don't build an empty html string 7963 7964 7965 7966 // build a large concatenation of event segment HTML 7967 7968 for (i = 0; i < segs.length; i++) { 7969 7970 html += this.fgSegHtml(segs[i], disableResizing); 7971 7972 } 7973 7974 7975 7976 // Grab individual elements from the combined HTML string. Use each as the default rendering. 7977 7978 // Then, compute the 'el' for each segment. An el might be null if the eventRender callback returned false. 7979 7980 $(html).each(function(i, node) { 7981 7982 var seg = segs[i]; 7983 7984 var el = view.resolveEventEl(seg.event, $(node)); 7985 7986 7987 7988 if (el) { 7989 7990 el.data('fc-seg', seg); // used by handlers 7991 7992 seg.el = el; 7993 7994 renderedSegs.push(seg); 7995 7996 } 7997 7998 }); 7999 8000 } 8001 8002 8003 8004 return renderedSegs; 8005 8006 }, 8007 8008 8009 8010 8011 8012 // Generates the HTML for the default rendering of a foreground event segment. Used by renderFgSegEls() 8013 8014 fgSegHtml: function(seg, disableResizing) { 8015 8016 // subclasses should implement 8017 8018 }, 8019 8020 8021 8022 8023 8024 /* Background Segment Rendering 8025 8026 ------------------------------------------------------------------------------------------------------------------*/ 8027 8028 8029 8030 8031 8032 // Renders the given background event segments onto the grid. 8033 8034 // Returns a subset of the segs that were actually rendered. 8035 8036 renderBgSegs: function(segs) { 8037 8038 return this.renderFill('bgEvent', segs); 8039 8040 }, 8041 8042 8043 8044 8045 8046 // Unrenders all the currently rendered background event segments 8047 8048 unrenderBgSegs: function() { 8049 8050 this.unrenderFill('bgEvent'); 8051 8052 }, 8053 8054 8055 8056 8057 8058 // Renders a background event element, given the default rendering. Called by the fill system. 8059 8060 bgEventSegEl: function(seg, el) { 8061 8062 return this.view.resolveEventEl(seg.event, el); // will filter through eventRender 8063 8064 }, 8065 8066 8067 8068 8069 8070 // Generates an array of classNames to be used for the default rendering of a background event. 8071 8072 // Called by the fill system. 8073 8074 bgEventSegClasses: function(seg) { 8075 8076 var event = seg.event; 8077 8078 var source = event.source || {}; 8079 8080 8081 8082 return [ 'fc-bgevent' ].concat( 8083 8084 event.className, 8085 8086 source.className || [] 8087 8088 ); 8089 8090 }, 8091 8092 8093 8094 8095 8096 // Generates a semicolon-separated CSS string to be used for the default rendering of a background event. 8097 8098 // Called by the fill system. 8099 8100 // TODO: consolidate with getEventSkinCss? 8101 8102 bgEventSegCss: function(seg) { 8103 8104 var view = this.view; 8105 8106 var event = seg.event; 8107 8108 var source = event.source || {}; 8109 8110 8111 8112 return { 8113 8114 'background-color': 8115 8116 event.backgroundColor || 8117 8118 event.color || 8119 8120 source.backgroundColor || 8121 8122 source.color || 8123
8124 view.opt('eventBackgroundColor') || 8125 8126 view.opt('eventColor') 8127 8128 }; 8129 8130 }, 8131 8132 8133 8134 8135 8136 // Generates an array of classNames to be used for the rendering business hours overlay. Called by the fill system. 8137 8138 businessHoursSegClasses: function(seg) { 8139 8140 return [ 'fc-nonbusiness', 'fc-bgevent' ]; 8141 8142 }, 8143 8144 8145 8146 8147 8148 /* Handlers 8149 8150 ------------------------------------------------------------------------------------------------------------------*/ 8151 8152 8153 8154 8155 8156 // Attaches event-element-related handlers to the container element and leverage bubbling 8157 8158 bindSegHandlers: function() { 8159 8160 var _this = this; 8161 8162 var view = this.view; 8163 8164 8165 8166 $.each( 8167 8168 { 8169 8170 mouseenter: function(seg, ev) { 8171 8172 _this.triggerSegMouseover(seg, ev); 8173 8174 }, 8175 8176 mouseleave: function(seg, ev) { 8177 8178 _this.triggerSegMouseout(seg, ev); 8179 8180 }, 8181 8182 click: function(seg, ev) { 8183 8184 return view.trigger('eventClick', this, seg.event, ev); // can return `false` to cancel 8185 8186 }, 8187 8188 mousedown: function(seg, ev) { 8189 8190 if ($(ev.target).is('.fc-resizer') && view.isEventResizable(seg.event)) { 8191 8192 _this.segResizeMousedown(seg, ev, $(ev.target).is('.fc-start-resizer')); 8193 8194 } 8195 8196 else if (view.isEventDraggable(seg.event)) { 8197 8198 _this.segDragMousedown(seg, ev); 8199 8200 } 8201 8202 } 8203 8204 }, 8205 8206 function(name, func) { 8207 8208 // attach the handler to the container element and only listen for real event elements via bubbling 8209 8210 _this.el.on(name, '.fc-event-container > *', function(ev) { 8211 8212 var seg = $(this).data('fc-seg'); // grab segment data. put there by View::renderEvents 8213 8214 8215 8216 // only call the handlers if there is not a drag/resize in progress 8217 8218 if (seg && !_this.isDraggingSeg && !_this.isResizingSeg) { 8219 8220 return func.call(this, seg, ev); // `this` will be the event element 8221 8222 } 8223 8224 }); 8225 8226 } 8227 8228 ); 8229 8230 }, 8231 8232 8233 8234 8235 8236 // Updates internal state and triggers handlers for when an event element is moused over 8237 8238 triggerSegMouseover: function(seg, ev) { 8239 8240 if (!this.mousedOverSeg) { 8241 8242 this.mousedOverSeg = seg; 8243 8244 this.view.trigger('eventMouseover', seg.el[0], seg.event, ev); 8245 8246 } 8247 8248 }, 8249 8250 8251 8252 8253 8254 // Updates internal state and triggers handlers for when an event element is moused out. 8255 8256 // Can be given no arguments, in which case it will mouseout the segment that was previously moused over. 8257 8258 triggerSegMouseout: function(seg, ev) { 8259 8260 ev = ev || {}; // if given no args, make a mock mouse event 8261 8262 8263 8264 if (this.mousedOverSeg) { 8265 8266 seg = seg || this.mousedOverSeg; // if given no args, use the currently moused-over segment 8267 8268 this.mousedOverSeg = null; 8269 8270 this.view.trigger('eventMouseout', seg.el[0], seg.event, ev); 8271 8272 } 8273 8274 }, 8275 8276 8277 8278 8279 8280 /* Event Dragging 8281 8282 ------------------------------------------------------------------------------------------------------------------*/ 8283 8284 8285 8286 8287 8288 // Called when the user does a mousedown on an event, which might lead to dragging. 8289 8290 // Generic enough to work with any type of Grid. 8291 8292 segDragMousedown: function(seg, ev) { 8293 8294 var _this = this; 8295 8296 var view = this.view; 8297 8298 var calendar = view.calendar; 8299 8300 var el = seg.el; 8301 8302 var event = seg.event; 8303 8304 var dropLocation; // zoned event date properties 8305 8306 8307 8308 // A clone of the original element that will move with the mouse 8309 8310 var mouseFollower = new MouseFollower(seg.el, { 8311 8312 parentEl: view.el, 8313 8314 opacity: view.opt('dragOpacity'), 8315 8316 revertDuration: view.opt('dragRevertDuration'), 8317 8318 zIndex: 2 // one above the .fc-view 8319 8320 }); 8321 8322 8323 8324 // Tracks mouse movement over the *view's* coordinate map. Allows dragging and dropping between subcomponents 8325 8326 // of the view. 8327 8328 var dragListener = new HitDragListener(view, { 8329 8330 distance: 5, 8331 8332 scroll: view.opt('dragScroll'), 8333 8334 subjectEl: el, 8335 8336 subjectCenter: true, 8337 8338 listenStart: function(ev) { 8339 8340 mouseFollower.hide(); // don't show until we know this is a real drag 8341 8342 mouseFollower.start(ev); 8343 8344 }, 8345 8346 dragStart: function(ev) { 8347 8348 _this.triggerSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported 8349 8350 _this.segDragStart(seg, ev); 8351 8352 view.hideEvent(event);
8352 // hide all event segments. our mouseFollower will take over 8353 8354 }, 8355 8356 hitOver: function(hit, isOrig, origHit) { 8357 8358 8359 8360 // starting hit could be forced (DayGrid.limit) 8361 8362 if (seg.hit) { 8363 8364 origHit = seg.hit; 8365 8366 } 8367 8368 8369 8370 // since we are querying the parent view, might not belong to this grid 8371 8372 dropLocation = _this.computeEventDrop( 8373 8374 origHit.component.getHitSpan(origHit), 8375 8376 hit.component.getHitSpan(hit), 8377 8378 event 8379 8380 ); 8381 8382 8383 8384 if (dropLocation &&!calendar.isEventSpanAllowed(_this.eventToSpan(dropLocation), event)) { 8385 8386 disableCursor(); 8387 8388 dropLocation = null; 8389 8390 } 8391 8392 8393 8394 // if a valid drop location, have the subclass render a visual indication 8395 8396 if (dropLocation && view.renderDrag(dropLocation, seg)) { 8397 8398 mouseFollower.hide(); // if the subclass is already using a mock event "helper", hide our own 8399 8400 } 8401 8402 else { 8403 8404 mouseFollower.show(); // otherwise, have the helper follow the mouse (no snapping) 8405 8406 } 8407 8408 8409 8410 if (isOrig) { 8411 8412 dropLocation = null; // needs to have moved hits to be a valid drop 8413 8414 } 8415 8416 }, 8417 8418 hitOut: function() { // called before mouse moves to a different hit OR moved out of all hits 8419 8420 view.unrenderDrag(); // unrender whatever was done in renderDrag 8421 8422 mouseFollower.show(); // show in case we are moving out of all hits 8423 8424 dropLocation = null; 8425 8426 }, 8427 8428 hitDone: function() { // Called after a hitOut OR before a dragStop 8429 8430 enableCursor(); 8431 8432 }, 8433 8434 dragStop: function(ev) { 8435 8436 // do revert animation if hasn't changed. calls a callback when finished (whether animation or not) 8437 8438 mouseFollower.stop(!dropLocation, function() { 8439 8440 view.unrenderDrag(); 8441 8442 view.showEvent(event); 8443 8444 _this.segDragStop(seg, ev); 8445 8446 8447 8448 if (dropLocation) { 8449 8450 view.reportEventDrop(event, dropLocation, this.largeUnit, el, ev); 8451 8452 } 8453 8454 }); 8455 8456 }, 8457 8458 listenStop: function() { 8459 8460 mouseFollower.stop(); // put in listenStop in case there was a mousedown but the drag never started 8461 8462 } 8463 8464 }); 8465 8466 8467 8468 dragListener.mousedown(ev); // start listening, which will eventually lead to a dragStart 8469 8470 }, 8471 8472 8473 8474 8475 8476 // Called before event segment dragging starts 8477 8478 segDragStart: function(seg, ev) { 8479 8480 this.isDraggingSeg = true; 8481 8482 this.view.trigger('eventDragStart', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy 8483 8484 }, 8485 8486 8487 8488 8489 8490 // Called after event segment dragging stops 8491 8492 segDragStop: function(seg, ev) { 8493 8494 this.isDraggingSeg = false; 8495 8496 this.view.trigger('eventDragStop', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy 8497 8498 }, 8499 8500 8501 8502 8503 8504 // Given the spans an event drag began, and the span event was dropped, calculates the new zoned start/end/allDay 8505 8506 // values for the event. Subclasses may override and set additional properties to be used by renderDrag. 8507 8508 // A falsy returned value indicates an invalid drop. 8509 8510 computeEventDrop: function(startSpan, endSpan, event) { 8511 8512 var calendar = this.view.calendar; 8513 8514 var dragStart = startSpan.start; 8515 8516 var dragEnd = endSpan.start; 8517 8518 var delta; 8519 8520 var dropLocation; // zoned event date properties 8521 8522 8523 8524 if (dragStart.hasTime() === dragEnd.hasTime()) { 8525 8526 delta = this.diffDates(dragEnd, dragStart); 8527 8528 8529 8530 // if an all-day event was in a timed area and it was dragged to a different time, 8531 8532 // guarantee an end and adjust start/end to have times 8533 8534 if (event.allDay && durationHasTime(delta)) { 8535 8536 dropLocation = { 8537 8538 start: event.start.clone(), 8539 8540 end: calendar.getEventEnd(event), // will be an ambig day 8541 8542 allDay: false // for normalizeEventTimes 8543 8544 }; 8545 8546 calendar.normalizeEventTimes(dropLocation); 8547 8548 } 8549 8550 // othewise, work off existing values 8551 8552 else { 8553 8554 dropLocation = { 8555 8556 start: event.start.clone(), 8557 8558 end: event.end ? event.end.clone() : null, 8559 8560 allDay: event.allDay // keep it the same 8561 8562 }; 8563 8564 } 8565 8566 8567 8568 dropLocation.start.add(delta); 8569 8570 if (dropLocation.end) { 8571 8572 dropLocation.end.add(delta); 8573 8574 } 8575 8576 } 8577 8578 else { 8579 8580 // if switching from day <-> timed, start should be reset to the dropped date, and the end cleared 8581 8582 dropLocation = { 8583 8584 start: dragEnd.clone(), 8585 8586 end: null, // end should be cleared 8587 8588 allDay: !dragEnd.hasTime() 8589 8590 }; 8591 8592 } 8593 8594 8595 8596 return dropLocation; 8597 8598 }, 8599 8600 8601 8602 8603 8604 // Utility for apply dragOpacity to a jQuery set 8605 8606 applyDragOpacity: function(els) { 8607 8608 var opacity = this.view.opt('dragOpacity'); 8609 8610 8611 8612 if (opacity != null) { 8613 8614 els.each(function(i, node) { 8615 8616 // Don't use jQuery (will set an IE filter), do it the old fashioned way. 8617 8618 // In IE8, a helper element will disappears if there's a filter. 8619 8620 node.style.opacity = opacity; 8621 8622 }); 8623 8624 } 8625 8626 }, 8627 8628 8629 8630 8631 8632 /* External Element Dragging 8633 8634 ------------------------------------------------------------------------------------------------------------------*/ 8635 8636 8637 8638 8639 8640 // Called when a jQuery UI drag is initiated anywhere in the DOM 8641 8642 externalDragStart: function(ev, ui) { 8643 8644 var view = this.view; 8645 8646 var el; 8647 8648 var accept; 8649 8650 8651 8652 if (view.opt('droppable')) { // only listen if this setting is on 8653 8654 el = $((ui ? ui.item : null) || ev.target); 8655 8656 8657 8658 // Test that the dragged element passes the dropAccept selector or filter function. 8659 8660 // FYI, the default is "*" (matches all) 8661 8662 accept = view.opt('dropAccept'); 8663 8664 if ($.isFunction(accept) ? accept.call(el[0], el) : el.is(accept)) { 8665
8666 if (!this.isDraggingExternal) { // prevent double-listening if fired twice 8667 8668 this.listenToExternalDrag(el, ev, ui); 8669 8670 } 8671 8672 } 8673 8674 } 8675 8676 }, 8677 8678 8679 8680 8681 8682 // Called when a jQuery UI drag starts and it needs to be monitored for dropping 8683 8684 listenToExternalDrag: function(el, ev, ui) { 8685 8686 var _this = this; 8687 8688 var meta = getDraggedElMeta(el); // extra data about event drop, including possible event to create 8689 8690 var dropLocation; // a null value signals an unsuccessful drag 8691 8692 8693 8694 // listener that tracks mouse movement over date-associated pixel regions 8695 8696 var dragListener = new HitDragListener(this, { 8697 8698 listenStart: function() { 8699 8700 _this.isDraggingExternal = true; 8701 8702 }, 8703 8704 hitOver: function(hit) { 8705 8706 dropLocation = _this.computeExternalDrop( 8707 8708 hit.component.getHitSpan(hit), // since we are querying the parent view, might not belong to this grid 8709 8710 meta 8711 8712 ); 8713 8714 if (dropLocation) { 8715 8716 _this.renderDrag(dropLocation); // called without a seg parameter 8717 8718 } 8719 8720 else { // invalid hit 8721 8722 disableCursor(); 8723 8724 } 8725 8726 }, 8727 8728 hitOut: function() { 8729 8730 dropLocation = null; // signal unsuccessful 8731 8732 _this.unrenderDrag(); 8733 8734 enableCursor(); 8735 8736 }, 8737 8738 dragStop: function() { 8739 8740 _this.unrenderDrag(); 8741 8742 enableCursor(); 8743 8744 8745 8746 if (dropLocation) { // element was dropped on a valid hit 8747 8748 _this.view.reportExternalDrop(meta, dropLocation, el, ev, ui); 8749 8750 } 8751 8752 }, 8753 8754 listenStop: function() { 8755
8756 _this.isDraggingExternal = false; 8757 8758 } 8759 8760 }); 8761 8762 8763 8764 dragListener.startDrag(ev); // start listening immediately 8765 8766 }, 8767 8768 8769 8770 8771 8772 // Given a hit to be dropped upon, and misc data associated with the jqui drag (guaranteed to be a plain object), 8773 8774 // returns the zoned start/end dates for the event that would result from the hypothetical drop. end might be null. 8775 8776 // Returning a null value signals an invalid drop hit. 8777 8778 computeExternalDrop: function(span, meta) { 8779 8780 var calendar = this.view.calendar; 8781 8782 var dropLocation = { 8783 8784 start: calendar.applyTimezone(span.start), // simulate a zoned event start date 8785 8786 end: null 8787 8788 }; 8789 8790 8791 8792 // if dropped on an all-day span, and element's metadata specified a time, set it 8793 8794 if (meta.startTime && !dropLocation.start.hasTime()) { 8795 8796 dropLocation.start.time(meta.startTime); 8797 8798 } 8799 8800 8801 8802 if (meta.duration) { 8803 8804 dropLocation.end = dropLocation.start.clone().add(meta.duration); 8805 8806 } 8807 8808 8809 8810 if (!calendar.isExternalSpanAllowed(this.eventToSpan(dropLocation), dropLocation, meta.eventProps)) { 8811 8812 return null; 8813 8814 } 8815 8816 8817 8818 return dropLocation; 8819 8820 }, 8821 8822 8823 8824 8825 8826 8827 8828 /* Drag Rendering (for both events and an external elements) 8829 8830 ------------------------------------------------------------------------------------------------------------------*/ 8831 8832 8833 8834 8835 8836 // Renders a visual indication of an event or external element being dragged. 8837 8838 // `dropLocation` contains hypothetical start/end/allDay values the event would have if dropped. end can be null. 8839 8840 // `seg` is the internal segment object that is being dragged. If dragging an external element, `seg` is null. 8841 8842 // A truthy returned value indicates this method has rendered a helper element. 8843 8844 renderDrag: function(dropLocation, seg) { 8845 8846 // subclasses must implement 8847 8848 }, 8849 8850 8851 8852 8853 8854 // Unrenders a visual indication of an event or external element being dragged 8855 8856 unrenderDrag: function() { 8857 8858 // subclasses must implement 8859 8860 }, 8861 8862 8863 8864 8865 8866 /* Resizing 8867 8868 ------------------------------------------------------------------------------------------------------------------*/ 8869 8870 8871 8872 8873 8874 // Called when the user does a mousedown on an event's resizer, which might lead to resizing. 8875 8876 // Generic enough to work with any type of Grid. 8877 8878 segResizeMousedown: function(seg, ev, isStart) { 8879 8880 var _this = this; 8881 8882 var view = this.view; 8883 8884 var calendar = view.calendar; 8885 8886 var el = seg.el; 8887 8888 var event = seg.event; 8889 8890 var eventEnd = calendar.getEventEnd(event); 8891 8892 var resizeLocation; // zoned event date properties. falsy if invalid resize 8893 8894 8895 8896 // Tracks mouse movement over the *grid's* coordinate map 8897 8898 var dragListener = new HitDragListener(this, { 8899 8900 distance: 5, 8901 8902 scroll: view.opt('dragScroll'), 8903 8904 subjectEl: el, 8905 8906 dragStart: function(ev) { 8907 8908 _this.triggerSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported 8909 8910 _this.segResizeStart(seg, ev); 8911 8912 }, 8913 8914 hitOver: function(hit, isOrig, origHit) { 8915 8916 var origHitSpan = _this.getHitSpan(origHit); 8917 8918 var hitSpan = _this.getHitSpan(hit); 8919 8920 8921 8922 resizeLocation = isStart ? 8923 8924 _this.computeEventStartResize(origHitSpan, hitSpan, event) : 8925 8926 _this.computeEventEndResize(origHitSpan, hitSpan, event); 8927 8928 8929 8930 if (resizeLocation) { 8931 8932 if (!calendar.isEventSpanAllowed(_this.eventToSpan(resizeLocation), event)) { 8933 8934 disableCursor(); 8935 8936 resizeLocation = null; 8937 8938 } 8939 8940 // no change? (TODO: how does this work with timezones?) 8941 8942 else if (resizeLocation.start.isSame(event.start) && resizeLocation.end.isSame(eventEnd)) { 8943 8944 resizeLocation = null; 8945 8946 } 8947 8948 } 8949 8950 8951 8952 if (resizeLocation) { 8953 8954 view.hideEvent(event); 8955 8956 _this.renderEventResize(resizeLocation, seg); 8957 8958 } 8959 8960 }, 8961 8962 hitOut: function() { // called before mouse moves to a different hit OR moved out of all hits 8963 8964 resizeLocation = null; 8965 8966 }, 8967 8968 hitDone: function() { // resets the rendering to show the original event 8969 8970 _this.unrenderEventResize(); 8971 8972 view.showEvent(event); 8973 8974 enableCursor(); 8975 8976 }, 8977 8978 dragStop: function(ev) { 8979 8980 _this.segResizeStop(seg, ev); 8981 8982 8983 8984 if (resizeLocation) { // valid date to resize to? 8985 8986 view.reportEventResize(event, resizeLocation, this.largeUnit, el, ev); 8987 8988 } 8989 8990 } 8991 8992 }); 8993 8994 8995 8996 dragListener.mousedown(ev); // start listening, which will eventually lead to a dragStart 8997 8998 }, 8999 9000 9001 9002 9003 9004 // Called before event segment resizing starts 9005 9006 segResizeStart: function(seg, ev) { 9007 9008 this.isResizingSeg = true; 9009 9010 this.view.trigger('eventResizeStart', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy 9011 9012 }, 9013 9014 9015 9016 9017 9018 // Called after event segment resizing stops 9019 9020 segResizeStop: function(seg, ev) { 9021 9022 this.isResizingSeg = false;
9023 9024 this.view.trigger('eventResizeStop', seg.el[0], seg.event, ev, {}); // last argument is jqui dummy 9025 9026 }, 9027 9028 9029 9030 9031 9032 // Returns new date-information for an event segment being resized from its start 9033 9034 computeEventStartResize: function(startSpan, endSpan, event) { 9035 9036 return this.computeEventResize('start', startSpan, endSpan, event); 9037 9038 }, 9039 9040 9041 9042 9043 9044 // Returns new date-information for an event segment being resized from its end 9045 9046 computeEventEndResize: function(startSpan, endSpan, event) { 9047 9048 return this.computeEventResize('end', startSpan, endSpan, event); 9049 9050 }, 9051 9052 9053 9054 9055 9056 // Returns new zoned date information for an event segment being resized from its start OR end 9057 9058 // `type` is either 'start' or 'end' 9059 9060 computeEventResize: function(type, startSpan, endSpan, event) { 9061 9062 var calendar = this.view.calendar; 9063 9064 var delta = this.diffDates(endSpan[type], startSpan[type]); 9065 9066 var resizeLocation; // zoned event date properties 9067 9068 var defaultDuration; 9069 9070 9071 9072 // build original values to work from, guaranteeing a start and end 9073 9074 resizeLocation = { 9075 9076 start: event.start.clone(), 9077 9078 end: calendar.getEventEnd(event), 9079 9080 allDay: event.allDay 9081 9082 }; 9083 9084 9085 9086 // if an all-day event was in a timed area and was resized to a time, adjust start/end to have times 9087 9088 if (resizeLocation.allDay && durationHasTime(delta)) { 9089 9090 resizeLocation.allDay = false; 9091 9092 calendar.normalizeEventTimes(resizeLocation); 9093 9094 } 9095 9096 9097 9098 resizeLocation[type].add(delta); // apply delta to start or end 9099 9100 9101 9102 // if the event was compressed too small, find a new reasonable duration for it 9103 9104 if (!resizeLocation.start.isBefore(resizeLocation.end)) { 9105 9106 9107 9108 defaultDuration = 9109 9110 this.minResizeDuration || // TODO: hack 9111 9112 (event.allDay ? 9113 9114 calendar.defaultAllDayEventDuration : 9115 9116 calendar.defaultTimedEventDuration); 9117 9118 9119 9120 if (type == 'start') { // resizing the start? 9121 9122 resizeLocation.start = resizeLocation.end.clone().subtract(defaultDuration); 9123 9124 } 9125 9126 else { // resizing the end? 9127 9128 resizeLocation.end = resizeLocation.start.clone().add(defaultDuration); 9129 9130 } 9131 9132 } 9133 9134 9135 9136 return resizeLocation; 9137 9138 }, 9139 9140 9141 9142 9143 9144 // Renders a visual indication of an event being resized. 9145 9146 // `range` has the updated dates of the event. `seg` is the original segment object involved in the drag. 9147 9148 renderEventResize: function(range, seg) { 9149 9150 // subclasses must implement 9151 9152 }, 9153 9154 9155 9156 9157 9158 // Unrenders a visual indication of an event being resized. 9159 9160 unrenderEventResize: function() { 9161 9162 // subclasses must implement 9163 9164 }, 9165 9166 9167 9168 9169 9170 /* Rendering Utils 9171 9172 ------------------------------------------------------------------------------------------------------------------*/ 9173 9174 9175 9176 9177 9178 // Compute the text that should be displayed on an event's element. 9179 9180 // `range` can be the Event object itself, or something range-like, with at least a `start`. 9181 9182 // If event times are disabled, or the event has no time, will return a blank string. 9183 9184 // If not specified, formatStr will default to the eventTimeFormat setting, 9185 9186 // and displayEnd will default to the displayEventEnd setting. 9187 9188 getEventTimeText: function(range, formatStr, displayEnd) { 9189 9190 9191 9192 if (formatStr == null) { 9193 9194 formatStr = this.eventTimeFormat; 9195 9196 } 9197 9198 9199 9200 if (displayEnd == null) { 9201 9202 displayEnd = this.displayEventEnd; 9203 9204 } 9205 9206 9207 9208 if (this.displayEventTime && range.start.hasTime()) { 9209 9210 if (displayEnd && range.end) { 9211 9212 return this.view.formatRange(range, formatStr); 9213 9214 } 9215 9216 else { 9217 9218 return range.start.format(formatStr); 9219 9220 } 9221 9222 } 9223 9224 9225 9226 return ''; 9227 9228 }, 9229 9230 9231 9232 9233 9234 // Generic utility for generating the HTML classNames for an event segment's element 9235 9236 getSegClasses: function(seg, isDraggable, isResizable) { 9237 9238 var event = seg.event; 9239 9240 var classes = [ 9241 9242 'fc-event', 9243 9244 seg.isStart ? 'fc-start' : 'fc-not-start', 9245 9246 seg.isEnd ? 'fc-end' : 'fc-not-end' 9247 9248 ].concat( 9249 9250 event.className, 9251 9252 event.source ? event.source.className : [] 9253 9254 ); 9255 9256 9257 9258 if (isDraggable) { 9259 9260 classes.push('fc-draggable'); 9261 9262 } 9263 9264 if (isResizable) { 9265 9266 classes.push('fc-resizable'); 9267 9268 } 9269 9270 9271 9272 return classes; 9273 9274 }, 9275 9276 9277 9278 9279 9280 // Utility for generating event skin-related CSS properties 9281 9282 getEventSkinCss: function(event) { 9283 9284 var view = this.view; 9285 9286 var source = event.source || {}; 9287 9288 var eventColor = event.color; 9289 9290 var sourceColor = source.color; 9291 9292 var optionColor = view.opt('eventColor'); 9293 9294 9295 9296 return { 9297 9298 'background-color': 9299 9300 event.backgroundColor || 9301 9302 eventColor || 9303 9304 source.backgroundColor || 9305 9306 sourceColor || 9307
9308 view.opt('eventBackgroundColor') || 9309 9310 optionColor, 9311 9312 'border-color': 9313 9314 event.borderColor || 9315 9316 eventColor || 9317 9318 source.borderColor || 9319 9320 sourceColor || 9321 9322 view.opt('eventBorderColor') || 9323 9324 optionColor, 9325 9326 color: 9327 9328 event.textColor || 9329 9330 source.textColor || 9331 9332 view.opt('eventTextColor') 9333 9334 }; 9335 9336 }, 9337 9338 9339 9340 9341 9342 /* Converting events -> eventRange -> eventSpan -> eventSegs 9343 9344 ------------------------------------------------------------------------------------------------------------------*/ 9345 9346 9347 9348 9349 9350 // Generates an array of segments for the given single event 9351 9352 eventToSegs: function(event) { 9353 9354 return this.eventsToSegs([ event ]); 9355 9356 }, 9357 9358 9359 9360 9361 9362 // Generates a single span (always unzoned) by using the given event's dates. 9363 9364 // Does not do any inverting for inverse-background events. 9365 9366 eventToSpan: function(event) { 9367 9368 var range = this.eventToRange(event); 9369 9370 this.transformEventSpan(range, event); // convert it to a span, in-place 9371 9372 return range; 9373 9374 }, 9375 9376 9377 9378 9379 9380 // Converts an array of event objects into an array of event segment objects. 9381 9382 // A custom `segSliceFunc` may be given for arbitrarily slicing up events. 9383 9384 // Doesn't guarantee an order for the resulting array. 9385 9386 eventsToSegs: function(allEvents, segSliceFunc) { 9387 9388 var _this = this; 9389 9390 var eventsById = groupEventsById(allEvents); 9391 9392 var segs = []; 9393 9394 9395 9396 $.each(eventsById, function(id, events) { 9397 9398 var ranges = []; 9399 9400 var i; 9401 9402 9403 9404 for (i = 0; i < events.length; i++) { 9405 9406 ranges.push(_this.eventToRange(events[i])); 9407 9408 } 9409 9410 9411 9412 // inverse-background events (utilize only the first event in calculations) 9413 9414 if (isInverseBgEvent(events[0])) { 9415 9416 ranges = _this.invertRanges(ranges); 9417 9418 9419 9420 for (i = 0; i < ranges.length; i++) { 9421 9422 _this.generateEventSegs(ranges[i], events[0], segSliceFunc, segs); 9423 9424 } 9425 9426 } 9427 9428 // normal event ranges 9429 9430 else { 9431 9432 for (i = 0; i < ranges.length; i++) { 9433 9434 _this.generateEventSegs(ranges[i], events[i], segSliceFunc, segs); 9435 9436 } 9437 9438 } 9439 9440 }); 9441 9442 9443 9444 return segs; 9445 9446 }, 9447 9448 9449 9450 9451 9452 // Generates the unzoned start/end dates an event appears to occupy 9453 9454 eventToRange: function(event) { 9455 9456 return { 9457 9458 start: event.start.clone().stripZone(), 9459 9460 end: this.view.calendar.getEventEnd(event).stripZone() 9461 9462 }; 9463 9464 }, 9465 9466 9467 9468 9469 9470 // Given an event's span (unzoned start/end and other misc data), and the event itself, 9471 9472 // slice into segments (using the segSliceFunc function if specified) and append to the `out` array. 9473 9474 // SIDE EFFECT: will mutate the given `range`. 9475 9476 generateEventSegs: function(range, event, segSliceFunc, out) { 9477 9478 var segs; 9479 9480 var i; 9481 9482 9483 9484 this.transformEventSpan(range, event); // converts the range to a span 9485 9486 9487 9488 segs = segSliceFunc ? segSliceFunc(range) : this.spanToSegs(range); 9489 9490 9491 9492 for (i = 0; i < segs.length; i++) { 9493 9494 this.transformEventSeg(segs[i], range, event); 9495 9496 out.push(segs[i]); 9497 9498 } 9499 9500 }, 9501 9502 9503 9504 9505 9506 // Given a range (unzoned start/end) that is about to become a span, 9507 9508 // attach any event-derived properties to it. 9509 9510 transformEventSpan: function(range, event) { 9511 9512 // subclasses can implement 9513 9514 }, 9515 9516 9517 9518 9519 9520 // Given a segment object, attach any extra properties, based off of its source span and event. 9521 9522 transformEventSeg: function(seg, span, event) { 9523 9524 seg.event = event; 9525 9526 seg.eventStartMS = +span.start; // TODO: not the best name after making spans unzoned 9527 9528 seg.eventDurationMS = span.end - span.start; 9529 9530 }, 9531 9532 9533 9534 9535 9536 // Produces a new array of range objects that will cover all the time NOT covered by the given ranges. 9537 9538 // SIDE EFFECT: will mutate the given array and will use its date references. 9539 9540 invertRanges: function(ranges) { 9541 9542 var view = this.view; 9543 9544 var viewStart = view.start.clone(); // need a copy 9545 9546 var viewEnd = view.end.clone(); // need a copy 9547 9548 var inverseRanges = []; 9549 9550 var start = viewStart; // the end of the previous range. the start of the new range 9551 9552 var i, range; 9553 9554 9555 9556 // ranges need to be in order. required for our date-walking algorithm 9557 9558 ranges.sort(compareRanges); 9559 9560 9561 9562 for (i = 0; i < ranges.length; i++) { 9563 9564 range = ranges[i]; 9565 9566 9567 9568 // add the span of time before the event (if there is any) 9569 9570 if (range.start > start) { // compare millisecond time (skip any ambig logic) 9571 9572 inverseRanges.push({ 9573 9574 start: start, 9575 9576 end: range.start 9577 9578 }); 9579 9580 } 9581 9582 9583 9584 start = range.end; 9585 9586 } 9587 9588 9589 9590 // add the span of time after the last event (if there is any) 9591 9592 if (start < viewEnd) { // compare millisecond time (skip any ambig logic) 9593 9594 inverseRanges.push({ 9595 9596 start: start, 9597 9598 end: viewEnd 9599 9600 }); 9601 9602 } 9603 9604 9605 9606 return inverseRanges; 9607 9608 }, 9609 9610 9611 9612 9613 9614 sortEventSegs: function(segs) { 9615 9616 segs.sort(proxy(this, 'compareEventSegs')); 9617 9618 }, 9619 9620 9621 9622 9623 9624 // A cmp function for determining which segments should take visual priority 9625 9626 compareEventSegs: function(seg1, seg2) { 9627 9628 return seg1.eventStartMS - seg2.eventStartMS || // earlier events go first 9629 9630 seg2.eventDurationMS - seg1.eventDurationMS || // tie? longer events go first 9631 9632 seg2.event.allDay - seg1.event.allDay || // tie? put all-day events first (booleans cast to 0/1) 9633 9634 compareByFieldSpecs(seg1.event, seg2.event, this.view.eventOrderSpecs); 9635 9636 } 9637 9638 9639 9640 }); 9641 9642 9643 9644 9645 9646 /* Utilities 9647 9648 ----------------------------------------------------------------------------------------------------------------------*/ 9649 9650 9651 9652 9653 9654 function isBgEvent(event) { // returns true if background OR inverse-background 9655 9656 var rendering = getEventRendering(event); 9657 9658 return rendering === 'background' || rendering === 'inverse-background'; 9659 9660 } 9661 9662 9663 9664 9665 9666 function isInverseBgEvent(event) { 9667
9668 return getEventRendering(event) === 'inverse-background'; 9669 9670 } 9671 9672 9673 9674 9675 9676 function getEventRendering(event) { 9677 9678 return firstDefined((event.source || {}).rendering, event.rendering); 9679 9680 } 9681 9682 9683 9684 9685 9686 function groupEventsById(events) { 9687 9688 var eventsById = {}; 9689 9690 var i, event; 9691 9692 9693 9694 for (i = 0; i < events.length; i++) { 9695 9696 event = events[i]; 9697 9698 (eventsById[event._id] || (eventsById[event._id] = [])).push(event); 9699 9700 } 9701 9702 9703 9704 return eventsById; 9705 9706 } 9707 9708 9709 9710 9711 9712// A cmp function for determining which non-inverted "ranges" (see above) happen earlier 9713 9714 function compareRanges(range1, range2) { 9715 9716 return range1.start - range2.start; // earlier ranges go first 9717 9718 } 9719 9720 9721 9722 9723 9724 /* External-Dragging-Element Data 9725 9726 ----------------------------------------------------------------------------------------------------------------------*/ 9727 9728 9729 9730// Require all HTML5 data-* attributes used by FullCalendar to have this prefix. 9731 9732// A value of '' will query attributes like data-event. A value of 'fc' will query attributes like data-fc-event. 9733 9734 FC.dataAttrPrefix = ''; 9735 9736 9737 9738// Given a jQuery element that might represent a dragged FullCalendar event, returns an intermediate data structure 9739 9740// to be used for Event Object creation. 9741 9742// A defined `.eventProps`, even when empty, indicates that an event should be created. 9743 9744 function getDraggedElMeta(el) { 9745 9746 var prefix = FC.dataAttrPrefix; 9747 9748 var eventProps; // properties for creating the event, not related to date/time 9749 9750 var startTime; // a Duration 9751 9752 var duration; 9753 9754 var stick; 9755 9756 9757 9758 if (prefix) { prefix += '-'; } 9759 9760 eventProps = el.data(prefix + 'event') || null; 9761 9762 9763 9764 if (eventProps) { 9765 9766 if (typeof eventProps === 'object') { 9767 9768 eventProps = $.extend({}, eventProps); // make a copy 9769 9770 } 9771 9772 else { // something like 1 or true. still signal event creation 9773 9774 eventProps = {}; 9775 9776 } 9777 9778 9779 9780 // pluck special-cased date/time properties 9781 9782 startTime = eventProps.start; 9783 9784 if (startTime == null) { startTime = eventProps.time; } // accept 'time' as well 9785 9786 duration = eventProps.duration; 9787 9788 stick = eventProps.stick; 9789 9790 delete eventProps.start; 9791 9792 delete eventProps.time; 9793 9794 delete eventProps.duration; 9795 9796 delete eventProps.stick; 9797 9798 } 9799 9800 9801 9802 // fallback to standalone attribute values for each of the date/time properties 9803 9804 if (startTime == null) { startTime = el.data(prefix + 'start'); } 9805 9806 if (startTime == null) { startTime = el.data(prefix + 'time'); } // accept 'time' as well 9807 9808 if (duration == null) { duration = el.data(prefix + 'duration'); } 9809 9810 if (stick == null) { stick = el.data(prefix + 'stick'); } 9811 9812 9813 9814 // massage into correct data types 9815 9816 startTime = startTime != null ? moment.duration(startTime) : null; 9817 9818 duration = duration != null ? moment.duration(duration) : null; 9819 9820 stick = Boolean(stick); 9821 9822 9823 9824 return { eventProps: eventProps, startTime: startTime, duration: duration, stick: stick }; 9825 9826 } 9827 9828 9829 9830 9831 9832 ;; 9833 9834 9835 9836 /* 9837 9838 A set of rendering and date-related methods for a visual component comprised of one or more rows of day columns. 9839 9840 Prerequisite: the object being mixed into needs to be a *Grid* 9841 9842 */ 9843 9844 var DayTableMixin = FC.DayTableMixin = { 9845 9846 9847 9848 breakOnWeeks: false, // should create a new row for each week? 9849 9850 dayDates: null, // whole-day dates for each column. left to right 9851 9852 dayIndices: null, // for each day from start, the offset 9853 9854 daysPerRow: null, 9855 9856 rowCnt: null, 9857 9858 colCnt: null, 9859 9860 colHeadFormat: null, 9861 9862 9863 9864 9865 9866 // Populates internal variables used for date calculation and rendering 9867 9868 updateDayTable: function() { 9869 9870 var view = this.view; 9871 9872 var date = this.start.clone(); 9873 9874 var dayIndex = -1; 9875 9876 var dayIndices = []; 9877 9878 var dayDates = []; 9879 9880 var daysPerRow; 9881 9882 var firstDay; 9883 9884 var rowCnt; 9885 9886 9887 9888 while (date.isBefore(this.end)) { // loop each day from start to end 9889 9890 if (view.isHiddenDay(date)) { 9891 9892 dayIndices.push(dayIndex + 0.5); // mark that it's between indices 9893 9894 } 9895 9896 else { 9897 9898 dayIndex++; 9899 9900 dayIndices.push(dayIndex); 9901 9902 dayDates.push(date.clone()); 9903 9904 } 9905 9906 date.add(1, 'days'); 9907 9908 } 9909 9910 9911 9912 if (this.breakOnWeeks) { 9913 9914 // count columns until the day-of-week repeats 9915 9916 firstDay = dayDates[0].day(); 9917 9918 for (daysPerRow = 1; daysPerRow < dayDates.length; daysPerRow++) { 9919 9920 if (dayDates[daysPerRow].day() == firstDay) { 9921 9922 break; 9923 9924 } 9925 9926 } 9927
9928 rowCnt = Math.ceil(dayDates.length / daysPerRow); 9929 9930 } 9931 9932 else { 9933 9934 rowCnt = 1; 9935 9936 daysPerRow = dayDates.length; 9937 9938 } 9939 9940 9941 9942 this.dayDates = dayDates; 9943 9944 this.dayIndices = dayIndices; 9945 9946 this.daysPerRow = daysPerRow; 9947 9948 this.rowCnt = rowCnt; 9949 9950 9951 9952 this.updateDayTableCols(); 9953 9954 }, 9955 9956 9957 9958 9959 9960 // Computes and assigned the colCnt property and updates any options that may be computed from it 9961 9962 updateDayTableCols: function() { 9963 9964 this.colCnt = this.computeColCnt(); 9965 9966 this.colHeadFormat = this.view.opt('columnFormat') || this.computeColHeadFormat(); 9967 9968 }, 9969 9970 9971 9972 9973 9974 // Determines how many columns there should be in the table 9975 9976 computeColCnt: function() { 9977 9978 return this.daysPerRow; 9979 9980 }, 9981 9982 9983 9984 9985 9986 // Computes the ambiguously-timed moment for the given cell 9987 9988 getCellDate: function(row, col) { 9989 9990 return this.dayDates[ 9991 9992 this.getCellDayIndex(row, col) 9993 9994 ].clone(); 9995 9996 }, 9997 9998 9999 10000 10001 10002 // Computes the ambiguously-timed date range for the given cell 10003 10004 getCellRange: function(row, col) { 10005 10006 var start = this.getCellDate(row, col); 10007 10008 var end = start.clone().add(1, 'days'); 10009 10010 10011 10012 return { start: start, end: end }; 10013 10014 }, 10015 10016 10017 10018 10019 10020 // Returns the number of day cells, chronologically, from the first of the grid (0-based) 10021 10022 getCellDayIndex: function(row, col) { 10023 10024 return row * this.daysPerRow + this.getColDayIndex(col); 10025 10026 }, 10027 10028 10029 10030 10031 10032 // Returns the numner of day cells, chronologically, from the first cell in *any given row* 10033 10034 getColDayIndex: function(col) { 10035 10036 if (this.isRTL) { 10037 10038 return this.colCnt - 1 - col; 10039 10040 } 10041 10042 else { 10043 10044 return col; 10045 10046 } 10047 10048 }, 10049 10050 10051 10052 10053 10054 // Given a date, returns its chronolocial cell-index from the first cell of the grid. 10055 10056 // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets. 10057 10058 // If before the first offset, returns a negative number. 10059 10060 // If after the last offset, returns an offset past the last cell offset. 10061 10062 // Only works for *start* dates of cells. Will not work for exclusive end dates for cells. 10063 10064 getDateDayIndex: function(date) { 10065 10066 var dayIndices = this.dayIndices; 10067 10068 var dayOffset = date.diff(this.start, 'days'); 10069 10070 10071 10072 if (dayOffset < 0) { 10073 10074 return dayIndices[0] - 1; 10075 10076 } 10077 10078 else if (dayOffset >= dayIndices.length) { 10079 10080 return dayIndices[dayIndices.length - 1] + 1; 10081 10082 } 10083 10084 else { 10085 10086 return dayIndices[dayOffset]; 10087 10088 } 10089 10090 }, 10091 10092 10093 10094 10095 10096 /* Options 10097 10098 ------------------------------------------------------------------------------------------------------------------*/ 10099 10100 10101 10102 10103 10104 // Computes a default column header formatting string if `colFormat` is not explicitly defined 10105 10106 computeColHeadFormat: function() { 10107 10108 // if more than one week row, or if there are a lot of columns with not much space, 10109 10110 // put just the day numbers will be in each cell 10111 10112 if (this.rowCnt > 1 || this.colCnt > 10) { 10113 10114 return 'ddd'; // "Sat" 10115 10116 } 10117 10118 // multiple days, so full single date string WON'T be in title text 10119 10120 else if (this.colCnt > 1) { 10121 10122 return this.view.opt('dayOfMonthFormat'); // "Sat 12/10" 10123 10124 } 10125 10126 // single day, so full single date string will probably be in title text 10127 10128 else { 10129 10130 return 'dddd'; // "Saturday" 10131 10132 } 10133 10134 }, 10135 10136 10137 10138 10139 10140 /* Slicing 10141 10142 ------------------------------------------------------------------------------------------------------------------*/ 10143 10144 10145 10146 10147 10148 // Slices up a date range into a segment for every week-row it intersects with 10149 10150 sliceRangeByRow: function(range) { 10151 10152 var daysPerRow = this.daysPerRow; 10153 10154 var normalRange = this.view.computeDayRange(range); // make whole-day range, considering nextDayThreshold 10155 10156 var rangeFirst = this.getDateDayIndex(normalRange.start); // inclusive first index 10157 10158 var rangeLast = this.getDateDayIndex(normalRange.end.clone().subtract(1, 'days')); // inclusive last index 10159 10160 var segs = []; 10161 10162 var row; 10163 10164 var rowFirst, rowLast; // inclusive day-index range for current row 10165 10166 var segFirst, segLast; // inclusive day-index range for segment 10167 10168 10169 10170 for (row = 0; row < this.rowCnt; row++) { 10171 10172 rowFirst = row * daysPerRow; 10173 10174 rowLast = rowFirst + daysPerRow - 1; 10175 10176 10177 10178 // intersect segment's offset range with the row's 10179 10180 segFirst = Math.max(rangeFirst, rowFirst); 10181 10182 segLast = Math.min(rangeLast, rowLast); 10183 10184 10185 10186 // deal with in-between indices 10187
10188 segFirst = Math.ceil(segFirst); // in-between starts round to next cell 10189 10190 segLast = Math.floor(segLast); // in-between ends round to prev cell 10191 10192 10193 10194 if (segFirst <= segLast) { // was there any intersection with the current row? 10195 10196 segs.push({ 10197 10198 row: row, 10199 10200 10201 10202 // normalize to start of row 10203 10204 firstRowDayIndex: segFirst - rowFirst, 10205 10206 lastRowDayIndex: segLast - rowFirst, 10207 10208 10209 10210 // must be matching integers to be the segment's start/end 10211 10212 isStart: segFirst === rangeFirst, 10213 10214 isEnd: segLast === rangeLast 10215 10216 }); 10217 10218 } 10219 10220 } 10221 10222 10223 10224 return segs; 10225 10226 }, 10227 10228 10229 10230 10231 10232 // Slices up a date range into a segment for every day-cell it intersects with. 10233 10234 // TODO: make more DRY with sliceRangeByRow somehow. 10235 10236 sliceRangeByDay: function(range) { 10237 10238 var daysPerRow = this.daysPerRow; 10239 10240 var normalRange = this.view.computeDayRange(range); // make whole-day range, considering nextDayThreshold 10241 10242 var rangeFirst = this.getDateDayIndex(normalRange.start); // inclusive first index 10243 10244 var rangeLast = this.getDateDayIndex(normalRange.end.clone().subtract(1, 'days')); // inclusive last index 10245 10246 var segs = []; 10247 10248 var row; 10249 10250 var rowFirst, rowLast; // inclusive day-index range for current row 10251 10252 var i; 10253 10254 var segFirst, segLast; // inclusive day-index range for segment 10255 10256 10257 10258 for (row = 0; row < this.rowCnt; row++) { 10259 10260 rowFirst = row * daysPerRow; 10261 10262 rowLast = rowFirst + daysPerRow - 1; 10263 10264 10265 10266 for (i = rowFirst; i <= rowLast; i++) { 10267 10268 10269 10270 // intersect segment's offset range with the row's 10271 10272 segFirst = Math.max(rangeFirst, i); 10273 10274 segLast = Math.min(rangeLast, i); 10275 10276 10277 10278 // deal with in-between indices 10279 10280 segFirst = Math.ceil(segFirst); // in-between starts round to next cell 10281 10282 segLast = Math.floor(segLast); // in-between ends round to prev cell 10283 10284 10285 10286 if (segFirst <= segLast) { // was there any intersection with the current row? 10287 10288 segs.push({ 10289 10290 row: row, 10291 10292 10293 10294 // normalize to start of row 10295 10296 firstRowDayIndex: segFirst - rowFirst, 10297 10298 lastRowDayIndex: segLast - rowFirst, 10299 10300 10301 10302 // must be matching integers to be the segment's start/end 10303 10304 isStart: segFirst === rangeFirst, 10305 10306 isEnd: segLast === rangeLast 10307 10308 }); 10309 10310 } 10311 10312 } 10313 10314 } 10315 10316 10317 10318 return segs; 10319 10320 }, 10321 10322 10323 10324 10325 10326 /* Header Rendering 10327 10328 ------------------------------------------------------------------------------------------------------------------*/ 10329 10330 10331 10332 10333 10334 renderHeadHtml: function() { 10335 10336 var view = this.view; 10337 10338 10339 10340 return '' + 10341 10342 '<div class="fc-row ' + view.widgetHeaderClass + '">' + 10343 10344 '<table>' + 10345 10346 '<thead>' + 10347 10348 this.renderHeadTrHtml() + 10349 10350 '</thead>' + 10351 10352 '</table>' + 10353 10354 '</div>'; 10355 10356 }, 10357 10358 10359 10360 10361 10362 renderHeadIntroHtml: function() { 10363 10364 return this.renderIntroHtml(); // fall back to generic 10365 10366 }, 10367 10368 10369 10370 10371 10372 renderHeadTrHtml: function() { 10373 10374 return '' + 10375 10376 '<tr>' + 10377 10378 (this.isRTL ? '' : this.renderHeadIntroHtml()) + 10379 10380 this.renderHeadDateCellsHtml() + 10381 10382 (this.isRTL ? this.renderHeadIntroHtml() : '') + 10383 10384 '</tr>'; 10385 10386 }, 10387 10388 10389 10390 10391 10392 renderHeadDateCellsHtml: function() { 10393 10394 var htmls = []; 10395 10396 var col, date; 10397 10398 10399 10400 for (col = 0; col < this.colCnt; col++) { 10401 10402 date = this.getCellDate(0, col); 10403 10404 htmls.push(this.renderHeadDateCellHtml(date)); 10405 10406 } 10407 10408 10409 10410 return htmls.join(''); 10411 10412 }, 10413 10414 10415 10416 10417 10418 renderHeadDateCellHtml: function(date, colspan) { 10419 10420 var view = this.view; 10421 10422 10423 10424 return '' + 10425 10426 '<th class="fc-day-header ' + view.widgetHeaderClass + ' fc-' + dayIDs[date.day()] + '"' + 10427 10428 (colspan > 1 ? ' colspan="' + colspan + '"' : '') + 10429 10430 '>' + 10431 10432 htmlEscape(date.format(this.colHeadFormat)) + 10433 10434 '</th>'; 10435 10436 }, 10437 10438 10439 10440 10441 10442 /* Background Rendering 10443 10444 ------------------------------------------------------------------------------------------------------------------*/ 10445 10446 10447 10448 10449 10450 renderBgTrHtml: function(row) { 10451 10452 return '' + 10453 10454 '<tr>' + 10455 10456 (this.isRTL ? '' : this.renderBgIntroHtml(row)) + 10457 10458 this.renderBgCellsHtml(row) + 10459 10460 (this.isRTL ? this.renderBgIntroHtml(row) : '') + 10461 10462 '</tr>'; 10463 10464 }, 10465 10466 10467 10468 10469 10470 renderBgIntroHtml: function(row) { 10471 10472 return this.renderIntroHtml(); // fall back to generic 10473 10474 }, 10475 10476 10477 10478 10479 10480 renderBgCellsHtml: function(row) { 10481 10482 var htmls = []; 10483 10484 var col, date; 10485 10486 10487 10488 for (col = 0; col < this.colCnt; col++) { 10489 10490 date = this.getCellDate(row, col); 10491 10492 htmls.push(this.renderBgCellHtml(date)); 10493 10494 } 10495 10496 10497 10498 return htmls.join(''); 10499 10500 }, 10501 10502 10503 10504 10505 10506 renderBgCellHtml: function(date) { 10507 10508 var view = this.view; 10509 10510 var classes = this.getDayClasses(date); 10511 10512 10513 10514 classes.unshift('fc-day', view.widgetContentClass); 10515 10516 10517 10518 return '<td class="' + classes.join(' ') + '"' + 10519 10520 ' data-date="' + date.format('YYYY-MM-DD') + '"' + // if date has a time, won't format it 10521 10522 '></td>'; 10523 10524 }, 10525 10526 10527 10528 10529 10530 /* Generic 10531 10532 ------------------------------------------------------------------------------------------------------------------*/ 10533 10534 10535 10536 10537 10538 // Generates the default HTML intro for any row. User classes should override 10539 10540 renderIntroHtml: function() { 10541 10542 }, 10543 10544 10545 10546 10547 10548 /* Utils 10549 10550 ------------------------------------------------------------------------------------------------------------------*/ 10551 10552 10553 10554 10555 10556 // Applies the generic "intro" and "outro" HTML to the given cells. 10557 10558 // Intro means the leftmost cell when the calendar is LTR and the rightmost cell when RTL. Vice-versa for outro. 10559 10560 bookendCells: function(trEl) { 10561 10562 var introHtml = this.renderIntroHtml(); 10563 10564 10565 10566 if (introHtml) { 10567 10568 if (this.isRTL) { 10569 10570 trEl.append(introHtml); 10571 10572 } 10573 10574 else { 10575 10576 trEl.prepend(introHtml); 10577 10578 } 10579 10580 } 10581 10582 } 10583 10584 10585 10586 }; 10587 10588 10589 10590 ;; 10591 10592 10593 10594 /* A component that renders a grid of whole-days that runs horizontally. There can be multiple rows, one per week. 10595 10596 ----------------------------------------------------------------------------------------------------------------------*/ 10597 10598 10599 10600 var DayGrid = FC.DayGrid = Grid.extend(DayTableMixin, { 10601 10602 10603 10604 numbersVisible: false, // should render a row for day/week numbers? set by outside view. TODO: make internal 10605 10606 bottomCoordPadding: 0, // hack for extending the hit area for the last row of the coordinate grid 10607 10608 10609 10610 rowEls: null, // set of fake row elements 10611 10612 cellEls: null, // set of whole-day elements comprising the row's background 10613 10614 helperEls: null, // set of cell skeleton elements for rendering the mock event "helper" 10615 10616 10617 10618 rowCoordCache: null, 10619 10620 colCoordCache: null, 10621 10622 10623 10624 10625 10626 // Renders the rows and columns into the component's `this.el`, which should already be assigned. 10627 10628 // isRigid determins whether the individual rows should ignore the contents and be a constant height. 10629 10630 // Relies on the view's colCnt and rowCnt. In the future, this component should probably be self-sufficient. 10631 10632 renderDates: function(isRigid) { 10633 10634 var view = this.view; 10635 10636 var rowCnt = this.rowCnt; 10637 10638 var colCnt = this.colCnt; 10639 10640 var html = ''; 10641 10642 var row; 10643 10644 var col; 10645 10646 10647 10648 for (row = 0; row < rowCnt; row++) { 10649 10650 html += this.renderDayRowHtml(row, isRigid); 10651 10652 } 10653 10654 this.el.html(html); 10655 10656 10657 10658 this.rowEls = this.el.find('.fc-row'); 10659 10660 this.cellEls = this.el.find('.fc-day'); 10661 10662 10663 10664 this.rowCoordCache = new CoordCache({ 10665 10666 els: this.rowEls, 10667 10668 isVertical: true 10669 10670 }); 10671 10672 this.colCoordCache = new CoordCache({ 10673 10674 els: this.cellEls.slice(0, this.colCnt), // only the first row 10675 10676 isHorizontal: true 10677 10678 }); 10679 10680 10681 10682 // trigger dayRender with each cell's element 10683 10684 for (row = 0; row < rowCnt; row++) { 10685 10686 for (col = 0; col < colCnt; col++) { 10687 10688 view.trigger( 10689 10690 'dayRender', 10691 10692 null, 10693 10694 this.getCellDate(row, col), 10695 10696 this.getCellEl(row, col) 10697 10698 ); 10699 10700 } 10701 10702 } 10703 10704 }, 10705 10706 10707 10708 10709 10710 unrenderDates: function() { 10711 10712 this.removeSegPopover(); 10713 10714 }, 10715 10716 10717 10718 10719 10720 renderBusinessHours: function() { 10721 10722 var events = this.view.calendar.getBusinessHoursEvents(true); // wholeDay=true 10723 10724 var segs = this.eventsToSegs(events); 10725 10726 10727 10728 this.renderFill('businessHours', segs, 'bgevent'); 10729 10730 }, 10731 10732 10733 10734 10735 10736 // Generates the HTML for a single row, which is a div that wraps a table. 10737 10738 // `row` is the row number. 10739 10740 renderDayRowHtml: function(row, isRigid) { 10741 10742 var view = this.view; 10743 10744 var classes = [ 'fc-row', 'fc-week', view.widgetContentClass ]; 10745 10746 10747 10748 if (isRigid) { 10749 10750 classes.push('fc-rigid'); 10751 10752 } 10753 10754 10755 10756 return '' + 10757 10758 '<div class="' + classes.join(' ') + '">' + 10759 10760 '<div class="fc-bg">' + 10761 10762 '<table>' + 10763 10764 this.renderBgTrHtml(row) + 10765 10766 '</table>' + 10767 10768 '</div>' + 10769 10770 '<div class="fc-content-skeleton">' + 10771 10772 '<table>' + 10773 10774 (this.numbersVisible ? 10775 10776 '<thead>' + 10777 10778 this.renderNumberTrHtml(row) + 10779 10780 '</thead>' : 10781 10782 '' 10783 10784 ) + 10785 10786 '</table>' + 10787 10788 '</div>' + 10789 10790 '</div>'; 10791 10792 }, 10793 10794 10795 10796 10797 10798 /* Grid Number Rendering 10799 10800 ------------------------------------------------------------------------------------------------------------------*/ 10801 10802 10803 10804 10805 10806 renderNumberTrHtml: function(row) { 10807 10808 return '' + 10809 10810 '<tr>' + 10811 10812 (this.isRTL ? '' : this.renderNumberIntroHtml(row)) + 10813 10814 this.renderNumberCellsHtml(row) + 10815 10816 (this.isRTL ? this.renderNumberIntroHtml(row) : '') + 10817 10818 '</tr>'; 10819 10820 }, 10821 10822 10823 10824 10825 10826 renderNumberIntroHtml: function(row) { 10827 10828 return this.renderIntroHtml(); 10829 10830 }, 10831 10832 10833 10834 10835 10836 renderNumberCellsHtml: function(row) { 10837 10838 var htmls = []; 10839 10840 var col, date; 10841 10842 10843 10844 for (col = 0; col < this.colCnt; col++) { 10845 10846 date = this.getCellDate(row, col); 10847 10848 htmls.push(this.renderNumberCellHtml(date)); 10849 10850 } 10851 10852 10853 10854 return htmls.join(''); 10855 10856 }, 10857 10858 10859 10860 10861 10862 // Generates the HTML for the <td>s of the "number" row in the DayGrid's content skeleton. 10863 10864 // The number row will only exist if either day numbers or week numbers are turned on. 10865 10866 renderNumberCellHtml: function(date) { 10867 10868 var classes; 10869 10870 10871 10872 if (!this.view.dayNumbersVisible) { // if there are week numbers but not day numbers 10873 10874 return '<td/>'; // will create an empty space above events :( 10875 10876 } 10877 10878 10879 10880 classes = this.getDayClasses(date); 10881 10882 classes.unshift('fc-day-number'); 10883 10884 10885 10886 return '' + 10887 10888 '<td class="' + classes.join(' ') + '" data-date="' + date.format() + '">' + 10889 10890 date.date() + 10891 10892 '</td>'; 10893 10894 }, 10895 10896 10897 10898 10899 10900 /* Options 10901 10902 ------------------------------------------------------------------------------------------------------------------*/ 10903 10904 10905 10906 10907 10908 // Computes a default event time formatting string if `timeFormat` is not explicitly defined 10909 10910 computeEventTimeFormat: function() { 10911 10912 return this.view.opt('extraSmallTimeFormat'); // like "6p" or "6:30p" 10913 10914 }, 10915 10916 10917 10918 10919 10920 // Computes a default `displayEventEnd` value if one is not expliclty defined 10921 10922 computeDisplayEventEnd: function() { 10923 10924 return this.colCnt == 1; // we'll likely have space if there's only one day 10925 10926 }, 10927 10928 10929 10930 10931 10932 /* Dates 10933 10934 ------------------------------------------------------------------------------------------------------------------*/ 10935 10936 10937 10938 10939 10940 rangeUpdated: function() { 10941 10942 this.updateDayTable(); 10943 10944 }, 10945 10946 10947 10948 10949 10950 // Slices up the given span (unzoned start/end with other misc data) into an array of segments 10951 10952 spanToSegs: function(span) { 10953 10954 var segs = this.sliceRangeByRow(span); 10955 10956 var i, seg; 10957 10958 10959 10960 for (i = 0; i < segs.length; i++) { 10961 10962 seg = segs[i]; 10963 10964 if (this.isRTL) { 10965 10966 seg.leftCol = this.daysPerRow - 1 - seg.lastRowDayIndex; 10967 10968 seg.rightCol = this.daysPerRow - 1 - seg.firstRowDayIndex; 10969 10970 } 10971 10972 else { 10973
10974 seg.leftCol = seg.firstRowDayIndex; 10975 10976 seg.rightCol = seg.lastRowDayIndex; 10977 10978 } 10979 10980 } 10981 10982 10983 10984 return segs; 10985 10986 }, 10987 10988 10989 10990 10991 10992 /* Hit System 10993 10994 ------------------------------------------------------------------------------------------------------------------*/ 10995 10996 10997 10998 10999 11000 prepareHits: function() { 11001 11002 this.colCoordCache.build(); 11003 11004 this.rowCoordCache.build(); 11005 11006 this.rowCoordCache.bottoms[this.rowCnt - 1] += this.bottomCoordPadding; // hack 11007 11008 }, 11009 11010 11011 11012 11013 11014 releaseHits: function() { 11015 11016 this.colCoordCache.clear(); 11017 11018 this.rowCoordCache.clear(); 11019 11020 }, 11021 11022 11023 11024 11025 11026 queryHit: function(leftOffset, topOffset) { 11027 11028 var col = this.colCoordCache.getHorizontalIndex(leftOffset); 11029 11030 var row = this.rowCoordCache.getVerticalIndex(topOffset); 11031 11032 11033 11034 if (row != null && col != null) { 11035 11036 return this.getCellHit(row, col); 11037 11038 } 11039 11040 }, 11041 11042 11043 11044 11045 11046 getHitSpan: function(hit) { 11047 11048 return this.getCellRange(hit.row, hit.col); 11049 11050 }, 11051 11052 11053 11054 11055 11056 getHitEl: function(hit) { 11057 11058 return this.getCellEl(hit.row, hit.col); 11059 11060 }, 11061 11062 11063 11064 11065 11066 /* Cell System 11067 11068 ------------------------------------------------------------------------------------------------------------------*/ 11069 11070 // FYI: the first column is the leftmost column, regardless of date 11071 11072 11073 11074 11075 11076 getCellHit: function(row, col) { 11077 11078 return { 11079 11080 row: row, 11081 11082 col: col, 11083 11084 component: this, // needed unfortunately :( 11085 11086 left: this.colCoordCache.getLeftOffset(col), 11087 11088 right: this.colCoordCache.getRightOffset(col), 11089 11090 top: this.rowCoordCache.getTopOffset(row), 11091 11092 bottom: this.rowCoordCache.getBottomOffset(row) 11093 11094 }; 11095 11096 }, 11097 11098 11099 11100 11101 11102 getCellEl: function(row, col) { 11103 11104 return this.cellEls.eq(row * this.colCnt + col); 11105 11106 }, 11107 11108 11109 11110 11111 11112 /* Event Drag Visualization 11113 11114 ------------------------------------------------------------------------------------------------------------------*/ 11115 11116 // TODO: move to DayGrid.event, similar to what we did with Grid's drag methods 11117 11118 11119 11120 11121 11122 // Renders a visual indication of an event or external element being dragged. 11123 11124 // `eventLocation` has zoned start and end (optional) 11125 11126 renderDrag: function(eventLocation, seg) { 11127 11128 11129 11130 // always render a highlight underneath 11131 11132 this.renderHighlight(this.eventToSpan(eventLocation)); 11133 11134 11135 11136 // if a segment from the same calendar but another component is being dragged, render a helper event 11137 11138 if (seg && !seg.el.closest(this.el).length) { 11139 11140 11141 11142 this.renderEventLocationHelper(eventLocation, seg); 11143 11144 this.applyDragOpacity(this.helperEls); 11145 11146 11147 11148 return true; // a helper has been rendered 11149 11150 } 11151 11152 }, 11153 11154 11155 11156 11157 11158 // Unrenders any visual indication of a hovering event 11159 11160 unrenderDrag: function() { 11161 11162 this.unrenderHighlight(); 11163 11164 this.unrenderHelper(); 11165 11166 }, 11167 11168 11169 11170 11171 11172 /* Event Resize Visualization 11173 11174 ------------------------------------------------------------------------------------------------------------------*/ 11175 11176 11177 11178 11179 11180 // Renders a visual indication of an event being resized 11181 11182 renderEventResize: function(eventLocation, seg) { 11183 11184 this.renderHighlight(this.eventToSpan(eventLocation)); 11185 11186 this.renderEventLocationHelper(eventLocation, seg); 11187 11188 }, 11189 11190 11191 11192 11193 11194 // Unrenders a visual indication of an event being resized 11195 11196 unrenderEventResize: function() { 11197 11198 this.unrenderHighlight(); 11199 11200 this.unrenderHelper(); 11201 11202 }, 11203 11204 11205 11206 11207 11208 /* Event Helper 11209 11210 ------------------------------------------------------------------------------------------------------------------*/ 11211 11212 11213 11214 11215 11216 // Renders a mock "helper" event. `sourceSeg` is the associated internal segment object. It can be null. 11217 11218 renderHelper: function(event, sourceSeg) { 11219 11220 var helperNodes = []; 11221 11222 var segs = this.eventToSegs(event); 11223 11224 var rowStructs; 11225 11226 11227 11228 segs = this.renderFgSegEls(segs); // assigns each seg's el and returns a subset of segs that were rendered 11229 11230 rowStructs = this.renderSegRows(segs); 11231 11232 11233 11234 // inject each new event skeleton into each associated row 11235 11236 this.rowEls.each(function(row, rowNode) { 11237 11238 var rowEl = $(rowNode); // the .fc-row 11239 11240 var skeletonEl = $('<div class="fc-helper-skeleton"><table/></div>'); // will be absolutely positioned 11241 11242 var skeletonTop; 11243 11244 11245 11246 // If there is an original segment, match the top position. Otherwise, put it at the row's top level 11247 11248 if (sourceSeg && sourceSeg.row === row) { 11249 11250 skeletonTop = sourceSeg.el.position().top; 11251 11252 } 11253 11254 else { 11255 11256 skeletonTop = rowEl.find('.fc-content-skeleton tbody').position().top; 11257 11258 } 11259 11260 11261 11262 skeletonEl.css('top', skeletonTop) 11263 11264 .find('table') 11265 11266 .append(rowStructs[row].tbodyEl); 11267 11268 11269 11270 rowEl.append(skeletonEl); 11271 11272 helperNodes.push(skeletonEl[0]); 11273 11274 }); 11275 11276 11277 11278 this.helperEls = $(helperNodes); // array -> jQuery set 11279 11280 }, 11281 11282 11283 11284 11285 11286 // Unrenders any visual indication of a mock helper event 11287 11288 unrenderHelper: function() { 11289 11290 if (this.helperEls) { 11291 11292 this.helperEls.remove(); 11293 11294 this.helperEls = null; 11295 11296 } 11297 11298 }, 11299 11300 11301 11302 11303 11304 /* Fill System (highlight, background events, business hours) 11305 11306 ------------------------------------------------------------------------------------------------------------------*/ 11307 11308 11309 11310 11311 11312 fillSegTag: 'td', // override the default tag name 11313 11314 11315 11316 11317 11318 // Renders a set of rectangles over the given segments of days. 11319 11320 // Only returns segments that successfully rendered. 11321 11322 renderFill: function(type, segs, className) { 11323 11324 var nodes = []; 11325 11326 var i, seg; 11327 11328 var skeletonEl; 11329 11330 11331 11332 segs = this.renderFillSegEls(type, segs); // assignes `.el` to each seg. returns successfully rendered segs 11333 11334 11335 11336 for (i = 0; i < segs.length; i++) { 11337 11338 seg = segs[i]; 11339 11340 skeletonEl = this.renderFillRow(type, seg, className); 11341 11342 this.rowEls.eq(seg.row).append(skeletonEl); 11343 11344 nodes.push(skeletonEl[0]); 11345 11346 } 11347 11348 11349 11350 this.elsByFill[type] = $(nodes); 11351 11352 11353 11354 return segs; 11355 11356 }, 11357 11358 11359 11360 11361 11362 // Generates the HTML needed for one row of a fill. Requires the seg's el to be rendered. 11363 11364 renderFillRow: function(type, seg, className) { 11365 11366 var colCnt = this.colCnt; 11367 11368 var startCol = seg.leftCol; 11369 11370 var endCol = seg.rightCol + 1; 11371 11372 var skeletonEl; 11373 11374 var trEl; 11375 11376 11377 11378 className = className || type.toLowerCase(); 11379 11380 11381 11382 skeletonEl = $( 11383
11384 '<div class="fc-' + className + '-skeleton">' + 11385 11386 '<table><tr/></table>' + 11387 11388 '</div>' 11389 11390 ); 11391 11392 trEl = skeletonEl.find('tr'); 11393 11394 11395 11396 if (startCol > 0) { 11397 11398 trEl.append('<td colspan="' + startCol + '"/>'); 11399 11400 } 11401 11402 11403 11404 trEl.append( 11405 11406 seg.el.attr('colspan', endCol - startCol) 11407 11408 ); 11409 11410 11411 11412 if (endCol < colCnt) { 11413 11414 trEl.append('<td colspan="' + (colCnt - endCol) + '"/>'); 11415 11416 } 11417 11418 11419 11420 this.bookendCells(trEl); 11421 11422 11423 11424 return skeletonEl; 11425 11426 } 11427 11428 11429 11430 }); 11431 11432 11433 11434 ;; 11435 11436 11437 11438 /* Event-rendering methods for the DayGrid class 11439 11440 ----------------------------------------------------------------------------------------------------------------------*/ 11441 11442 11443 11444 DayGrid.mixin({ 11445 11446 11447 11448 rowStructs: null, // an array of objects, each holding information about a row's foreground event-rendering 11449 11450 11451 11452 11453 11454 // Unrenders all events currently rendered on the grid 11455 11456 unrenderEvents: function() { 11457 11458 this.removeSegPopover(); // removes the "more.." events popover 11459 11460 Grid.prototype.unrenderEvents.apply(this, arguments); // calls the super-method 11461 11462 }, 11463 11464 11465 11466 11467 11468 // Retrieves all rendered segment objects currently rendered on the grid 11469 11470 getEventSegs: function() { 11471 11472 return Grid.prototype.getEventSegs.call(this) // get the segments from the super-method 11473 11474 .concat(this.popoverSegs || []); // append the segments from the "more..." popover 11475 11476 }, 11477 11478 11479 11480 11481 11482 // Renders the given background event segments onto the grid 11483 11484 renderBgSegs: function(segs) { 11485 11486 11487 11488 // don't render timed background events 11489 11490 var allDaySegs = $.grep(segs, function(seg) { 11491 11492 return seg.event.allDay; 11493 11494 }); 11495 11496 11497 11498 return Grid.prototype.renderBgSegs.call(this, allDaySegs); // call the super-method 11499 11500 }, 11501 11502 11503 11504 11505 11506 // Renders the given foreground event segments onto the grid 11507 11508 renderFgSegs: function(segs) { 11509 11510 var rowStructs; 11511 11512 11513 11514 // render an `.el` on each seg 11515 11516 // returns a subset of the segs. segs that were actually rendered 11517 11518 segs = this.renderFgSegEls(segs); 11519 11520 11521 11522 rowStructs = this.rowStructs = this.renderSegRows(segs); 11523 11524 11525 11526 // append to each row's content skeleton 11527 11528 this.rowEls.each(function(i, rowNode) { 11529 11530 $(rowNode).find('.fc-content-skeleton > table').append( 11531 11532 rowStructs[i].tbodyEl 11533 11534 ); 11535 11536 }); 11537 11538 11539 11540 return segs; // return only the segs that were actually rendered 11541 11542 }, 11543 11544 11545 11546 11547 11548 // Unrenders all currently rendered foreground event segments 11549 11550 unrenderFgSegs: function() { 11551 11552 var rowStructs = this.rowStructs || []; 11553 11554 var rowStruct; 11555 11556 11557 11558 while ((rowStruct = rowStructs.pop())) { 11559 11560 rowStruct.tbodyEl.remove(); 11561 11562 } 11563 11564 11565 11566 this.rowStructs = null; 11567 11568 }, 11569 11570 11571 11572 11573 11574 // Uses the given events array to generate <tbody> elements that should be appended to each row's content skeleton. 11575 11576 // Returns an array of rowStruct objects (see the bottom of `renderSegRow`). 11577 11578 // PRECONDITION: each segment shoud already have a rendered and assigned `.el` 11579 11580 renderSegRows: function(segs) { 11581 11582 var rowStructs = []; 11583 11584 var segRows; 11585 11586 var row; 11587 11588 11589 11590 segRows = this.groupSegRows(segs); // group into nested arrays 11591 11592 11593 11594 // iterate each row of segment groupings 11595 11596 for (row = 0; row < segRows.length; row++) { 11597 11598 rowStructs.push( 11599 11600 this.renderSegRow(row, segRows[row]) 11601 11602 ); 11603 11604 } 11605 11606 11607 11608 return rowStructs; 11609 11610 }, 11611 11612 11613 11614 11615 11616 // Builds the HTML to be used for the default element for an individual segment 11617 11618 fgSegHtml: function(seg, disableResizing) { 11619 11620 var view = this.view; 11621 11622 var event = seg.event; 11623 11624 var isDraggable = view.isEventDraggable(event); 11625 11626 var isResizableFromStart = !disableResizing && event.allDay && 11627 11628 seg.isStart && view.isEventResizableFromStart(event); 11629 11630 var isResizableFromEnd = !disableResizing && event.allDay && 11631 11632 seg.isEnd && view.isEventResizableFromEnd(event); 11633 11634 var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd); 11635 11636 var skinCss = cssToStr(this.getEventSkinCss(event)); 11637 11638 var timeHtml = ''; 11639 11640 var timeText; 11641 11642 var titleHtml; 11643 11644 11645 11646 classes.unshift('fc-day-grid-event', 'fc-h-event'); 11647 11648 11649
11650 // Only display a timed events time if it is the starting segment 11651 11652 if (seg.isStart) { 11653 11654 timeText = this.getEventTimeText(event); 11655 11656 if (timeText) { 11657 11658 timeHtml = '<span class="fc-time">' + htmlEscape(timeText) + '</span>'; 11659 11660 } 11661 11662 } 11663 11664 11665 11666 titleHtml = 11667 11668 '<span class="fc-title" id="'+event.id+'">' + 11669 11670 (htmlEscape(event.title || '') || ' ') + // we always want one line of height 11671 11672 '</span>'; 11673 11674 11675 11676 return '<a class="' + classes.join(' ') + '"' + 11677 11678 (event.url ? 11679 11680 ' href="' + htmlEscape(event.url) + '"' : 11681 11682 '' 11683 11684 ) + 11685 11686 (skinCss ? 11687 11688 ' style="' + skinCss + '"' : 11689 11690 '' 11691 11692 ) + 11693 11694 '>' + 11695 11696 '<div class="fc-content">' + 11697 11698 (this.isRTL ? 11699 11700 titleHtml + ' ' + timeHtml : // put a natural space in between 11701 11702 timeHtml + ' ' + titleHtml // 11703 11704 ) + 11705 11706 '</div>' + 11707 11708 (isResizableFromStart ? 11709 11710 '<div class="fc-resizer fc-start-resizer" />' : 11711 11712 '' 11713 11714 ) + 11715 11716 (isResizableFromEnd ? 11717 11718 '<div class="fc-resizer fc-end-resizer" />' : 11719 11720 '' 11721 11722 ) + 11723 11724 '</a>'; 11725 11726 }, 11727 11728 11729 11730 11731 11732 // Given a row # and an array of segments all in the same row, render a <tbody> element, a skeleton that contains 11733 11734 // the segments. Returns object with a bunch of internal data about how the render was calculated. 11735 11736 // NOTE: modifies rowSegs 11737 11738 renderSegRow: function(row, rowSegs) { 11739 11740 var colCnt = this.colCnt; 11741 11742 var segLevels = this.buildSegLevels(rowSegs); // group into sub-arrays of levels 11743 11744 var levelCnt = Math.max(1, segLevels.length); // ensure at least one level 11745 11746 var tbody = $('<tbody/>'); 11747 11748 var segMatrix = []; // lookup for which segments are rendered into which level+col cells 11749 11750 var cellMatrix = []; // lookup for all <td> elements of the level+col matrix 11751 11752 var loneCellMatrix = []; // lookup for <td> elements that only take up a single column 11753 11754 var i, levelSegs; 11755 11756 var col; 11757 11758 var tr; 11759 11760 var j, seg; 11761 11762 var td; 11763 11764 11765 11766 // populates empty cells from the current column (`col`) to `endCol` 11767 11768 function emptyCellsUntil(endCol) { 11769 11770 while (col < endCol) { 11771 11772 // try to grab a cell from the level above and extend its rowspan. otherwise, create a fresh cell 11773 11774 td = (loneCellMatrix[i - 1] || [])[col]; 11775 11776 if (td) { 11777 11778 td.attr( 11779 11780 'rowspan', 11781 11782 parseInt(td.attr('rowspan') || 1, 10) + 1 11783 11784 ); 11785 11786 } 11787 11788 else { 11789 11790 td = $('<td/>'); 11791 11792 tr.append(td); 11793 11794 } 11795 11796 cellMatrix[i][col] = td; 11797 11798 loneCellMatrix[i][col] = td; 11799 11800 col++; 11801 11802 } 11803 11804 } 11805 11806 11807 11808 for (i = 0; i < levelCnt; i++) { // iterate through all levels 11809 11810 levelSegs = segLevels[i]; 11811 11812 col = 0; 11813 11814 tr = $('<tr/>'); 11815 11816 11817 11818 segMatrix.push([]); 11819 11820 cellMatrix.push([]); 11821 11822 loneCellMatrix.push([]); 11823 11824 11825 11826 // levelCnt might be 1 even though there are no actual levels. protect against this. 11827 11828 // this single empty row is useful for styling. 11829 11830 if (levelSegs) { 11831 11832 for (j = 0; j < levelSegs.length; j++) { // iterate through segments in level 11833 11834 seg = levelSegs[j]; 11835 11836 11837 11838 emptyCellsUntil(seg.leftCol); 11839 11840 11841 11842 // create a container that occupies or more columns. append the event element. 11843 11844 td = $('<td class="fc-event-container"/>').append(seg.el); 11845 11846 if (seg.leftCol != seg.rightCol) { 11847 11848 td.attr('colspan', seg.rightCol - seg.leftCol + 1); 11849 11850 } 11851 11852 else { // a single-column segment 11853 11854 loneCellMatrix[i][col] = td; 11855 11856 } 11857 11858 11859 11860 while (col <= seg.rightCol) { 11861 11862 cellMatrix[i][col] = td; 11863 11864 segMatrix[i][col] = seg; 11865 11866 col++; 11867 11868 } 11869 11870 11871 11872 tr.append(td); 11873 11874 } 11875 11876 } 11877 11878 11879 11880 emptyCellsUntil(colCnt); // finish off the row 11881 11882 this.bookendCells(tr); 11883 11884 tbody.append(tr); 11885 11886 } 11887 11888 11889 11890 return { // a "rowStruct" 11891 11892 row: row, // the row number 11893 11894 tbodyEl: tbody, 11895 11896 cellMatrix: cellMatrix, 11897 11898 segMatrix: segMatrix, 11899 11900 segLevels: segLevels, 11901 11902 segs: rowSegs 11903 11904 }; 11905 11906 }, 11907 11908 11909 11910 11911 11912 // Stacks a flat array of segments, which are all assumed to be in the same row, into subarrays of vertical levels. 11913 11914 // NOTE: modifies segs 11915 11916 buildSegLevels: function(segs) { 11917 11918 var levels = []; 11919 11920 var i, seg; 11921 11922 var j; 11923 11924 11925 11926 // Give preference to elements with certain criteria, so they have 11927 11928 // a chance to be closer to the top. 11929 11930 this.sortEventSegs(segs); 11931 11932 11933 11934 for (i = 0; i < segs.length; i++) { 11935 11936 seg = segs[i]; 11937 11938 11939 11940 // loop through levels, starting with the topmost, until the segment doesn't collide with other segments 11941 11942 for (j = 0; j < levels.length; j++) { 11943
11944 if (!isDaySegCollision(seg, levels[j])) { 11945 11946 break; 11947 11948 } 11949 11950 } 11951 11952 // `j` now holds the desired subrow index 11953 11954 seg.level = j; 11955 11956 11957 11958 // create new level array if needed and append segment 11959 11960 (levels[j] || (levels[j] = [])).push(seg); 11961 11962 } 11963 11964 11965 11966 // order segments left-to-right. very important if calendar is RTL 11967 11968 for (j = 0; j < levels.length; j++) { 11969 11970 levels[j].sort(compareDaySegCols); 11971 11972 } 11973 11974 11975 11976 return levels; 11977 11978 }, 11979 11980 11981 11982 11983 11984 // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's row 11985 11986 groupSegRows: function(segs) { 11987 11988 var segRows = []; 11989 11990 var i; 11991 11992 11993 11994 for (i = 0; i < this.rowCnt; i++) { 11995 11996 segRows.push([]); 11997 11998 } 11999 12000 12001 12002 for (i = 0; i < segs.length; i++) { 12003 12004 segRows[segs[i].row].push(segs[i]); 12005 12006 } 12007 12008 12009 12010 return segRows; 12011 12012 } 12013 12014 12015 12016 }); 12017 12018 12019 12020 12021 12022// Computes whether two segments' columns collide. They are assumed to be in the same row. 12023 12024 function isDaySegCollision(seg, otherSegs) { 12025 12026 var i, otherSeg; 12027 12028 12029 12030 for (i = 0; i < otherSegs.length; i++) { 12031 12032 otherSeg = otherSegs[i]; 12033 12034 12035 12036 if ( 12037 12038 otherSeg.leftCol <= seg.rightCol && 12039 12040 otherSeg.rightCol >= seg.leftCol 12041 12042 ) { 12043 12044 return true; 12045 12046 } 12047 12048 } 12049 12050 12051 12052 return false; 12053 12054 } 12055 12056 12057 12058 12059 12060// A cmp function for determining the leftmost event 12061 12062 function compareDaySegCols(a, b) { 12063 12064 return a.leftCol - b.leftCol; 12065 12066 } 12067 12068 12069 12070 ;; 12071 12072 12073 12074 /* Methods relate to limiting the number events for a given day on a DayGrid 12075 12076 ----------------------------------------------------------------------------------------------------------------------*/ 12077 12078// NOTE: all the segs being passed around in here are foreground segs 12079 12080 12081 12082 DayGrid.mixin({ 12083 12084 12085 12086 segPopover: null, // the Popover that holds events that can't fit in a cell. null when not visible 12087 12088 popoverSegs: null, // an array of segment objects that the segPopover holds. null when not visible 12089 12090 12091 12092 12093 12094 removeSegPopover: function() { 12095 12096 if (this.segPopover) { 12097 12098 this.segPopover.hide(); // in handler, will call segPopover's removeElement 12099 12100 } 12101 12102 }, 12103 12104 12105 12106 12107 12108 // Limits the number of "levels" (vertically stacking layers of events) for each row of the grid. 12109 12110 // `levelLimit` can be false (don't limit), a number, or true (should be computed). 12111 12112 limitRows: function(levelLimit) { 12113 12114 var rowStructs = this.rowStructs || []; 12115 12116 var row; // row # 12117 12118 var rowLevelLimit; 12119 12120 12121 12122 for (row = 0; row < rowStructs.length; row++) { 12123 12124 this.unlimitRow(row); 12125 12126 12127 12128 if (!levelLimit) { 12129 12130 rowLevelLimit = false; 12131 12132 } 12133 12134 else if (typeof levelLimit === 'number') { 12135 12136 rowLevelLimit = levelLimit; 12137 12138 } 12139 12140 else { 12141 12142 rowLevelLimit = this.computeRowLevelLimit(row); 12143 12144 } 12145 12146 12147 12148 if (rowLevelLimit !== false) { 12149 12150 this.limitRow(row, rowLevelLimit); 12151 12152 } 12153 12154 } 12155 12156 }, 12157 12158 12159 12160 12161 12162 // Computes the number of levels a row will accomodate without going outside its bounds. 12163 12164 // Assumes the row is "rigid" (maintains a constant height regardless of what is inside). 12165 12166 // `row` is the row number. 12167 12168 computeRowLevelLimit: function(row) { 12169 12170 var rowEl = this.rowEls.eq(row); // the containing "fake" row div 12171 12172 var rowHeight = rowEl.height(); // TODO: cache somehow? 12173 12174 var trEls = this.rowStructs[row].tbodyEl.children(); 12175 12176 var i, trEl; 12177 12178 var trHeight; 12179 12180 12181 12182 function iterInnerHeights(i, childNode) { 12183 12184 trHeight = Math.max(trHeight, $(childNode).outerHeight()); 12185 12186 } 12187 12188 12189 12190 // Reveal one level <tr> at a time and stop when we find one out of bounds 12191 12192 for (i = 0; i < trEls.length; i++) { 12193 12194 trEl = trEls.eq(i).removeClass('fc-limited'); // reset to original state (reveal) 12195 12196 12197 12198 // with rowspans>1 and IE8, trEl.outerHeight() would return the height of the largest cell, 12199 12200 // so instead, find the tallest inner content element. 12201 12202 trHeight = 0; 12203 12204 trEl.find('> td > :first-child').each(iterInnerHeights); 12205 12206 12207 12208 if (trEl.position().top + trHeight > rowHeight) { 12209 12210 return i; 12211 12212 } 12213 12214 } 12215 12216 12217 12218 return false; // should not limit at all 12219 12220 }, 12221 12222 12223 12224 12225 12226 // Limits the given grid row to the maximum number of levels and injects "more" links if necessary. 12227 12228 // `row` is the row number. 12229 12230 // `levelLimit` is a number for the maximum (inclusive) number of levels allowed. 12231 12232 limitRow: function(row, levelLimit) { 12233 12234 var _this = this; 12235 12236 var rowStruct = this.rowStructs[row]; 12237 12238 var moreNodes = []; // array of "more" <a> links and <td> DOM nodes 12239 12240 var col = 0; // col #, left-to-right (not chronologically) 12241 12242 var levelSegs; // array of segment objects in the last allowable level, ordered left-to-right 12243 12244 var cellMatrix; // a matrix (by level, then column) of all <td> jQuery elements in the row 12245 12246 var limitedNodes; // array of temporarily hidden level <tr> and segment <td> DOM nodes 12247 12248 var i, seg; 12249 12250 var segsBelow; // array of segment objects below `seg` in the current `col` 12251 12252 var totalSegsBelow; // total number of segments below `seg` in any of the columns `seg` occupies 12253 12254 var colSegsBelow; // array of segment arrays, below seg, one for each column (offset from segs's first column) 12255 12256 var td, rowspan; 12257 12258 var segMoreNodes; // array of "more" <td> cells that will stand-in for the current seg's cell 12259 12260 var j; 12261 12262 var moreTd, moreWrap, moreLink; 12263 12264 12265 12266 // Iterates through empty level cells and places "more" links inside if need be 12267 12268 function emptyCellsUntil(endCol) { // goes from current `col` to `endCol` 12269 12270 while (col < endCol) { 12271 12272 segsBelow = _this.getCellSegs(row, col, levelLimit); 12273 12274 if (segsBelow.length) { 12275 12276 td = cellMatrix[levelLimit - 1][col]; 12277 12278 moreLink = _this.renderMoreLink(row, col, segsBelow); 12279 12280 moreWrap = $('<div/>').append(moreLink); 12281 12282 td.append(moreWrap); 12283 12284 moreNodes.push(moreWrap[0]); 12285 12286 } 12287 12288 col++; 12289 12290 } 12291 12292 } 12293 12294 12295 12296 if (levelLimit && levelLimit < rowStruct.segLevels.length) { // is it actually over the limit? 12297 12298 levelSegs = rowStruct.segLevels[levelLimit - 1]; 12299 12300 cellMatrix = rowStruct.cellMatrix; 12301 12302 12303 12304 limitedNodes = rowStruct.tbodyEl.children().slice(levelLimit) // get level <tr> elements past the limit 12305 12306 .addClass('fc-limited').get(); // hide elements and get a simple DOM-nodes array 12307 12308 12309 12310 // iterate though segments in the last allowable level 12311 12312 for (i = 0; i < levelSegs.length; i++) { 12313 12314 seg = levelSegs[i]; 12315 12316 emptyCellsUntil(seg.leftCol); // process empty cells before the segment 12317 12318 12319 12320 // determine *all* segments below `seg` that occupy the same columns 12321 12322 colSegsBelow = []; 12323 12324 totalSegsBelow = 0; 12325 12326 while (col <= seg.rightCol) { 12327 12328 segsBelow = this.getCellSegs(row, col, levelLimit); 12329 12330 colSegsBelow.push(segsBelow); 12331 12332 totalSegsBelow += segsBelow.length; 12333 12334 col++; 12335 12336 } 12337 12338 12339 12340 if (totalSegsBelow) { // do we need to replace this segment with one or many "more" links? 12341 12342 td = cellMatrix[levelLimit - 1][seg.leftCol]; // the segment's parent cell 12343 12344 rowspan = td.attr('rowspan') || 1; 12345 12346 segMoreNodes = []; 12347 12348 12349 12350 // make a replacement <td> for each column the segment occupies. will be one for each colspan 12351 12352 for (j = 0; j < colSegsBelow.length; j++) { 12353 12354 moreTd = $('<td class="fc-more-cell"/>').attr('rowspan', rowspan); 12355 12356 segsBelow = colSegsBelow[j]; 12357 12358 moreLink = this.renderMoreLink( 12359 12360 row, 12361 12362 seg.leftCol + j, 12363 12364 [ seg ].concat(segsBelow) // count seg as hidden too 12365 12366 ); 12367 12368 moreWrap = $('<div/>').append(moreLink); 12369 12370 moreTd.append(moreWrap); 12371 12372 segMoreNodes.push(moreTd[0]); 12373 12374 moreNodes.push(moreTd[0]); 12375 12376 } 12377 12378 12379 12380 td.addClass('fc-limited').after($(segMoreNodes)); // hide original <td> and inject replacements 12381 12382 limitedNodes.push(td[0]); 12383 12384 } 12385 12386 } 12387 12388 12389 12390 emptyCellsUntil(this.colCnt); // finish off the level 12391 12392 rowStruct.moreEls = $(moreNodes); // for easy undoing later 12393 12394 rowStruct.limitedEls = $(limitedNodes); // for easy undoing later 12395 12396 } 12397 12398 }, 12399 12400 12401 12402 12403 12404 // Reveals all levels and removes all "more"-related elements for a grid's row. 12405 12406 // `row` is a row number. 12407 12408 unlimitRow: function(row) { 12409 12410 var rowStruct = this.rowStructs[row]; 12411 12412 12413 12414 if (rowStruct.moreEls) { 12415 12416 rowStruct.moreEls.remove(); 12417 12418 rowStruct.moreEls = null; 12419 12420 } 12421 12422 12423 12424 if (rowStruct.limitedEls) { 12425 12426 rowStruct.limitedEls.removeClass('fc-limited'); 12427 12428 rowStruct.limitedEls = null; 12429 12430 } 12431 12432 }, 12433 12434 12435 12436 12437 12438 // Renders an <a> element that represents hidden event element for a cell. 12439 12440 // Responsible for attaching click handler as well. 12441 12442 renderMoreLink: function(row, col, hiddenSegs) { 12443 12444 var _this = this; 12445 12446 var view = this.view; 12447 12448 12449 12450 return $('<a class="fc-more"/>') 12451 12452 .text( 12453 12454 this.getMoreLinkText(hiddenSegs.length) 12455 12456 ) 12457 12458 .on('click', function(ev) { 12459 12460 var clickOption = view.opt('eventLimitClick'); 12461 12462 var date = _this.getCellDate(row, col); 12463 12464 var moreEl = $(this); 12465 12466 var dayEl = _this.getCellEl(row, col); 12467 12468 var allSegs = _this.getCellSegs(row, col); 12469 12470 12471 12472 // rescope the segments to be within the cell's date 12473
12474 var reslicedAllSegs = _this.resliceDaySegs(allSegs, date); 12475 12476 var reslicedHiddenSegs = _this.resliceDaySegs(hiddenSegs, date); 12477 12478 12479 12480 if (typeof clickOption === 'function') { 12481 12482 // the returned value can be an atomic option 12483 12484 clickOption = view.trigger('eventLimitClick', null, { 12485 12486 date: date, 12487 12488 dayEl: dayEl, 12489 12490 moreEl: moreEl, 12491 12492 segs: reslicedAllSegs, 12493 12494 hiddenSegs: reslicedHiddenSegs 12495 12496 }, ev); 12497 12498 } 12499 12500 12501 12502 if (clickOption === 'popover') { 12503 12504 _this.showSegPopover(row, col, moreEl, reslicedAllSegs); 12505 12506 } 12507 12508 else if (typeof clickOption === 'string') { // a view name 12509 12510 view.calendar.zoomTo(date, clickOption); 12511 12512 } 12513 12514 }); 12515 12516 }, 12517 12518 12519 12520 12521 12522 // Reveals the popover that displays all events within a cell 12523 12524 showSegPopover: function(row, col, moreLink, segs) { 12525 12526 var _this = this; 12527 12528 var view = this.view; 12529 12530 var moreWrap = moreLink.parent(); // the <div> wrapper around the <a> 12531 12532 var topEl; // the element we want to match the top coordinate of 12533 12534 var options; 12535 12536 12537 12538 if (this.rowCnt == 1) { 12539 12540 topEl = view.el; // will cause the popover to cover any sort of header 12541 12542 } 12543 12544 else { 12545 12546 topEl = this.rowEls.eq(row); // will align with top of row 12547 12548 } 12549 12550 12551 12552 options = { 12553 12554 className: 'fc-more-popover', 12555 12556 content: this.renderSegPopoverContent(row, col, segs), 12557 12558 parentEl: this.el, 12559 12560 top: topEl.offset().top, 12561 12562 autoHide: true, // when the user clicks elsewhere, hide the popover 12563 12564 viewportConstrain: view.opt('popoverViewportConstrain'), 12565 12566 hide: function() { 12567 12568 // kill everything when the popover is hidden 12569 12570 _this.segPopover.removeElement(); 12571 12572 _this.segPopover = null; 12573 12574 _this.popoverSegs = null; 12575 12576 } 12577 12578 }; 12579 12580 12581 12582 // Determine horizontal coordinate. 12583 12584 // We use the moreWrap instead of the <td> to avoid border confusion. 12585 12586 if (this.isRTL) { 12587 12588 options.right = moreWrap.offset().left + moreWrap.outerWidth() + 1; // +1 to be over cell border 12589 12590 } 12591 12592 else { 12593 12594 options.left = moreWrap.offset().left - 1; // -1 to be over cell border 12595 12596 } 12597 12598 12599 12600 this.segPopover = new Popover(options); 12601 12602 this.segPopover.show(); 12603 12604 }, 12605 12606 12607 12608 12609 12610 // Builds the inner DOM contents of the segment popover 12611 12612 renderSegPopoverContent: function(row, col, segs) { 12613 12614 var view = this.view; 12615 12616 var isTheme = view.opt('theme'); 12617 12618 var title = this.getCellDate(row, col).format(view.opt('dayPopoverFormat')); 12619 12620 var content = $( 12621 12622 '<div class="fc-header ' + view.widgetHeaderClass + '">' + 12623 12624 '<span class="fc-close ' + 12625 12626 (isTheme ? 'ui-icon ui-icon-closethick' : 'fc-icon fc-icon-x') + 12627 12628 '"></span>' + 12629 12630 '<span class="fc-title">' + 12631 12632 htmlEscape(title) + 12633 12634 '</span>' + 12635 12636 '<div class="fc-clear"/>' + 12637 12638 '</div>' + 12639 12640 '<div class="fc-body ' + view.widgetContentClass + '">' + 12641 12642 '<div class="fc-event-container"></div>' + 12643 12644 '</div>' 12645 12646 ); 12647 12648 var segContainer = content.find('.fc-event-container'); 12649 12650 var i; 12651 12652 12653 12654 // render each seg's `el` and only return the visible segs 12655 12656 segs = this.renderFgSegEls(segs, true); // disableResizing=true 12657 12658 this.popoverSegs = segs; 12659 12660 12661 12662 for (i = 0; i < segs.length; i++) { 12663 12664 12665 12666 // because segments in the popover are not part of a grid coordinate system, provide a hint to any 12667 12668 // grids that want to do drag-n-drop about which cell it came from 12669 12670 this.prepareHits(); 12671 12672 segs[i].hit = this.getCellHit(row, col); 12673 12674 this.releaseHits(); 12675 12676 12677 12678 segContainer.append(segs[i].el); 12679 12680 } 12681 12682 12683 12684 return content; 12685 12686 }, 12687 12688 12689 12690 12691 12692 // Given the events within an array of segment objects, reslice them to be in a single day 12693 12694 resliceDaySegs: function(segs, dayDate) { 12695 12696 12697 12698 // build an array of the original events 12699 12700 var events = $.map(segs, function(seg) { 12701 12702 return seg.event; 12703 12704 }); 12705 12706 12707 12708 var dayStart = dayDate.clone(); 12709 12710 var dayEnd = dayStart.clone().add(1, 'days'); 12711 12712 var dayRange = { start: dayStart, end: dayEnd }; 12713 12714 12715 12716 // slice the events with a custom slicing function 12717 12718 segs = this.eventsToSegs( 12719 12720 events, 12721 12722 function(range) { 12723 12724 var seg = intersectRanges(range, dayRange); // undefind if no intersection 12725 12726 return seg ? [ seg ] : []; // must return an array of segments 12727 12728 } 12729 12730 ); 12731 12732 12733 12734 // force an order because eventsToSegs doesn't guarantee one 12735 12736 this.sortEventSegs(segs); 12737 12738 12739 12740 return segs; 12741 12742 }, 12743 12744 12745 12746 12747 12748 // Generates the text that should be inside a "more" link, given the number of events it represents 12749 12750 getMoreLinkText: function(num) { 12751 12752 var opt = this.view.opt('eventLimitText'); 12753 12754 12755 12756 if (typeof opt === 'function') { 12757 12758 return opt(num); 12759 12760 } 12761 12762 else { 12763 12764 return '+' + num + ' ' + opt; 12765 12766 } 12767 12768 }, 12769 12770 12771 12772 12773 12774 // Returns segments within a given cell. 12775 12776 // If `startLevel` is specified, returns only events including and below that level. Otherwise returns all segs. 12777 12778 getCellSegs: function(row, col, startLevel) { 12779 12780 var segMatrix = this.rowStructs[row].segMatrix; 12781 12782 var level = startLevel || 0; 12783 12784 var segs = []; 12785 12786 var seg; 12787 12788 12789 12790 while (level < segMatrix.length) { 12791 12792 seg = segMatrix[level][col]; 12793 12794 if (seg) { 12795 12796 segs.push(seg); 12797 12798 } 12799 12800 level++; 12801 12802 } 12803 12804 12805 12806 return segs; 12807 12808 } 12809 12810 12811 12812 }); 12813 12814 12815 12816 ;; 12817 12818 12819 12820 /* A component that renders one or more columns of vertical time slots 12821 12822 ----------------------------------------------------------------------------------------------------------------------*/ 12823 12824// We mixin DayTable, even though there is only a single row of days 12825 12826 12827 12828 var TimeGrid = FC.TimeGrid = Grid.extend(DayTableMixin, { 12829 12830 12831 12832 slotDuration: null, // duration of a "slot", a distinct time segment on given day, visualized by lines 12833 12834 snapDuration: null, // granularity of time for dragging and selecting 12835 12836 snapsPerSlot: null, 12837 12838 minTime: null, // Duration object that denotes the first visible time of any given day 12839 12840 maxTime: null, // Duration object that denotes the exclusive visible end time of any given day 12841 12842 labelFormat: null, // formatting string for times running along vertical axis 12843 12844 labelInterval: null, // duration of how often a label should be displayed for a slot 12845 12846 12847 12848 colEls: null, // cells elements in the day-row background 12849 12850 slatEls: null, // elements running horizontally across all columns 12851 12852 helperEl: null, // cell skeleton element for rendering the mock event "helper" 12853 12854 12855 12856 colCoordCache: null, 12857 12858 slatCoordCache: null, 12859 12860 12861 12862 businessHourSegs: null, 12863 12864 12865 12866 12867 12868 constructor: function() { 12869 12870 Grid.apply(this, arguments); // call the super-constructor 12871 12872 12873 12874 this.processOptions(); 12875 12876 }, 12877 12878 12879 12880 12881 12882 // Renders the time grid into `this.el`, which should already be assigned. 12883 12884 // Relies on the view's colCnt. In the future, this component should probably be self-sufficient. 12885 12886 renderDates: function() { 12887 12888 this.el.html(this.renderHtml()); 12889 12890 this.colEls = this.el.find('.fc-day'); 12891 12892 this.slatEls = this.el.find('.fc-slats tr'); 12893 12894 12895 12896 this.colCoordCache = new CoordCache({ 12897 12898 els: this.colEls, 12899 12900 isHorizontal: true 12901 12902 }); 12903
12904 this.slatCoordCache = new CoordCache({ 12905 12906 els: this.slatEls, 12907 12908 isVertical: true 12909 12910 }); 12911 12912 }, 12913 12914 12915 12916 12917 12918 renderBusinessHours: function() { 12919 12920 var events = this.view.calendar.getBusinessHoursEvents(); 12921 12922 this.businessHourSegs = this.renderFill('businessHours', this.eventsToSegs(events), 'bgevent'); 12923 12924 }, 12925 12926 12927 12928 12929 12930 // Renders the basic HTML skeleton for the grid 12931 12932 renderHtml: function() { 12933 12934 return '' + 12935 12936 '<div class="fc-bg">' + 12937 12938 '<table>' + 12939 12940 this.renderBgTrHtml(0) + // row=0 12941 12942 '</table>' + 12943 12944 '</div>' + 12945 12946 '<div class="fc-slats">' + 12947 12948 '<table>' + 12949 12950 this.renderSlatRowHtml() + 12951 12952 '</table>' + 12953 12954 '</div>'; 12955 12956 }, 12957 12958 12959 12960 12961 12962 // Generates the HTML for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL. 12963 12964 renderSlatRowHtml: function() { 12965 12966 var view = this.view; 12967 12968 var isRTL = this.isRTL; 12969 12970 var html = ''; 12971 12972 var slotTime = moment.duration(+this.minTime); // wish there was .clone() for durations 12973 12974 var slotDate; // will be on the view's first day, but we only care about its time 12975 12976 var isLabeled; 12977 12978 var axisHtml; 12979 12980 12981 12982 // Calculate the time for each slot 12983 12984 while (slotTime < this.maxTime) { 12985 12986 slotDate = this.start.clone().time(slotTime); 12987 12988 isLabeled = isInt(divideDurationByDuration(slotTime, this.labelInterval)); 12989 12990 12991 12992 axisHtml = 12993 12994 '<td class="fc-axis fc-time ' + view.widgetContentClass + '" ' + view.axisStyleAttr() + '>' + 12995 12996 (isLabeled ? 12997 12998 '<span>' + // for matchCellWidths 12999 13000 htmlEscape(slotDate.format(this.labelFormat)) + 13001 13002 '</span>' : 13003 13004 '' 13005 13006 ) + 13007 13008 '</td>'; 13009 13010 13011 13012 html += 13013 13014 '<tr ' + (isLabeled ? '' : 'class="fc-minor"') + '>' + 13015 13016 (!isRTL ? axisHtml : '') + 13017 13018 '<td class="' + view.widgetContentClass + '"/>' + 13019 13020 (isRTL ? axisHtml : '') + 13021 13022 "</tr>"; 13023 13024 13025 13026 slotTime.add(this.slotDuration); 13027 13028 } 13029 13030 13031 13032 return html; 13033 13034 }, 13035 13036 13037 13038 13039 13040 /* Options 13041 13042 ------------------------------------------------------------------------------------------------------------------*/ 13043 13044 13045 13046 13047 13048 // Parses various options into properties of this object 13049 13050 processOptions: function() { 13051 13052 var view = this.view; 13053 13054 var slotDuration = view.opt('slotDuration'); 13055 13056 var snapDuration = view.opt('snapDuration'); 13057 13058 var input; 13059 13060 13061 13062 slotDuration = moment.duration(slotDuration); 13063 13064 snapDuration = snapDuration ? moment.duration(snapDuration) : slotDuration; 13065 13066 13067 13068 this.slotDuration = slotDuration; 13069 13070 this.snapDuration = snapDuration; 13071 13072 this.snapsPerSlot = slotDuration / snapDuration; // TODO: ensure an integer multiple? 13073 13074 13075 13076 this.minResizeDuration = snapDuration; // hack 13077 13078 13079 13080 this.minTime = moment.duration(view.opt('minTime')); 13081 13082 this.maxTime = moment.duration(view.opt('maxTime')); 13083 13084 13085 13086 // might be an array value (for TimelineView). 13087 13088 // if so, getting the most granular entry (the last one probably). 13089 13090 input = view.opt('slotLabelFormat'); 13091 13092 if ($.isArray(input)) { 13093 13094 input = input[input.length - 1]; 13095 13096 } 13097 13098 13099 13100 this.labelFormat = 13101 13102 input || 13103 13104 view.opt('axisFormat') || // deprecated 13105 13106 view.opt('smallTimeFormat'); // the computed default 13107 13108 13109 13110 input = view.opt('slotLabelInterval'); 13111 13112 this.labelInterval = input ? 13113 13114 moment.duration(input) : 13115 13116 this.computeLabelInterval(slotDuration); 13117 13118 }, 13119 13120 13121 13122 13123 13124 // Computes an automatic value for slotLabelInterval 13125 13126 computeLabelInterval: function(slotDuration) { 13127 13128 var i; 13129 13130 var labelInterval; 13131 13132 var slotsPerLabel; 13133 13134 13135 13136 // find the smallest stock label interval that results in more than one slots-per-label 13137 13138 for (i = AGENDA_STOCK_SUB_DURATIONS.length - 1; i >= 0; i--) { 13139 13140 labelInterval = moment.duration(AGENDA_STOCK_SUB_DURATIONS[i]); 13141 13142 slotsPerLabel = divideDurationByDuration(labelInterval, slotDuration); 13143 13144 if (isInt(slotsPerLabel) && slotsPerLabel > 1) { 13145 13146 return labelInterval; 13147 13148 } 13149 13150 } 13151 13152 13153 13154 return moment.duration(slotDuration); // fall back. clone 13155 13156 }, 13157 13158 13159 13160 13161 13162 // Computes a default event time formatting string if `timeFormat` is not explicitly defined 13163 13164 computeEventTimeFormat: function() { 13165 13166 return this.view.opt('noMeridiemTimeFormat'); // like "6:30" (no AM/PM) 13167 13168 }, 13169 13170 13171 13172 13173 13174 // Computes a default `displayEventEnd` value if one is not expliclty defined 13175 13176 computeDisplayEventEnd: function() { 13177 13178 return true; 13179 13180 }, 13181 13182 13183 13184 13185 13186 /* Hit System 13187 13188 ------------------------------------------------------------------------------------------------------------------*/ 13189 13190 13191 13192 13193 13194 prepareHits: function() { 13195 13196 this.colCoordCache.build(); 13197
13198 this.slatCoordCache.build(); 13199 13200 }, 13201 13202 13203 13204 13205 13206 releaseHits: function() { 13207 13208 this.colCoordCache.clear(); 13209 13210 // NOTE: don't clear slatCoordCache because we rely on it for computeTimeTop 13211 13212 }, 13213 13214 13215 13216 13217 13218 queryHit: function(leftOffset, topOffset) { 13219 13220 var snapsPerSlot = this.snapsPerSlot; 13221 13222 var colCoordCache = this.colCoordCache; 13223 13224 var slatCoordCache = this.slatCoordCache; 13225 13226 var colIndex = colCoordCache.getHorizontalIndex(leftOffset); 13227 13228 var slatIndex = slatCoordCache.getVerticalIndex(topOffset); 13229 13230 13231 13232 if (colIndex != null && slatIndex != null) { 13233 13234 var slatTop = slatCoordCache.getTopOffset(slatIndex); 13235 13236 var slatHeight = slatCoordCache.getHeight(slatIndex); 13237 13238 var partial = (topOffset - slatTop) / slatHeight; // floating point number between 0 and 1 13239 13240 var localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat 13241 13242 var snapIndex = slatIndex * snapsPerSlot + localSnapIndex; 13243 13244 var snapTop = slatTop + (localSnapIndex / snapsPerSlot) * slatHeight; 13245 13246 var snapBottom = slatTop + ((localSnapIndex + 1) / snapsPerSlot) * slatHeight; 13247 13248 13249 13250 return { 13251 13252 col: colIndex, 13253 13254 snap: snapIndex, 13255 13256 component: this, // needed unfortunately :( 13257 13258 left: colCoordCache.getLeftOffset(colIndex), 13259 13260 right: colCoordCache.getRightOffset(colIndex), 13261 13262 top: snapTop, 13263 13264 bottom: snapBottom 13265 13266 }; 13267 13268 } 13269 13270 }, 13271 13272 13273 13274 13275 13276 getHitSpan: function(hit) { 13277 13278 var start = this.getCellDate(0, hit.col); // row=0 13279 13280 var time = this.computeSnapTime(hit.snap); // pass in the snap-index 13281 13282 var end; 13283 13284 13285 13286 start.time(time); 13287 13288 end = start.clone().add(this.snapDuration); 13289 13290 13291 13292 return { start: start, end: end }; 13293 13294 }, 13295 13296 13297 13298 13299 13300 getHitEl: function(hit) { 13301 13302 return this.colEls.eq(hit.col); 13303 13304 }, 13305 13306 13307 13308 13309 13310 /* Dates 13311 13312 ------------------------------------------------------------------------------------------------------------------*/ 13313 13314 13315 13316 13317 13318 rangeUpdated: function() { 13319 13320 this.updateDayTable(); 13321 13322 }, 13323 13324 13325 13326 13327 13328 // Given a row number of the grid, representing a "snap", returns a time (Duration) from its start-of-day 13329 13330 computeSnapTime: function(snapIndex) { 13331 13332 return moment.duration(this.minTime + this.snapDuration * snapIndex); 13333 13334 }, 13335 13336 13337 13338 13339 13340 // Slices up the given span (unzoned start/end with other misc data) into an array of segments 13341 13342 spanToSegs: function(span) { 13343 13344 var segs = this.sliceRangeByTimes(span); 13345 13346 var i; 13347 13348 13349 13350 for (i = 0; i < segs.length; i++) { 13351 13352 if (this.isRTL) { 13353 13354 segs[i].col = this.daysPerRow - 1 - segs[i].dayIndex; 13355 13356 } 13357 13358 else { 13359 13360 segs[i].col = segs[i].dayIndex; 13361 13362 } 13363 13364 } 13365 13366 13367 13368 return segs; 13369 13370 }, 13371 13372 13373 13374 13375 13376 sliceRangeByTimes: function(range) { 13377 13378 var segs = []; 13379 13380 var seg; 13381 13382 var dayIndex; 13383 13384 var dayDate; 13385 13386 var dayRange; 13387 13388 13389 13390 for (dayIndex = 0; dayIndex < this.daysPerRow; dayIndex++) { 13391 13392 dayDate = this.dayDates[dayIndex].clone(); // TODO: better API for this? 13393 13394 dayRange = { 13395 13396 start: dayDate.clone().time(this.minTime), 13397 13398 end: dayDate.clone().time(this.maxTime) 13399 13400 }; 13401 13402 seg = intersectRanges(range, dayRange); // both will be ambig timezone 13403 13404 if (seg) { 13405 13406 seg.dayIndex = dayIndex; 13407 13408 segs.push(seg); 13409 13410 } 13411 13412 } 13413 13414 13415 13416 return segs; 13417 13418 }, 13419 13420 13421 13422 13423 13424 /* Coordinates 13425 13426 ------------------------------------------------------------------------------------------------------------------*/ 13427 13428 13429 13430 13431 13432 updateSize: function(isResize) { // NOT a standard Grid method 13433 13434 this.slatCoordCache.build(); 13435 13436 13437 13438 if (isResize) { 13439 13440 this.updateSegVerticals(); 13441 13442 } 13443 13444 }, 13445 13446 13447 13448 13449 13450 // Computes the top coordinate, relative to the bounds of the grid, of the given date. 13451 13452 // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight. 13453 13454 computeDateTop: function(date, startOfDayDate) { 13455 13456 return this.computeTimeTop( 13457 13458 moment.duration( 13459 13460 date - startOfDayDate.clone().stripTime() 13461 13462 ) 13463 13464 ); 13465 13466 }, 13467 13468 13469 13470 13471 13472 // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration). 13473 13474 computeTimeTop: function(time) { 13475 13476 var len = this.slatEls.length; 13477 13478 var slatCoverage = (time - this.minTime) / this.slotDuration; // floating-point value of # of slots covered 13479 13480 var slatIndex; 13481 13482 var slatRemainder; 13483 13484 13485 13486 // compute a floating-point number for how many slats should be progressed through. 13487 13488 // from 0 to number of slats (inclusive) 13489 13490 // constrained because minTime/maxTime might be customized. 13491 13492 slatCoverage = Math.max(0, slatCoverage); 13493 13494 slatCoverage = Math.min(len, slatCoverage); 13495 13496 13497 13498 // an integer index of the furthest whole slat 13499 13500 // from 0 to number slats (*exclusive*, so len-1) 13501 13502 slatIndex = Math.floor(slatCoverage); 13503 13504 slatIndex = Math.min(slatIndex, len - 1); 13505 13506 13507 13508 // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition. 13509 13510 // could be 1.0 if slatCoverage is covering *all* the slots 13511 13512 slatRemainder = slatCoverage - slatIndex; 13513 13514 13515
13516 return this.slatCoordCache.getTopPosition(slatIndex) + 13517 13518 this.slatCoordCache.getHeight(slatIndex) * slatRemainder; 13519 13520 }, 13521 13522 13523 13524 13525 13526 13527 13528 /* Event Drag Visualization 13529 13530 ------------------------------------------------------------------------------------------------------------------*/ 13531 13532 13533 13534 13535 13536 // Renders a visual indication of an event being dragged over the specified date(s). 13537 13538 // A returned value of `true` signals that a mock "helper" event has been rendered. 13539 13540 renderDrag: function(eventLocation, seg) { 13541 13542 13543 13544 if (seg) { // if there is event information for this drag, render a helper event 13545 13546 this.renderEventLocationHelper(eventLocation, seg); 13547 13548 this.applyDragOpacity(this.helperEl); 13549 13550 13551 13552 return true; // signal that a helper has been rendered 13553 13554 } 13555 13556 else { 13557 13558 // otherwise, just render a highlight 13559 13560 this.renderHighlight(this.eventToSpan(eventLocation)); 13561 13562 } 13563 13564 }, 13565 13566 13567 13568 13569 13570 // Unrenders any visual indication of an event being dragged 13571 13572 unrenderDrag: function() { 13573 13574 this.unrenderHelper(); 13575 13576 this.unrenderHighlight(); 13577 13578 }, 13579 13580 13581 13582 13583 13584 /* Event Resize Visualization 13585 13586 ------------------------------------------------------------------------------------------------------------------*/ 13587 13588 13589 13590 13591 13592 // Renders a visual indication of an event being resized 13593 13594 renderEventResize: function(eventLocation, seg) { 13595 13596 this.renderEventLocationHelper(eventLocation, seg); 13597 13598 }, 13599 13600 13601 13602 13603 13604 // Unrenders any visual indication of an event being resized 13605 13606 unrenderEventResize: function() { 13607 13608 this.unrenderHelper(); 13609 13610 }, 13611 13612 13613 13614 13615 13616 /* Event Helper 13617 13618 ------------------------------------------------------------------------------------------------------------------*/ 13619 13620 13621 13622 13623 13624 // Renders a mock "helper" event. `sourceSeg` is the original segment object and might be null (an external drag) 13625 13626 renderHelper: function(event, sourceSeg) { 13627 13628 var segs = this.eventToSegs(event); 13629 13630 var tableEl; 13631 13632 var i, seg; 13633 13634 var sourceEl; 13635 13636 13637 13638 segs = this.renderFgSegEls(segs); // assigns each seg's el and returns a subset of segs that were rendered 13639 13640 tableEl = this.renderSegTable(segs); 13641 13642 13643 13644 // Try to make the segment that is in the same row as sourceSeg look the same 13645 13646 for (i = 0; i < segs.length; i++) { 13647 13648 seg = segs[i]; 13649 13650 if (sourceSeg && sourceSeg.col === seg.col) { 13651 13652 sourceEl = sourceSeg.el; 13653 13654 seg.el.css({ 13655 13656 left: sourceEl.css('left'), 13657 13658 right: sourceEl.css('right'), 13659 13660 'margin-left': sourceEl.css('margin-left'), 13661 13662 'margin-right': sourceEl.css('margin-right') 13663 13664 }); 13665 13666 } 13667 13668 } 13669 13670 13671 13672 this.helperEl = $('<div class="fc-helper-skeleton"/>') 13673 13674 .append(tableEl) 13675 13676 .appendTo(this.el); 13677 13678 }, 13679 13680 13681 13682 13683 13684 // Unrenders any mock helper event 13685 13686 unrenderHelper: function() { 13687 13688 if (this.helperEl) { 13689 13690 this.helperEl.remove(); 13691 13692 this.helperEl = null; 13693 13694 } 13695 13696 }, 13697 13698 13699 13700 13701 13702 /* Selection 13703 13704 ------------------------------------------------------------------------------------------------------------------*/ 13705 13706 13707 13708 13709 13710 // Renders a visual indication of a selection. Overrides the default, which was to simply render a highlight. 13711 13712 renderSelection: function(span) { 13713 13714 if (this.view.opt('selectHelper')) { // this setting signals that a mock helper event should be rendered 13715 13716 13717 13718 // normally acceps an eventLocation, span has a start/end, which is good enough 13719 13720 this.renderEventLocationHelper(span); 13721 13722 } 13723 13724 else { 13725 13726 this.renderHighlight(span); 13727 13728 } 13729 13730 }, 13731 13732 13733 13734 13735 13736 // Unrenders any visual indication of a selection 13737 13738 unrenderSelection: function() { 13739 13740 this.unrenderHelper(); 13741 13742 this.unrenderHighlight(); 13743 13744 }, 13745 13746 13747 13748 13749 13750 /* Fill System (highlight, background events, business hours) 13751 13752 ------------------------------------------------------------------------------------------------------------------*/ 13753 13754 13755 13756 13757 13758 // Renders a set of rectangles over the given time segments. 13759 13760 // Only returns segments that successfully rendered. 13761 13762 renderFill: function(type, segs, className) { 13763 13764 var segCols; 13765 13766 var skeletonEl; 13767 13768 var trEl; 13769 13770 var col, colSegs; 13771 13772 var tdEl; 13773 13774 var containerEl; 13775 13776 var dayDate; 13777 13778 var i, seg; 13779 13780 13781 13782 if (segs.length) { 13783 13784 13785 13786 segs = this.renderFillSegEls(type, segs); // assignes `.el` to each seg. returns successfully rendered segs 13787 13788 segCols = this.groupSegCols(segs); // group into sub-arrays, and assigns 'col' to each seg 13789 13790 13791 13792 className = className || type.toLowerCase(); 13793 13794 skeletonEl = $( 13795
13796 '<div class="fc-' + className + '-skeleton">' + 13797 13798 '<table><tr/></table>' + 13799 13800 '</div>' 13801 13802 ); 13803 13804 trEl = skeletonEl.find('tr'); 13805 13806 13807 13808 for (col = 0; col < segCols.length; col++) { 13809 13810 colSegs = segCols[col]; 13811 13812 tdEl = $('<td/>').appendTo(trEl); 13813 13814 13815 13816 if (colSegs.length) { 13817 13818 containerEl = $('<div class="fc-' + className + '-container"/>').appendTo(tdEl); 13819 13820 dayDate = this.getCellDate(0, col); // row=0 13821 13822 13823 13824 for (i = 0; i < colSegs.length; i++) { 13825 13826 seg = colSegs[i]; 13827 13828 containerEl.append( 13829 13830 seg.el.css({ 13831 13832 top: this.computeDateTop(seg.start, dayDate), 13833 13834 bottom: -this.computeDateTop(seg.end, dayDate) // the y position of the bottom edge 13835 13836 }) 13837 13838 ); 13839 13840 } 13841 13842 } 13843 13844 } 13845 13846 13847 13848 this.bookendCells(trEl); 13849 13850 13851 13852 this.el.append(skeletonEl); 13853 13854 this.elsByFill[type] = skeletonEl; 13855 13856 } 13857 13858 13859 13860 return segs; 13861 13862 } 13863 13864 13865 13866 }); 13867 13868 13869 13870 ;; 13871 13872 13873 13874 /* Event-rendering methods for the TimeGrid class 13875 13876 ----------------------------------------------------------------------------------------------------------------------*/ 13877 13878 13879 13880 TimeGrid.mixin({ 13881 13882 13883 13884 eventSkeletonEl: null, // has cells with event-containers, which contain absolutely positioned event elements 13885 13886 13887 13888 13889 13890 // Renders the given foreground event segments onto the grid 13891 13892 renderFgSegs: function(segs) { 13893 13894 segs = this.renderFgSegEls(segs); // returns a subset of the segs. segs that were actually rendered 13895 13896 13897 13898 this.el.append( 13899 13900 this.eventSkeletonEl = $('<div class="fc-content-skeleton"/>') 13901 13902 .append(this.renderSegTable(segs)) 13903 13904 ); 13905 13906 13907 13908 return segs; // return only the segs that were actually rendered 13909 13910 }, 13911 13912 13913 13914 13915 13916 // Unrenders all currently rendered foreground event segments 13917 13918 unrenderFgSegs: function(segs) { 13919 13920 if (this.eventSkeletonEl) { 13921 13922 this.eventSkeletonEl.remove(); 13923 13924 this.eventSkeletonEl = null; 13925 13926 } 13927 13928 }, 13929 13930 13931 13932 13933 13934 // Renders and returns the <table> portion of the event-skeleton. 13935 13936 // Returns an object with properties 'tbodyEl' and 'segs'. 13937 13938 renderSegTable: function(segs) { 13939 13940 var tableEl = $('<table><tr/></table>'); 13941 13942 var trEl = tableEl.find('tr'); 13943 13944 var segCols; 13945 13946 var i, seg; 13947 13948 var col, colSegs; 13949 13950 var containerEl; 13951 13952 13953 13954 segCols = this.groupSegCols(segs); // group into sub-arrays, and assigns 'col' to each seg 13955 13956 13957 13958 this.computeSegVerticals(segs); // compute and assign top/bottom 13959 13960 13961 13962 for (col = 0; col < segCols.length; col++) { // iterate each column grouping 13963 13964 colSegs = segCols[col]; 13965 13966 this.placeSlotSegs(colSegs); // compute horizontal coordinates, z-index's, and reorder the array 13967 13968 13969 13970 containerEl = $('<div class="fc-event-container"/>'); 13971 13972 13973 13974 // assign positioning CSS and insert into container 13975 13976 for (i = 0; i < colSegs.length; i++) { 13977 13978 seg = colSegs[i]; 13979 13980 seg.el.css(this.generateSegPositionCss(seg)); 13981 13982 13983 13984 // if the height is short, add a className for alternate styling 13985 13986 if (seg.bottom - seg.top < 30) { 13987 13988 seg.el.addClass('fc-short'); 13989 13990 } 13991 13992 13993 13994 containerEl.append(seg.el); 13995 13996 } 13997 13998 13999 14000 trEl.append($('<td/>').append(containerEl)); 14001 14002 } 14003 14004 14005 14006 this.bookendCells(trEl); 14007 14008 14009 14010 return tableEl; 14011 14012 }, 14013 14014 14015 14016 14017 14018 // Given an array of segments that are all in the same column, sets the backwardCoord and forwardCoord on each. 14019 14020 // NOTE: Also reorders the given array by date! 14021 14022 placeSlotSegs: function(segs) { 14023 14024 var levels; 14025 14026 var level0; 14027 14028 var i; 14029 14030 14031 14032 this.sortEventSegs(segs); // order by certain criteria 14033 14034 levels = buildSlotSegLevels(segs); 14035 14036 computeForwardSlotSegs(levels); 14037 14038 14039 14040 if ((level0 = levels[0])) { 14041 14042 14043 14044 for (i = 0; i < level0.length; i++) { 14045 14046 computeSlotSegPressures(level0[i]); 14047 14048 } 14049 14050 14051 14052 for (i = 0; i < level0.length; i++) { 14053 14054 this.computeSlotSegCoords(level0[i], 0, 0); 14055 14056 } 14057 14058 } 14059 14060 }, 14061 14062 14063 14064 14065 14066 // Calculate seg.forwardCoord and seg.backwardCoord for the segment, where both values range 14067 14068 // from 0 to 1. If the calendar is left-to-right, the seg.backwardCoord maps to "left" and 14069 14070 // seg.forwardCoord maps to "right" (via percentage). Vice-versa if the calendar is right-to-left. 14071 14072 // 14073 14074 // The segment might be part of a "series", which means consecutive segments with the same pressure 14075 14076 // who's width is unknown until an edge has been hit. `seriesBackwardPressure` is the number of 14077 14078 // segments behind this one in the current series, and `seriesBackwardCoord` is the starting 14079 14080 // coordinate of the first segment in the series. 14081 14082 computeSlotSegCoords: function(seg, seriesBackwardPressure, seriesBackwardCoord) { 14083 14084 var forwardSegs = seg.forwardSegs; 14085 14086 var i; 14087 14088 14089 14090 if (seg.forwardCoord === undefined) { // not already computed 14091 14092 14093 14094 if (!forwardSegs.length) { 14095 14096 14097 14098 // if there are no forward segments, this segment should butt up against the edge 14099 14100 seg.forwardCoord = 1; 14101 14102 } 14103 14104 else { 14105 14106 14107 14108 // sort highest pressure first 14109 14110 this.sortForwardSlotSegs(forwardSegs); 14111 14112 14113 14114 // this segment's forwardCoord will be calculated from the backwardCoord of the 14115 14116 // highest-pressure forward segment. 14117 14118 this.computeSlotSegCoords(forwardSegs[0], seriesBackwardPressure + 1, seriesBackwardCoord); 14119 14120 seg.forwardCoord = forwardSegs[0].backwardCoord; 14121 14122 } 14123 14124 14125 14126 // calculate the backwardCoord from the forwardCoord. consider the series 14127 14128 seg.backwardCoord = seg.forwardCoord - 14129 14130 (seg.forwardCoord - seriesBackwardCoord) / // available width for series 14131 14132 (seriesBackwardPressure + 1); // # of segments in the series 14133 14134 14135
14136 // use this segment's coordinates to computed the coordinates of the less-pressurized 14137 14138 // forward segments 14139 14140 for (i=0; i<forwardSegs.length; i++) { 14141 14142 this.computeSlotSegCoords(forwardSegs[i], 0, seg.forwardCoord); 14143 14144 } 14145 14146 } 14147 14148 }, 14149 14150 14151 14152 14153 14154 // Refreshes the CSS top/bottom coordinates for each segment element. Probably after a window resize/zoom. 14155 14156 // Repositions business hours segs too, so not just for events. Maybe shouldn't be here. 14157 14158 updateSegVerticals: function() { 14159 14160 var allSegs = (this.segs || []).concat(this.businessHourSegs || []); 14161 14162 var i; 14163 14164 14165 14166 this.computeSegVerticals(allSegs); 14167 14168 14169 14170 for (i = 0; i < allSegs.length; i++) { 14171 14172 allSegs[i].el.css( 14173 14174 this.generateSegVerticalCss(allSegs[i]) 14175 14176 ); 14177 14178 } 14179 14180 }, 14181 14182 14183 14184 14185 14186 // For each segment in an array, computes and assigns its top and bottom properties 14187 14188 computeSegVerticals: function(segs) { 14189 14190 var i, seg; 14191 14192 14193 14194 for (i = 0; i < segs.length; i++) { 14195 14196 seg = segs[i]; 14197 14198 seg.top = this.computeDateTop(seg.start, seg.start); 14199 14200 seg.bottom = this.computeDateTop(seg.end, seg.start); 14201 14202 } 14203 14204 }, 14205 14206 14207 14208 14209 14210 // Renders the HTML for a single event segment's default rendering 14211 14212 fgSegHtml: function(seg, disableResizing) { 14213 14214 var view = this.view; 14215 14216 var event = seg.event; 14217 14218 var isDraggable = view.isEventDraggable(event); 14219 14220 var isResizableFromStart = !disableResizing && seg.isStart && view.isEventResizableFromStart(event); 14221 14222 var isResizableFromEnd = !disableResizing && seg.isEnd && view.isEventResizableFromEnd(event); 14223 14224 var classes = this.getSegClasses(seg, isDraggable, isResizableFromStart || isResizableFromEnd); 14225 14226 var skinCss = cssToStr(this.getEventSkinCss(event)); 14227 14228 var timeText; 14229 14230 var fullTimeText; // more verbose time text. for the print stylesheet 14231 14232 var startTimeText; // just the start time text 14233 14234 14235 14236 classes.unshift('fc-time-grid-event', 'fc-v-event'); 14237 14238 14239 14240 if (view.isMultiDayEvent(event)) { // if the event appears to span more than one day... 14241 14242 // Don't display time text on segments that run entirely through a day. 14243 14244 // That would appear as midnight-midnight and would look dumb. 14245 14246 // Otherwise, display the time text for the *segment's* times (like 6pm-midnight or midnight-10am) 14247 14248 if (seg.isStart || seg.isEnd) { 14249 14250 timeText = this.getEventTimeText(seg); 14251 14252 fullTimeText = this.getEventTimeText(seg, 'LT'); 14253 14254 startTimeText = this.getEventTimeText(seg, null, false); // displayEnd=false 14255 14256 } 14257 14258 } else { 14259 14260 // Display the normal time text for the *event's* times 14261 14262 timeText = this.getEventTimeText(event); 14263 14264 fullTimeText = this.getEventTimeText(event, 'LT'); 14265 14266 startTimeText = this.getEventTimeText(event, null, false); // displayEnd=false 14267 14268 } 14269 14270 14271 14272 return '<a class="' + classes.join(' ') + '"' + 14273 14274 (event.url ? 14275 14276 ' href="' + htmlEscape(event.url) + '"' : 14277 14278 '' 14279 14280 ) + 14281 14282 (skinCss ? 14283 14284 ' style="' + skinCss + '"' : 14285 14286 '' 14287 14288 ) + 14289 14290 '>' + 14291 14292 '<div class="fc-content">' + 14293 14294 (timeText ? 14295 14296 '<div class="fc-time"' + 14297 14298 ' data-start="' + htmlEscape(startTimeText) + '"' + 14299 14300 ' data-full="' + htmlEscape(fullTimeText) + '"' + 14301 14302 '>' + 14303 14304 '<span>' + htmlEscape(timeText) + '</span>' + 14305 14306 '</div>' : 14307 14308 '' 14309 14310 ) + 14311 14312 (event.title ? 14313 14314 '<div class="fc-title">' + 14315 14316 htmlEscape(event.title) + 14317 14318 '</div>' : 14319 14320 '' 14321 14322 ) + 14323 14324 '</div>' + 14325 14326 '<div class="fc-bg"/>' + 14327 14328 /* TODO: write CSS for this 14329 14330 (isResizableFromStart ? 14331 14332 '<div class="fc-resizer fc-start-resizer" />' : 14333 14334 '' 14335 14336 ) + 14337 14338 */ 14339 14340 (isResizableFromEnd ? 14341 14342 '<div class="fc-resizer fc-end-resizer" />' : 14343 14344 '' 14345 14346 ) + 14347 14348 '</a>'; 14349 14350 }, 14351 14352 14353 14354 14355 14356 // Generates an object with CSS properties/values that should be applied to an event segment element. 14357 14358 // Contains important positioning-related properties that should be applied to any event element, customized or not. 14359 14360 generateSegPositionCss: function(seg) { 14361 14362 var shouldOverlap = this.view.opt('slotEventOverlap'); 14363 14364 var backwardCoord = seg.backwardCoord; // the left side if LTR. the right side if RTL. floating-point 14365 14366 var forwardCoord = seg.forwardCoord; // the right side if LTR. the left side if RTL. floating-point 14367 14368 var props = this.generateSegVerticalCss(seg); // get top/bottom first 14369 14370 var left; // amount of space from left edge, a fraction of the total width 14371 14372 var right; // amount of space from right edge, a fraction of the total width 14373 14374 14375 14376 if (shouldOverlap) { 14377 14378 // double the width, but don't go beyond the maximum forward coordinate (1.0) 14379 14380 forwardCoord = Math.min(1, backwardCoord + (forwardCoord - backwardCoord) * 2); 14381 14382 } 14383 14384 14385 14386 if (this.isRTL) { 14387 14388 left = 1 - forwardCoord; 14389 14390 right = backwardCoord; 14391 14392 } 14393 14394 else { 14395 14396 left = backwardCoord; 14397 14398 right = 1 - forwardCoord; 14399 14400 } 14401 14402 14403 14404 props.zIndex = seg.level + 1; // convert from 0-base to 1-based 14405 14406 props.left = left * 100 + '%'; 14407 14408 props.right = right * 100 + '%'; 14409 14410 14411 14412 if (shouldOverlap && seg.forwardPressure) { 14413 14414 // add padding to the edge so that forward stacked events don't cover the resizer's icon 14415 14416 props[this.isRTL ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width 14417 14418 } 14419 14420 14421 14422 return props; 14423 14424 }, 14425 14426 14427 14428 14429 14430 // Generates an object with CSS properties for the top/bottom coordinates of a segment element 14431 14432 generateSegVerticalCss: function(seg) { 14433 14434 return { 14435 14436 top: seg.top, 14437 14438 bottom: -seg.bottom // flipped because needs to be space beyond bottom edge of event container 14439 14440 }; 14441 14442 }, 14443 14444 14445 14446 14447 14448 // Given a flat array of segments, return an array of sub-arrays, grouped by each segment's col 14449 14450 groupSegCols: function(segs) { 14451 14452 var segCols = []; 14453 14454 var i; 14455 14456 14457 14458 for (i = 0; i < this.colCnt; i++) { 14459 14460 segCols.push([]); 14461 14462 } 14463 14464 14465 14466 for (i = 0; i < segs.length; i++) { 14467 14468 segCols[segs[i].col].push(segs[i]); 14469 14470 } 14471 14472 14473 14474 return segCols; 14475 14476 }, 14477 14478 14479 14480 14481 14482 sortForwardSlotSegs: function(forwardSegs) { 14483 14484 forwardSegs.sort(proxy(this, 'compareForwardSlotSegs')); 14485 14486 }, 14487 14488 14489 14490 14491 14492 // A cmp function for determining which forward segment to rely on more when computing coordinates. 14493 14494 compareForwardSlotSegs: function(seg1, seg2) { 14495 14496 // put higher-pressure first 14497 14498 return seg2.forwardPressure - seg1.forwardPressure || 14499 14500 // put segments that are closer to initial edge first (and favor ones with no coords yet) 14501 14502 (seg1.backwardCoord || 0) - (seg2.backwardCoord || 0) || 14503 14504 // do normal sorting... 14505 14506 this.compareEventSegs(seg1, seg2); 14507 14508 } 14509 14510 14511 14512 }); 14513 14514 14515 14516 14517 14518// Builds an array of segments "levels". The first level will be the leftmost tier of segments if the calendar is 14519 14520// left-to-right, or the rightmost if the calendar is right-to-left. Assumes the segments are already ordered by date. 14521 14522 function buildSlotSegLevels(segs) { 14523 14524 var levels = []; 14525 14526 var i, seg; 14527 14528 var j; 14529 14530 14531 14532 for (i=0; i<segs.length; i++) { 14533 14534 seg = segs[i]; 14535 14536 14537 14538 // go through all the levels and stop on the first level where there are no collisions 14539 14540 for (j=0; j<levels.length; j++) { 14541 14542 if (!computeSlotSegCollisions(seg, levels[j]).length) { 14543 14544 break; 14545 14546 } 14547 14548 } 14549 14550 14551 14552 seg.level = j; 14553 14554 14555 14556 (levels[j] || (levels[j] = [])).push(seg); 14557 14558 } 14559 14560 14561 14562 return levels; 14563 14564 } 14565 14566 14567 14568 14569 14570// For every segment, figure out the other segments that are in subsequent 14571 14572// levels that also occupy the same vertical space. Accumulate in seg.forwardSegs 14573 14574 function computeForwardSlotSegs(levels) { 14575 14576 var i, level; 14577 14578 var j, seg; 14579 14580 var k; 14581 14582 14583 14584 for (i=0; i<levels.length; i++) { 14585 14586 level = levels[i]; 14587 14588 14589 14590 for (j=0; j<level.length; j++) { 14591 14592 seg = level[j]; 14593 14594 14595 14596 seg.forwardSegs = []; 14597 14598 for (k=i+1; k<levels.length; k++) { 14599 14600 computeSlotSegCollisions(seg, levels[k], seg.forwardSegs); 14601 14602 } 14603 14604 } 14605 14606 } 14607 14608 } 14609 14610 14611 14612 14613 14614// Figure out which path forward (via seg.forwardSegs) results in the longest path until 14615 14616// the furthest edge is reached. The number of segments in this path will be seg.forwardPressure 14617 14618 function computeSlotSegPressures(seg) { 14619 14620 var forwardSegs = seg.forwardSegs; 14621 14622 var forwardPressure = 0; 14623 14624 var i, forwardSeg; 14625 14626 14627 14628 if (seg.forwardPressure === undefined) { // not already computed 14629 14630 14631 14632 for (i=0; i<forwardSegs.length; i++) { 14633 14634 forwardSeg = forwardSegs[i]; 14635 14636 14637 14638 // figure out the child's maximum forward path 14639 14640 computeSlotSegPressures(forwardSeg); 14641 14642 14643 14644 // either use the existing maximum, or use the child's forward pressure 14645 14646 // plus one (for the forwardSeg itself) 14647 14648 forwardPressure = Math.max( 14649 14650 forwardPressure, 14651 14652 1 + forwardSeg.forwardPressure 14653 14654 ); 14655 14656 } 14657 14658 14659 14660 seg.forwardPressure = forwardPressure; 14661 14662 } 14663 14664 } 14665 14666 14667 14668 14669 14670// Find all the segments in `otherSegs` that vertically collide with `seg`. 14671 14672// Append into an optionally-supplied `results` array and return. 14673 14674 function computeSlotSegCollisions(seg, otherSegs, results) { 14675 14676 results = results || []; 14677 14678 14679 14680 for (var i=0; i<otherSegs.length; i++) { 14681 14682 if (isSlotSegCollision(seg, otherSegs[i])) { 14683 14684 results.push(otherSegs[i]); 14685 14686 } 14687 14688 } 14689 14690 14691 14692 return results; 14693 14694 } 14695 14696 14697 14698 14699 14700// Do these segments occupy the same vertical space? 14701 14702 function isSlotSegCollision(seg1, seg2) { 14703 14704 return seg1.bottom > seg2.top && seg1.top < seg2.bottom; 14705 14706 } 14707 14708 14709 14710 ;; 14711 14712 14713 14714 /* An abstract class from which other views inherit from 14715 14716 ----------------------------------------------------------------------------------------------------------------------*/ 14717 14718 14719 14720 var View = FC.View = Class.extend({ 14721 14722 14723 14724 type: null, // subclass' view name (string) 14725 14726 name: null, // deprecated. use `type` instead 14727 14728 title: null, // the text that will be displayed in the header's title 14729 14730 14731 14732 calendar: null, // owner Calendar object 14733 14734 options: null, // hash containing all options. already merged with view-specific-options 14735 14736 el: null, // the view's containing element. set by Calendar 14737 14738 14739 14740 displaying: null, // a promise representing the state of rendering. null if no render requested 14741 14742 isSkeletonRendered: false, 14743 14744 isEventsRendered: false, 14745 14746 14747 14748 // range the view is actually displaying (moments) 14749 14750 start: null, 14751 14752 end: null, // exclusive 14753 14754 14755 14756 // range the view is formally responsible for (moments) 14757 14758 // may be different from start/end. for example, a month view might have 1st-31st, excluding padded dates 14759 14760 intervalStart: null, 14761 14762 intervalEnd: null, // exclusive 14763 14764 intervalDuration: null, 14765 14766 intervalUnit: null, // name of largest unit being displayed, like "month" or "week" 14767 14768 14769 14770 isRTL: false, 14771 14772 isSelected: false, // boolean whether a range of time is user-selected or not 14773 14774 14775 14776 eventOrderSpecs: null, // criteria for ordering events when they have same date/time 14777 14778 14779 14780 // subclasses can optionally use a scroll container 14781 14782 scrollerEl: null, // the element that will most likely scroll when content is too tall 14783 14784 scrollTop: null, // cached vertical scroll value 14785 14786 14787 14788 // classNames styled by jqui themes 14789 14790 widgetHeaderClass: null, 14791 14792 widgetContentClass: null, 14793 14794 highlightStateClass: null, 14795 14796 14797 14798 // for date utils, computed from options 14799 14800 nextDayThreshold: null, 14801
14802 isHiddenDayHash: null, 14803 14804 14805 14806 // document handlers, bound to `this` object 14807 14808 documentMousedownProxy: null, // TODO: doesn't work with touch 14809 14810 14811 14812 14813 14814 constructor: function(calendar, type, options, intervalDuration) { 14815 14816 14817 14818 this.calendar = calendar; 14819 14820 this.type = this.name = type; // .name is deprecated 14821 14822 this.options = options; 14823 14824 this.intervalDuration = intervalDuration || moment.duration(1, 'day'); 14825 14826 14827 14828 this.nextDayThreshold = moment.duration(this.opt('nextDayThreshold')); 14829 14830 this.initThemingProps(); 14831 14832 this.initHiddenDays(); 14833 14834 this.isRTL = this.opt('isRTL'); 14835 14836 14837 14838 this.eventOrderSpecs = parseFieldSpecs(this.opt('eventOrder')); 14839 14840 14841 14842 this.documentMousedownProxy = proxy(this, 'documentMousedown'); 14843 14844 14845 14846 this.initialize(); 14847 14848 }, 14849 14850 14851 14852 14853 14854 // A good place for subclasses to initialize member variables 14855 14856 initialize: function() { 14857 14858 // subclasses can implement 14859 14860 }, 14861 14862 14863 14864 14865 14866 // Retrieves an option with the given name 14867 14868 opt: function(name) { 14869 14870 return this.options[name]; 14871 14872 }, 14873 14874 14875 14876 14877 14878 // Triggers handlers that are view-related. Modifies args before passing to calendar. 14879 14880 trigger: function(name, thisObj) { // arguments beyond thisObj are passed along 14881 14882 var calendar = this.calendar; 14883 14884 14885 14886 return calendar.trigger.apply( 14887 14888 calendar, 14889 14890 [name, thisObj || this].concat( 14891 14892 Array.prototype.slice.call(arguments, 2), // arguments beyond thisObj 14893 14894 [ this ] // always make the last argument a reference to the view. TODO: deprecate 14895 14896 ) 14897 14898 ); 14899 14900 }, 14901 14902 14903 14904 14905 14906 /* Dates 14907 14908 ------------------------------------------------------------------------------------------------------------------*/ 14909 14910 14911 14912 14913 14914 // Updates all internal dates to center around the given current unzoned date. 14915 14916 setDate: function(date) { 14917 14918 this.setRange(this.computeRange(date)); 14919 14920 }, 14921 14922 14923 14924 14925 14926 // Updates all internal dates for displaying the given unzoned range. 14927 14928 setRange: function(range) { 14929 14930 $.extend(this, range); // assigns every property to this object's member variables 14931 14932 this.updateTitle(); 14933 14934 }, 14935 14936 14937 14938 14939 14940 // Given a single current unzoned date, produce information about what range to display. 14941 14942 // Subclasses can override. Must return all properties. 14943 14944 computeRange: function(date) { 14945 14946 var intervalUnit = computeIntervalUnit(this.intervalDuration); 14947 14948 var intervalStart = date.clone().startOf(intervalUnit); 14949 14950 var intervalEnd = intervalStart.clone().add(this.intervalDuration); 14951 14952 var start, end; 14953 14954 14955 14956 // normalize the range's time-ambiguity 14957 14958 if (/year|month|week|day/.test(intervalUnit)) { // whole-days? 14959 14960 intervalStart.stripTime(); 14961 14962 intervalEnd.stripTime(); 14963 14964 } 14965 14966 else { // needs to have a time? 14967 14968 if (!intervalStart.hasTime()) { 14969 14970 intervalStart = this.calendar.time(0); // give 00:00 time 14971 14972 } 14973 14974 if (!intervalEnd.hasTime()) { 14975 14976 intervalEnd = this.calendar.time(0); // give 00:00 time 14977 14978 } 14979 14980 } 14981 14982 14983 14984 start = intervalStart.clone(); 14985 14986 start = this.skipHiddenDays(start); 14987 14988 end = intervalEnd.clone(); 14989 14990 end = this.skipHiddenDays(end, -1, true); // exclusively move backwards 14991 14992 14993 14994 return { 14995 14996 intervalUnit: intervalUnit, 14997 14998 intervalStart: intervalStart, 14999 15000 intervalEnd: intervalEnd, 15001 15002 start: start, 15003 15004 end: end 15005 15006 }; 15007 15008 }, 15009 15010 15011 15012 15013 15014 // Computes the new date when the user hits the prev button, given the current date 15015 15016 computePrevDate: function(date) { 15017 15018 return this.massageCurrentDate( 15019 15020 date.clone().startOf(this.intervalUnit).subtract(this.intervalDuration), -1 15021 15022 ); 15023 15024 }, 15025 15026 15027 15028 15029 15030 // Computes the new date when the user hits the next button, given the current date 15031 15032 computeNextDate: function(date) { 15033 15034 return this.massageCurrentDate( 15035 15036 date.clone().startOf(this.intervalUnit).add(this.intervalDuration) 15037 15038 ); 15039 15040 }, 15041 15042 15043 15044 15045 15046 // Given an arbitrarily calculated current date of the calendar, returns a date that is ensured to be completely 15047 15048 // visible. `direction` is optional and indicates which direction the current date was being 15049 15050 // incremented or decremented (1 or -1). 15051 15052 massageCurrentDate: function(date, direction) { 15053 15054 if (this.intervalDuration.as('days') <= 1) { // if the view displays a single day or smaller 15055
15056 if (this.isHiddenDay(date)) { 15057 15058 date = this.skipHiddenDays(date, direction); 15059 15060 date.startOf('day'); 15061 15062 } 15063 15064 } 15065 15066 15067 15068 return date; 15069 15070 }, 15071 15072 15073 15074 15075 15076 /* Title and Date Formatting 15077 15078 ------------------------------------------------------------------------------------------------------------------*/ 15079 15080 15081 15082 15083 15084 // Sets the view's title property to the most updated computed value 15085 15086 updateTitle: function() { 15087 15088 this.title = this.computeTitle(); 15089 15090 }, 15091 15092 15093 15094 15095 15096 // Computes what the title at the top of the calendar should be for this view 15097 15098 computeTitle: function() { 15099 15100 return this.formatRange( 15101 15102 { 15103 15104 // in case intervalStart/End has a time, make sure timezone is correct 15105 15106 start: this.calendar.applyTimezone(this.intervalStart), 15107 15108 end: this.calendar.applyTimezone(this.intervalEnd) 15109 15110 }, 15111 15112 this.opt('titleFormat') || this.computeTitleFormat(), 15113 15114 this.opt('titleRangeSeparator') 15115 15116 ); 15117 15118 }, 15119 15120 15121 15122 15123 15124 // Generates the format string that should be used to generate the title for the current date range. 15125 15126 // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`. 15127 15128 computeTitleFormat: function() { 15129 15130 if (this.intervalUnit == 'year') { 15131 15132 return 'YYYY'; 15133 15134 } 15135 15136 else if (this.intervalUnit == 'month') { 15137 15138 return this.opt('monthYearFormat'); // like "September 2014" 15139 15140 } 15141 15142 else if (this.intervalDuration.as('days') > 1) { 15143 15144 return 'll'; // multi-day range. shorter, like "Sep 9 - 10 2014" 15145 15146 } 15147 15148 else { 15149 15150 return 'LL'; // one day. longer, like "September 9 2014" 15151 15152 } 15153 15154 }, 15155 15156 15157 15158 15159 15160 // Utility for formatting a range. Accepts a range object, formatting string, and optional separator. 15161 15162 // Displays all-day ranges naturally, with an inclusive end. Takes the current isRTL into account. 15163 15164 // The timezones of the dates within `range` will be respected. 15165 15166 formatRange: function(range, formatStr, separator) { 15167 15168 var end = range.end; 15169 15170 15171 15172 if (!end.hasTime()) { // all-day? 15173 15174 end = end.clone().subtract(1); // convert to inclusive. last ms of previous day 15175 15176 } 15177 15178 15179 15180 return formatRange(range.start, end, formatStr, separator, this.opt('isRTL')); 15181 15182 }, 15183 15184 15185 15186 15187 15188 /* Rendering 15189 15190 ------------------------------------------------------------------------------------------------------------------*/ 15191 15192 15193 15194 15195 15196 // Sets the container element that the view should render inside of. 15197 15198 // Does other DOM-related initializations. 15199 15200 setElement: function(el) { 15201 15202 this.el = el; 15203 15204 this.bindGlobalHandlers(); 15205 15206 }, 15207 15208 15209 15210 15211 15212 // Removes the view's container element from the DOM, clearing any content beforehand. 15213 15214 // Undoes any other DOM-related attachments. 15215 15216 removeElement: function() { 15217 15218 this.clear(); // clears all content 15219 15220 15221 15222 // clean up the skeleton 15223 15224 if (this.isSkeletonRendered) { 15225 15226 this.unrenderSkeleton(); 15227 15228 this.isSkeletonRendered = false; 15229 15230 } 15231 15232 15233 15234 this.unbindGlobalHandlers(); 15235 15236 15237 15238 this.el.remove(); 15239 15240 15241 15242 // NOTE: don't null-out this.el in case the View was destroyed within an API callback. 15243 15244 // We don't null-out the View's other jQuery element references upon destroy, 15245 15246 // so we shouldn't kill this.el either. 15247 15248 }, 15249 15250 15251 15252 15253 15254 // Does everything necessary to display the view centered around the given unzoned date. 15255 15256 // Does every type of rendering EXCEPT rendering events. 15257 15258 // Is asychronous and returns a promise. 15259 15260 display: function(date) { 15261 15262 var _this = this; 15263 15264 var scrollState = null; 15265 15266 15267 15268 if (this.displaying) { 15269 15270 scrollState = this.queryScroll(); 15271 15272 } 15273 15274 15275 15276 this.calendar.freezeContentHeight(); 15277 15278 15279 15280 return this.clear().then(function() { // clear the content first (async) 15281 15282 return ( 15283 15284 _this.displaying = 15285 15286 $.when(_this.displayView(date)) // displayView might return a promise 15287 15288 .then(function() { 15289 15290 _this.forceScroll(_this.computeInitialScroll(scrollState)); 15291 15292 _this.calendar.unfreezeContentHeight(); 15293 15294 _this.triggerRender(); 15295 15296 }) 15297 15298 ); 15299 15300 }); 15301 15302 }, 15303 15304 15305 15306 15307 15308 // Does everything necessary to clear the content of the view. 15309 15310 // Clears dates and events. Does not clear the skeleton. 15311 15312 // Is asychronous and returns a promise. 15313 15314 clear: function() { 15315 15316 var _this = this; 15317 15318 var displaying = this.displaying; 15319 15320 15321
15322 if (displaying) { // previously displayed, or in the process of being displayed? 15323 15324 return displaying.then(function() { // wait for the display to finish 15325 15326 _this.displaying = null; 15327 15328 _this.clearEvents(); 15329 15330 return _this.clearView(); // might return a promise. chain it 15331 15332 }); 15333 15334 } 15335 15336 else { 15337 15338 return $.when(); // an immediately-resolved promise 15339 15340 } 15341 15342 }, 15343 15344 15345 15346 15347 15348 // If the view has already been displayed, tears it down and displays it again. 15349 15350 // Will re-render the events if necessary, which display/clear DO NOT do. 15351 15352 // TODO: make behavior more consistent. 15353 15354 redisplay: function() { 15355 15356 if (this.isSkeletonRendered) { 15357 15358 var wasEventsRendered = this.isEventsRendered; 15359 15360 this.clearEvents(); // won't trigger handlers if events never rendered 15361 15362 this.clearView(); 15363 15364 this.displayView(); 15365 15366 if (wasEventsRendered) { // only render and trigger handlers if events previously rendered 15367 15368 this.displayEvents(); 15369 15370 } 15371 15372 } 15373 15374 }, 15375 15376 15377 15378 15379 15380 // Displays the view's non-event content, such as date-related content or anything required by events. 15381 15382 // Renders the view's non-content skeleton if necessary. 15383 15384 // Can be asynchronous and return a promise. 15385 15386 displayView: function(date) { 15387 15388 if (!this.isSkeletonRendered) { 15389 15390 this.renderSkeleton(); 15391 15392 this.isSkeletonRendered = true; 15393 15394 } 15395 15396 if (date) { 15397 15398 this.setDate(date); 15399 15400 } 15401 15402 if (this.render) { 15403 15404 this.render(); // TODO: deprecate 15405 15406 } 15407 15408 this.renderDates(); 15409 15410 this.updateSize(); 15411 15412 this.renderBusinessHours(); // might need coordinates, so should go after updateSize() 15413 15414 }, 15415 15416 15417 15418 15419 15420 // Unrenders the view content that was rendered in displayView. 15421 15422 // Can be asynchronous and return a promise. 15423 15424 clearView: function() { 15425 15426 this.unselect(); 15427 15428 this.triggerUnrender(); 15429 15430 this.unrenderBusinessHours(); 15431 15432 this.unrenderDates(); 15433 15434 if (this.destroy) { 15435 15436 this.destroy(); // TODO: deprecate 15437 15438 } 15439 15440 }, 15441 15442 15443 15444 15445 15446 // Renders the basic structure of the view before any content is rendered 15447 15448 renderSkeleton: function() { 15449 15450 // subclasses should implement 15451 15452 }, 15453 15454 15455 15456 15457 15458 // Unrenders the basic structure of the view 15459 15460 unrenderSkeleton: function() { 15461 15462 // subclasses should implement 15463 15464 }, 15465 15466 15467 15468 15469 15470 // Renders the view's date-related content. 15471 15472 // Assumes setRange has already been called and the skeleton has already been rendered. 15473 15474 renderDates: function() { 15475 15476 // subclasses should implement 15477 15478 }, 15479 15480 15481 15482 15483 15484 // Unrenders the view's date-related content 15485 15486 unrenderDates: function() { 15487 15488 // subclasses should override 15489 15490 }, 15491 15492 15493 15494 15495 15496 // Renders business-hours onto the view. Assumes updateSize has already been called. 15497 15498 renderBusinessHours: function() { 15499 15500 // subclasses should implement 15501 15502 }, 15503 15504 15505 15506 15507 15508 // Unrenders previously-rendered business-hours 15509 15510 unrenderBusinessHours: function() { 15511 15512 // subclasses should implement 15513 15514 }, 15515 15516 15517 15518 15519 15520 // Signals that the view's content has been rendered 15521 15522 triggerRender: function() { 15523 15524 this.trigger('viewRender', this, this, this.el); 15525 15526 }, 15527 15528 15529 15530 15531 15532 // Signals that the view's content is about to be unrendered 15533 15534 triggerUnrender: function() { 15535 15536 this.trigger('viewDestroy', this, this, this.el); 15537 15538 }, 15539 15540 15541 15542 15543 15544 // Binds DOM handlers to elements that reside outside the view container, such as the document 15545 15546 bindGlobalHandlers: function() { 15547 15548 $(document).on('mousedown', this.documentMousedownProxy); 15549 15550 }, 15551 15552 15553 15554 15555 15556 // Unbinds DOM handlers from elements that reside outside the view container 15557 15558 unbindGlobalHandlers: function() { 15559 15560 $(document).off('mousedown', this.documentMousedownProxy); 15561 15562 }, 15563 15564 15565 15566 15567 15568 // Initializes internal variables related to theming 15569 15570 initThemingProps: function() { 15571 15572 var tm = this.opt('theme') ? 'ui' : 'fc'; 15573 15574 15575 15576 this.widgetHeaderClass = tm + '-widget-header'; 15577 15578 this.widgetContentClass = tm + '-widget-content'; 15579 15580 this.highlightStateClass = tm + '-state-highlight'; 15581 15582 }, 15583 15584 15585 15586 15587 15588 /* Dimensions 15589 15590 ------------------------------------------------------------------------------------------------------------------*/ 15591 15592 15593 15594 15595 15596 // Refreshes anything dependant upon sizing of the container element of the grid 15597 15598 updateSize: function(isResize) { 15599 15600 var scrollState; 15601 15602 15603 15604 if (isResize) { 15605 15606 scrollState = this.queryScroll(); 15607 15608 } 15609 15610 15611 15612 this.updateHeight(isResize); 15613 15614 this.updateWidth(isResize); 15615 15616 15617 15618 if (isResize) { 15619 15620 this.setScroll(scrollState); 15621 15622 } 15623 15624 }, 15625 15626 15627 15628 15629 15630 // Refreshes the horizontal dimensions of the calendar 15631 15632 updateWidth: function(isResize) { 15633 15634 // subclasses should implement 15635 15636 }, 15637 15638 15639 15640 15641 15642 // Refreshes the vertical dimensions of the calendar 15643 15644 updateHeight: function(isResize) { 15645 15646 var calendar = this.calendar; // we poll the calendar for height information 15647 15648 15649 15650 this.setHeight( 15651 15652 calendar.getSuggestedViewHeight(), 15653 15654 calendar.isHeightAuto() 15655 15656 ); 15657 15658 }, 15659 15660 15661 15662 15663 15664 // Updates the vertical dimensions of the calendar to the specified height. 15665 15666 // if `isAuto` is set to true, height becomes merely a suggestion and the view should use its "natural" height. 15667 15668 setHeight: function(height, isAuto) { 15669 15670 // subclasses should implement 15671 15672 }, 15673 15674 15675 15676 15677
15678 /* Scroller 15679 15680 ------------------------------------------------------------------------------------------------------------------*/ 15681 15682 15683 15684 15685 15686 // Given the total height of the view, return the number of pixels that should be used for the scroller. 15687 15688 // Utility for subclasses. 15689 15690 computeScrollerHeight: function(totalHeight) { 15691 15692 var scrollerEl = this.scrollerEl; 15693 15694 var both; 15695 15696 var otherHeight; // cumulative height of everything that is not the scrollerEl in the view (header+borders) 15697 15698 15699 15700 both = this.el.add(scrollerEl); 15701 15702 15703 15704 // fuckin IE8/9/10/11 sometimes returns 0 for dimensions. this weird hack was the only thing that worked 15705 15706 both.css({ 15707 15708 position: 'relative', // cause a reflow, which will force fresh dimension recalculation 15709 15710 left: -1 // ensure reflow in case the el was already relative. negative is less likely to cause new scroll 15711 15712 }); 15713 15714 otherHeight = this.el.outerHeight() - scrollerEl.height(); // grab the dimensions 15715 15716 both.css({ position: '', left: '' }); // undo hack 15717 15718 15719 15720 return totalHeight - otherHeight; 15721 15722 }, 15723 15724 15725 15726 15727 15728 // Computes the initial pre-configured scroll state prior to allowing the user to change it. 15729 15730 // Given the scroll state from the previous rendering. If first time rendering, given null. 15731 15732 computeInitialScroll: function(previousScrollState) { 15733 15734 return 0; 15735 15736 }, 15737 15738 15739 15740 15741 15742 // Retrieves the view's current natural scroll state. Can return an arbitrary format. 15743 15744 queryScroll: function() { 15745 15746 if (this.scrollerEl) { 15747 15748 return this.scrollerEl.scrollTop(); // operates on scrollerEl by default 15749 15750 } 15751 15752 }, 15753 15754 15755 15756 15757 15758 // Sets the view's scroll state. Will accept the same format computeInitialScroll and queryScroll produce. 15759 15760 setScroll: function(scrollState) { 15761 15762 if (this.scrollerEl) { 15763 15764 return this.scrollerEl.scrollTop(scrollState); // operates on scrollerEl by default 15765 15766 } 15767 15768 }, 15769 15770 15771 15772 15773 15774 // Sets the scroll state, making sure to overcome any predefined scroll value the browser has in mind 15775 15776 forceScroll: function(scrollState) { 15777 15778 var _this = this; 15779 15780 15781 15782 this.setScroll(scrollState); 15783 15784 setTimeout(function() { 15785 15786 _this.setScroll(scrollState); 15787 15788 }, 0); 15789 15790 }, 15791 15792 15793 15794 15795 15796 /* Event Elements / Segments 15797 15798 ------------------------------------------------------------------------------------------------------------------*/ 15799 15800 15801 15802 15803 15804 // Does everything necessary to display the given events onto the current view 15805 15806 displayEvents: function(events) { 15807 15808 var scrollState = this.queryScroll(); 15809 15810 15811 15812 this.clearEvents(); 15813 15814 this.renderEvents(events); 15815 15816 this.isEventsRendered = true; 15817 15818 this.setScroll(scrollState); 15819 15820 this.triggerEventRender(); 15821 15822 }, 15823 15824 15825 15826 15827 15828 // Does everything necessary to clear the view's currently-rendered events 15829 15830 clearEvents: function() { 15831 15832 if (this.isEventsRendered) { 15833 15834 this.triggerEventUnrender(); 15835 15836 if (this.destroyEvents) { 15837 15838 this.destroyEvents(); // TODO: deprecate 15839 15840 } 15841 15842 this.unrenderEvents(); 15843 15844 this.isEventsRendered = false; 15845 15846 } 15847 15848 }, 15849 15850 15851 15852 15853 15854 // Renders the events onto the view. 15855 15856 renderEvents: function(events) { 15857 15858 // subclasses should implement 15859 15860 }, 15861 15862 15863 15864 15865 15866 // Removes event elements from the view. 15867 15868 unrenderEvents: function() { 15869 15870 // subclasses should implement 15871 15872 }, 15873 15874 15875 15876 15877 15878 // Signals that all events have been rendered 15879 15880 triggerEventRender: function() { 15881 15882 this.renderedEventSegEach(function(seg) { 15883 15884 this.trigger('eventAfterRender', seg.event, seg.event, seg.el); 15885 15886 }); 15887 15888 this.trigger('eventAfterAllRender'); 15889 15890 }, 15891 15892 15893 15894 15895 15896 // Signals that all event elements are about to be removed 15897 15898 triggerEventUnrender: function() { 15899 15900 this.renderedEventSegEach(function(seg) { 15901 15902 this.trigger('eventDestroy', seg.event, seg.event, seg.el); 15903 15904 }); 15905 15906 }, 15907 15908 15909 15910 15911 15912 // Given an event and the default element used for rendering, returns the element that should actually be used. 15913 15914 // Basically runs events and elements through the eventRender hook. 15915 15916 resolveEventEl: function(event, el) { 15917 15918 var custom = this.trigger('eventRender', event, event, el); 15919 15920 15921 15922 if (custom === false) { // means don't render at all 15923 15924 el = null; 15925 15926 } 15927 15928 else if (custom && custom !== true) { 15929 15930 el = $(custom); 15931 15932 } 15933 15934 15935 15936 return el; 15937 15938 }, 15939 15940 15941 15942 15943 15944 // Hides all rendered event segments linked to the given event 15945 15946 showEvent: function(event) { 15947 15948 this.renderedEventSegEach(function(seg) { 15949 15950 seg.el.css('visibility', ''); 15951 15952 }, event); 15953 15954 }, 15955 15956 15957 15958 15959 15960 // Shows all rendered event segments linked to the given event 15961 15962 hideEvent: function(event) { 15963 15964 this.renderedEventSegEach(function(seg) { 15965 15966 seg.el.css('visibility', 'hidden'); 15967 15968 }, event); 15969 15970 }, 15971 15972 15973 15974 15975 15976 // Iterates through event segments that have been rendered (have an el). Goes through all by default. 15977 15978 // If the optional `event` argument is specified, only iterates through segments linked to that event. 15979 15980 // The `this` value of the callback function will be the view. 15981 15982 renderedEventSegEach: function(func, event) { 15983 15984 var segs = this.getEventSegs(); 15985 15986 var i; 15987 15988 15989 15990 for (i = 0; i < segs.length; i++) { 15991 15992 if (!event || segs[i].event._id === event._id) { 15993 15994 if (segs[i].el) { 15995 15996 func.call(this, segs[i]); 15997 15998 } 15999 16000 } 16001 16002 } 16003 16004 }, 16005 16006 16007 16008 16009 16010 // Retrieves all the rendered segment objects for the view 16011 16012 getEventSegs: function() { 16013 16014 // subclasses must implement 16015 16016 return []; 16017 16018 }, 16019 16020 16021 16022 16023 16024 /* Event Drag-n-Drop 16025 16026 ------------------------------------------------------------------------------------------------------------------*/ 16027 16028 16029 16030 16031 16032 // Computes if the given event is allowed to be dragged by the user 16033 16034 isEventDraggable: function(event) { 16035 16036 var source = event.source || {}; 16037 16038 16039 16040 return firstDefined( 16041 16042 event.startEditable, 16043 16044 source.startEditable, 16045 16046 this.opt('eventStartEditable'), 16047 16048 event.editable, 16049 16050 source.editable, 16051 16052 this.opt('editable') 16053 16054 ); 16055 16056 }, 16057 16058 16059 16060 16061 16062 // Must be called when an event in the view is dropped onto new location. 16063 16064 // `dropLocation` is an object that contains the new zoned start/end/allDay values for the event. 16065 16066 reportEventDrop: function(event, dropLocation, largeUnit, el, ev) { 16067 16068 var calendar = this.calendar; 16069 16070 var mutateResult = calendar.mutateEvent(event, dropLocation, largeUnit); 16071
16072 var undoFunc = function() { 16073 16074 mutateResult.undo(); 16075 16076 calendar.reportEventChange(); 16077 16078 }; 16079 16080 16081 16082 this.triggerEventDrop(event, mutateResult.dateDelta, undoFunc, el, ev); 16083 16084 calendar.reportEventChange(); // will rerender events 16085 16086 }, 16087 16088 16089 16090 16091 16092 // Triggers event-drop handlers that have subscribed via the API 16093 16094 triggerEventDrop: function(event, dateDelta, undoFunc, el, ev) { 16095 16096 this.trigger('eventDrop', el[0], event, dateDelta, undoFunc, ev, {}); // {} = jqui dummy 16097 16098 }, 16099 16100 16101 16102 16103 16104 /* External Element Drag-n-Drop 16105 16106 ------------------------------------------------------------------------------------------------------------------*/ 16107 16108 16109 16110 16111 16112 // Must be called when an external element, via jQuery UI, has been dropped onto the calendar. 16113 16114 // `meta` is the parsed data that has been embedded into the dragging event. 16115 16116 // `dropLocation` is an object that contains the new zoned start/end/allDay values for the event. 16117 16118 reportExternalDrop: function(meta, dropLocation, el, ev, ui) { 16119 16120 var eventProps = meta.eventProps; 16121 16122 var eventInput; 16123 16124 var event; 16125 16126 16127 16128 // Try to build an event object and render it. TODO: decouple the two 16129 16130 if (eventProps) { 16131 16132 eventInput = $.extend({}, eventProps, dropLocation); 16133 16134 event = this.calendar.renderEvent(eventInput, meta.stick)[0]; // renderEvent returns an array 16135 16136 } 16137 16138 16139 16140 this.triggerExternalDrop(event, dropLocation, el, ev, ui); 16141 16142 }, 16143 16144 16145 16146 16147 16148 // Triggers external-drop handlers that have subscribed via the API 16149 16150 triggerExternalDrop: function(event, dropLocation, el, ev, ui) { 16151 16152 16153 16154 // trigger 'drop' regardless of whether element represents an event 16155 16156 this.trigger('drop', el[0], dropLocation.start, ev, ui); 16157 16158 16159 16160 if (event) { 16161 16162 this.trigger('eventReceive', null, event); // signal an external event landed 16163 16164 } 16165 16166 }, 16167 16168 16169 16170 16171 16172 /* Drag-n-Drop Rendering (for both events and external elements) 16173 16174 ------------------------------------------------------------------------------------------------------------------*/ 16175 16176 16177 16178 16179 16180 // Renders a visual indication of a event or external-element drag over the given drop zone. 16181 16182 // If an external-element, seg will be `null` 16183 16184 renderDrag: function(dropLocation, seg) { 16185 16186 // subclasses must implement 16187 16188 }, 16189 16190 16191 16192 16193 16194 // Unrenders a visual indication of an event or external-element being dragged. 16195 16196 unrenderDrag: function() { 16197 16198 // subclasses must implement 16199 16200 }, 16201 16202 16203 16204 16205 16206 /* Event Resizing 16207 16208 ------------------------------------------------------------------------------------------------------------------*/ 16209 16210 16211 16212 16213 16214 // Computes if the given event is allowed to be resized from its starting edge 16215 16216 isEventResizableFromStart: function(event) { 16217 16218 return this.opt('eventResizableFromStart') && this.isEventResizable(event); 16219 16220 }, 16221 16222 16223 16224 16225 16226 // Computes if the given event is allowed to be resized from its ending edge 16227 16228 isEventResizableFromEnd: function(event) { 16229 16230 return this.isEventResizable(event); 16231 16232 }, 16233 16234 16235 16236 16237 16238 // Computes if the given event is allowed to be resized by the user at all 16239 16240 isEventResizable: function(event) { 16241 16242 var source = event.source || {}; 16243 16244 16245 16246 return firstDefined( 16247 16248 event.durationEditable, 16249 16250 source.durationEditable, 16251 16252 this.opt('eventDurationEditable'), 16253 16254 event.editable, 16255 16256 source.editable, 16257 16258 this.opt('editable') 16259 16260 ); 16261 16262 }, 16263 16264 16265 16266 16267 16268 // Must be called when an event in the view has been resized to a new length 16269 16270 reportEventResize: function(event, resizeLocation, largeUnit, el, ev) { 16271 16272 var calendar = this.calendar; 16273 16274 var mutateResult = calendar.mutateEvent(event, resizeLocation, largeUnit); 16275 16276 var undoFunc = function() { 16277 16278 mutateResult.undo(); 16279 16280 calendar.reportEventChange(); 16281 16282 }; 16283 16284 16285 16286 this.triggerEventResize(event, mutateResult.durationDelta, undoFunc, el, ev); 16287 16288 calendar.reportEventChange(); // will rerender events 16289 16290 }, 16291 16292 16293 16294 16295 16296 // Triggers event-resize handlers that have subscribed via the API 16297 16298 triggerEventResize: function(event, durationDelta, undoFunc, el, ev) { 16299 16300 this.trigger('eventResize', el[0], event, durationDelta, undoFunc, ev, {}); // {} = jqui dummy 16301 16302 }, 16303 16304 16305 16306 16307 16308 /* Selection 16309 16310 ------------------------------------------------------------------------------------------------------------------*/ 16311 16312 16313 16314 16315 16316 // Selects a date span on the view. `start` and `end` are both Moments. 16317 16318 // `ev` is the native mouse event that begin the interaction. 16319 16320 select: function(span, ev) { 16321 16322 this.unselect(ev); 16323 16324 this.renderSelection(span); 16325 16326 this.reportSelection(span, ev); 16327 16328 }, 16329 16330 16331 16332 16333 16334 // Renders a visual indication of the selection 16335 16336 renderSelection: function(span) { 16337 16338 // subclasses should implement 16339 16340 }, 16341 16342 16343 16344 16345 16346 // Called when a new selection is made. Updates internal state and triggers handlers. 16347 16348 reportSelection: function(span, ev) { 16349 16350 this.isSelected = true; 16351 16352 this.triggerSelect(span, ev); 16353 16354 }, 16355 16356 16357 16358 16359 16360 // Triggers handlers to 'select' 16361 16362 triggerSelect: function(span, ev) { 16363 16364 this.trigger( 16365 16366 'select', 16367 16368 null, 16369 16370 this.calendar.applyTimezone(span.start), // convert to calendar's tz for external API 16371 16372 this.calendar.applyTimezone(span.end), // " 16373 16374 ev 16375 16376 ); 16377 16378 }, 16379 16380 16381 16382 16383 16384 // Undoes a selection. updates in the internal state and triggers handlers. 16385 16386 // `ev` is the native mouse event that began the interaction. 16387 16388 unselect: function(ev) { 16389 16390 if (this.isSelected) { 16391 16392 this.isSelected = false;
16393 16394 if (this.destroySelection) { 16395 16396 this.destroySelection(); // TODO: deprecate 16397 16398 } 16399 16400 this.unrenderSelection(); 16401 16402 this.trigger('unselect', null, ev); 16403 16404 } 16405 16406 }, 16407 16408 16409 16410 16411 16412 // Unrenders a visual indication of selection 16413 16414 unrenderSelection: function() { 16415 16416 // subclasses should implement 16417 16418 }, 16419 16420 16421 16422 16423 16424 // Handler for unselecting when the user clicks something and the 'unselectAuto' setting is on 16425 16426 documentMousedown: function(ev) { 16427 16428 var ignore; 16429 16430 16431 16432 // is there a selection, and has the user made a proper left click? 16433 16434 if (this.isSelected && this.opt('unselectAuto') && isPrimaryMouseButton(ev)) { 16435 16436 16437 16438 // only unselect if the clicked element is not identical to or inside of an 'unselectCancel' element 16439 16440 ignore = this.opt('unselectCancel'); 16441 16442 if (!ignore || !$(ev.target).closest(ignore).length) { 16443 16444 this.unselect(ev); 16445 16446 } 16447 16448 } 16449 16450 }, 16451 16452 16453 16454 16455 16456 /* Day Click 16457 16458 ------------------------------------------------------------------------------------------------------------------*/ 16459 16460 16461 16462 16463 16464 // Triggers handlers to 'dayClick' 16465 16466 // Span has start/end of the clicked area. Only the start is useful. 16467 16468 triggerDayClick: function(span, dayEl, ev) { 16469 16470 this.trigger( 16471 16472 'dayClick', 16473 16474 dayEl, 16475 16476 this.calendar.applyTimezone(span.start), // convert to calendar's timezone for external API 16477 16478 ev 16479 16480 ); 16481 16482 }, 16483 16484 16485 16486 16487 16488 /* Date Utils 16489 16490 ------------------------------------------------------------------------------------------------------------------*/ 16491 16492 16493 16494 16495 16496 // Initializes internal variables related to calculating hidden days-of-week 16497 16498 initHiddenDays: function() { 16499 16500 var hiddenDays = this.opt('hiddenDays') || []; // array of day-of-week indices that are hidden 16501 16502 var isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool) 16503 16504 var dayCnt = 0; 16505 16506 var i; 16507 16508 16509 16510 if (this.opt('weekends') === false) { 16511 16512 hiddenDays.push(0, 6); // 0=sunday, 6=saturday 16513 16514 } 16515 16516 16517 16518 for (i = 0; i < 7; i++) { 16519 16520 if ( 16521 16522 !(isHiddenDayHash[i] = $.inArray(i, hiddenDays) !== -1) 16523 16524 ) { 16525 16526 dayCnt++; 16527 16528 } 16529 16530 } 16531 16532 16533 16534 if (!dayCnt) { 16535 16536 throw 'invalid hiddenDays'; // all days were hidden? bad. 16537 16538 } 16539 16540 16541 16542 this.isHiddenDayHash = isHiddenDayHash; 16543 16544 }, 16545 16546 16547 16548 16549 16550 // Is the current day hidden? 16551 16552 // `day` is a day-of-week index (0-6), or a Moment 16553 16554 isHiddenDay: function(day) { 16555 16556 if (moment.isMoment(day)) { 16557 16558 day = day.day(); 16559 16560 } 16561 16562 return this.isHiddenDayHash[day]; 16563 16564 }, 16565 16566 16567 16568 16569 16570 // Incrementing the current day until it is no longer a hidden day, returning a copy. 16571 16572 // If the initial value of `date` is not a hidden day, don't do anything. 16573 16574 // Pass `isExclusive` as `true` if you are dealing with an end date. 16575 16576 // `inc` defaults to `1` (increment one day forward each time) 16577 16578 skipHiddenDays: function(date, inc, isExclusive) { 16579 16580 var out = date.clone(); 16581 16582 inc = inc || 1; 16583 16584 while ( 16585 16586 this.isHiddenDayHash[(out.day() + (isExclusive ? inc : 0) + 7) % 7] 16587 16588 ) { 16589 16590 out.add(inc, 'days'); 16591 16592 } 16593 16594 return out; 16595 16596 }, 16597 16598 16599 16600 16601 16602 // Returns the date range of the full days the given range visually appears to occupy. 16603 16604 // Returns a new range object. 16605 16606 computeDayRange: function(range) { 16607 16608 var startDay = range.start.clone().stripTime(); // the beginning of the day the range starts 16609 16610 var end = range.end; 16611 16612 var endDay = null; 16613 16614 var endTimeMS; 16615 16616 16617 16618 if (end) { 16619 16620 endDay = end.clone().stripTime(); // the beginning of the day the range exclusively ends 16621 16622 endTimeMS = +end.time(); // # of milliseconds into `endDay` 16623 16624 16625 16626 // If the end time is actually inclusively part of the next day and is equal to or 16627 16628 // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`. 16629 16630 // Otherwise, leaving it as inclusive will cause it to exclude `endDay`. 16631 16632 if (endTimeMS && endTimeMS >= this.nextDayThreshold) { 16633 16634 endDay.add(1, 'days'); 16635 16636 } 16637 16638 } 16639 16640 16641 16642 // If no end was specified, or if it is within `startDay` but not past nextDayThreshold, 16643 16644 // assign the default duration of one day. 16645 16646 if (!end || endDay <= startDay) { 16647 16648 endDay = startDay.clone().add(1, 'days'); 16649 16650 } 16651 16652 16653 16654 return { start: startDay, end: endDay }; 16655 16656 }, 16657 16658 16659 16660 16661 16662 // Does the given event visually appear to occupy more than one day? 16663 16664 isMultiDayEvent: function(event) { 16665 16666 var range = this.computeDayRange(event); // event is range-ish 16667 16668 16669 16670 return range.end.diff(range.start, 'days') > 1; 16671 16672 } 16673 16674 16675 16676 }); 16677 16678 16679 16680 ;; 16681 16682 16683 16684 var Calendar = FC.Calendar = Class.extend({ 16685 16686 16687
16688 dirDefaults: null, // option defaults related to LTR or RTL 16689 16690 langDefaults: null, // option defaults related to current locale 16691 16692 overrides: null, // option overrides given to the fullCalendar constructor 16693 16694 options: null, // all defaults combined with overrides 16695 16696 viewSpecCache: null, // cache of view definitions 16697 16698 view: null, // current View object 16699 16700 header: null, 16701 16702 loadingLevel: 0, // number of simultaneous loading tasks 16703 16704 16705 16706 16707 16708 // a lot of this class' OOP logic is scoped within this constructor function, 16709 16710 // but in the future, write individual methods on the prototype. 16711 16712 constructor: Calendar_constructor, 16713 16714 16715 16716 16717 16718 // Subclasses can override this for initialization logic after the constructor has been called 16719 16720 initialize: function() { 16721 16722 }, 16723 16724 16725 16726 16727 16728 // Initializes `this.options` and other important options-related objects 16729 16730 initOptions: function(overrides) { 16731 16732 var lang, langDefaults; 16733 16734 var isRTL, dirDefaults; 16735 16736 16737 16738 // converts legacy options into non-legacy ones. 16739 16740 // in the future, when this is removed, don't use `overrides` reference. make a copy. 16741 16742 overrides = massageOverrides(overrides); 16743 16744 16745 16746 lang = overrides.lang; 16747 16748 langDefaults = langOptionHash[lang]; 16749 16750 if (!langDefaults) { 16751 16752 lang = Calendar.defaults.lang; 16753 16754 langDefaults = langOptionHash[lang] || {}; 16755 16756 } 16757 16758 16759 16760 isRTL = firstDefined( 16761 16762 overrides.isRTL, 16763 16764 langDefaults.isRTL, 16765 16766 Calendar.defaults.isRTL 16767 16768 ); 16769 16770 dirDefaults = isRTL ? Calendar.rtlDefaults : {}; 16771 16772 16773 16774 this.dirDefaults = dirDefaults; 16775 16776 this.langDefaults = langDefaults; 16777 16778 this.overrides = overrides; 16779 16780 this.options = mergeOptions([ // merge defaults and overrides. lowest to highest precedence 16781 16782 Calendar.defaults, // global defaults 16783 16784 dirDefaults, 16785 16786 langDefaults, 16787 16788 overrides 16789 16790 ]); 16791 16792 populateInstanceComputableOptions(this.options); 16793 16794 16795 16796 this.viewSpecCache = {}; // somewhat unrelated 16797 16798 }, 16799 16800 16801 16802 16803 16804 // Gets information about how to create a view. Will use a cache. 16805 16806 getViewSpec: function(viewType) { 16807 16808 var cache = this.viewSpecCache; 16809 16810 16811 16812 return cache[viewType] || (cache[viewType] = this.buildViewSpec(viewType)); 16813 16814 }, 16815 16816 16817 16818 16819 16820 // Given a duration singular unit, like "week" or "day", finds a matching view spec. 16821 16822 // Preference is given to views that have corresponding buttons. 16823 16824 getUnitViewSpec: function(unit) { 16825 16826 var viewTypes; 16827 16828 var i; 16829 16830 var spec; 16831 16832 16833 16834 if ($.inArray(unit, intervalUnits) != -1) { 16835 16836 16837 16838 // put views that have buttons first. there will be duplicates, but oh well 16839 16840 viewTypes = this.header.getViewsWithButtons(); 16841 16842 $.each(FC.views, function(viewType) { // all views 16843 16844 viewTypes.push(viewType); 16845 16846 }); 16847 16848 16849 16850 for (i = 0; i < viewTypes.length; i++) { 16851 16852 spec = this.getViewSpec(viewTypes[i]); 16853 16854 if (spec) { 16855 16856 if (spec.singleUnit == unit) { 16857 16858 return spec; 16859 16860 } 16861 16862 } 16863 16864 } 16865 16866 } 16867 16868 }, 16869 16870 16871 16872 16873 16874 // Builds an object with information on how to create a given view 16875 16876 buildViewSpec: function(requestedViewType) { 16877 16878 var viewOverrides = this.overrides.views || {}; 16879 16880 var specChain = []; // for the view. lowest to highest priority 16881 16882 var defaultsChain = []; // for the view. lowest to highest priority 16883 16884 var overridesChain = []; // for the view. lowest to highest priority 16885 16886 var viewType = requestedViewType; 16887 16888 var spec; // for the view 16889 16890 var overrides; // for the view 16891 16892 var duration; 16893 16894 var unit; 16895 16896 16897 16898 // iterate from the specific view definition to a more general one until we hit an actual View class 16899 16900 while (viewType) { 16901 16902 spec = fcViews[viewType]; 16903 16904 overrides = viewOverrides[viewType]; 16905 16906 viewType = null; // clear. might repopulate for another iteration 16907 16908 16909 16910 if (typeof spec === 'function') { // TODO: deprecate 16911 16912 spec = { 'class': spec }; 16913 16914 } 16915 16916 16917 16918 if (spec) { 16919 16920 specChain.unshift(spec); 16921 16922 defaultsChain.unshift(spec.defaults || {}); 16923 16924 duration = duration || spec.duration; 16925 16926 viewType = viewType || spec.type; 16927 16928 } 16929 16930 16931 16932 if (overrides) { 16933 16934 overridesChain.unshift(overrides); // view-specific option hashes have options at zero-level 16935 16936 duration = duration || overrides.duration; 16937 16938 viewType = viewType || overrides.type; 16939 16940 } 16941 16942 } 16943 16944 16945 16946 spec = mergeProps(specChain); 16947 16948 spec.type = requestedViewType; 16949 16950 if (!spec['class']) { 16951 16952 return false;
16953 16954 } 16955 16956 16957 16958 if (duration) { 16959 16960 duration = moment.duration(duration); 16961 16962 if (duration.valueOf()) { // valid? 16963 16964 spec.duration = duration; 16965 16966 unit = computeIntervalUnit(duration); 16967 16968 16969 16970 // view is a single-unit duration, like "week" or "day" 16971 16972 // incorporate options for this. lowest priority 16973 16974 if (duration.as(unit) === 1) { 16975 16976 spec.singleUnit = unit; 16977 16978 overridesChain.unshift(viewOverrides[unit] || {}); 16979 16980 } 16981 16982 } 16983 16984 } 16985 16986 16987 16988 spec.defaults = mergeOptions(defaultsChain); 16989 16990 spec.overrides = mergeOptions(overridesChain); 16991 16992 16993 16994 this.buildViewSpecOptions(spec); 16995 16996 this.buildViewSpecButtonText(spec, requestedViewType); 16997 16998 16999 17000 return spec; 17001 17002 }, 17003 17004 17005 17006 17007 17008 // Builds and assigns a view spec's options object from its already-assigned defaults and overrides 17009 17010 buildViewSpecOptions: function(spec) { 17011 17012 spec.options = mergeOptions([ // lowest to highest priority 17013 17014 Calendar.defaults, // global defaults 17015 17016 spec.defaults, // view's defaults (from ViewSubclass.defaults) 17017 17018 this.dirDefaults, 17019 17020 this.langDefaults, // locale and dir take precedence over view's defaults! 17021 17022 this.overrides, // calendar's overrides (options given to constructor) 17023 17024 spec.overrides // view's overrides (view-specific options) 17025 17026 ]); 17027 17028 populateInstanceComputableOptions(spec.options); 17029 17030 }, 17031 17032 17033 17034 17035 17036 // Computes and assigns a view spec's buttonText-related options 17037 17038 buildViewSpecButtonText: function(spec, requestedViewType) { 17039 17040 17041 17042 // given an options object with a possible `buttonText` hash, lookup the buttonText for the 17043 17044 // requested view, falling back to a generic unit entry like "week" or "day" 17045 17046 function queryButtonText(options) { 17047 17048 var buttonText = options.buttonText || {}; 17049 17050 return buttonText[requestedViewType] || 17051 17052 (spec.singleUnit ? buttonText[spec.singleUnit] : null); 17053 17054 } 17055 17056 17057 17058 // highest to lowest priority 17059 17060 spec.buttonTextOverride = 17061 17062 queryButtonText(this.overrides) || // constructor-specified buttonText lookup hash takes precedence 17063 17064 spec.overrides.buttonText; // `buttonText` for view-specific options is a string 17065 17066 17067 17068 // highest to lowest priority. mirrors buildViewSpecOptions 17069 17070 spec.buttonTextDefault = 17071 17072 queryButtonText(this.langDefaults) || 17073 17074 queryButtonText(this.dirDefaults) || 17075 17076 spec.defaults.buttonText || // a single string. from ViewSubclass.defaults 17077 17078 queryButtonText(Calendar.defaults) || 17079 17080 (spec.duration ? this.humanizeDuration(spec.duration) : null) || // like "3 days" 17081 17082 requestedViewType; // fall back to given view name 17083 17084 }, 17085 17086 17087 17088 17089 17090 // Given a view name for a custom view or a standard view, creates a ready-to-go View object 17091 17092 instantiateView: function(viewType) { 17093 17094 var spec = this.getViewSpec(viewType); 17095 17096 17097 17098 return new spec['class'](this, viewType, spec.options, spec.duration); 17099 17100 }, 17101 17102 17103 17104 17105 17106 // Returns a boolean about whether the view is okay to instantiate at some point 17107 17108 isValidViewType: function(viewType) { 17109 17110 return Boolean(this.getViewSpec(viewType)); 17111 17112 }, 17113 17114 17115 17116 17117 17118 // Should be called when any type of async data fetching begins 17119 17120 pushLoading: function() { 17121 17122 if (!(this.loadingLevel++)) { 17123 17124 this.trigger('loading', null, true, this.view); 17125 17126 } 17127 17128 }, 17129 17130 17131 17132 17133 17134 // Should be called when any type of async data fetching completes 17135 17136 popLoading: function() { 17137 17138 if (!(--this.loadingLevel)) { 17139 17140 this.trigger('loading', null, false, this.view); 17141 17142 } 17143 17144 }, 17145 17146 17147 17148 17149 17150 // Given arguments to the select method in the API, returns a span (unzoned start/end and other info) 17151 17152 buildSelectSpan: function(zonedStartInput, zonedEndInput) { 17153 17154 var start = this.moment(zonedStartInput).stripZone(); 17155 17156 var end; 17157 17158 17159 17160 if (zonedEndInput) { 17161 17162 end = this.moment(zonedEndInput).stripZone(); 17163 17164 } 17165 17166 else if (start.hasTime()) { 17167 17168 end = start.clone().add(this.defaultTimedEventDuration); 17169 17170 } 17171 17172 else { 17173 17174 end = start.clone().add(this.defaultAllDayEventDuration); 17175 17176 } 17177 17178 17179 17180 return { start: start, end: end }; 17181 17182 } 17183 17184 17185 17186 }); 17187 17188 17189 17190 17191 17192 Calendar.mixin(Emitter); 17193 17194 17195 17196 17197 17198 function Calendar_constructor(element, overrides) { 17199 17200 var t = this; 17201 17202 17203 17204 17205 17206 t.initOptions(overrides || {}); 17207 17208 var options = this.options; 17209 17210 17211 17212 17213 17214 // Exports 17215 17216 // ----------------------------------------------------------------------------------- 17217 17218 17219 17220 t.render = render; 17221 17222 t.destroy = destroy; 17223 17224 t.refetchEvents = refetchEvents; 17225 17226 t.reportEvents = reportEvents; 17227 17228 t.reportEventChange = reportEventChange; 17229 17230 t.rerenderEvents = renderEvents; // `renderEvents` serves as a rerender. an API method 17231 17232 t.changeView = renderView; // `renderView` will switch to another view 17233 17234 t.select = select; 17235 17236 t.unselect = unselect; 17237 17238 t.prev = prev; 17239 17240 t.next = next; 17241 17242 t.prevYear = prevYear; 17243 17244 t.nextYear = nextYear; 17245 17246 t.today = today; 17247 17248 t.gotoDate = gotoDate; 17249 17250 t.incrementDate = incrementDate; 17251 17252 t.zoomTo = zoomTo; 17253 17254 t.getDate = getDate; 17255 17256 t.getCalendar = getCalendar; 17257 17258 t.getView = getView; 17259 17260 t.option = option; 17261 17262 t.trigger = trigger; 17263 17264 17265 17266 17267 17268 17269 17270 // Language-data Internals 17271 17272 // ----------------------------------------------------------------------------------- 17273 17274 // Apply overrides to the current language's data 17275 17276 17277 17278 17279 17280 var localeData = createObject( // make a cheap copy 17281 17282 getMomentLocaleData(options.lang) // will fall back to en 17283 17284 ); 17285 17286 17287 17288 if (options.monthNames) { 17289 17290 localeData._months = options.monthNames; 17291 17292 } 17293 17294 if (options.monthNamesShort) { 17295 17296 localeData._monthsShort = options.monthNamesShort; 17297 17298 } 17299 17300 if (options.dayNames) { 17301 17302 localeData._weekdays = options.dayNames; 17303 17304 } 17305 17306 if (options.dayNamesShort) { 17307 17308 localeData._weekdaysShort = options.dayNamesShort; 17309 17310 } 17311 17312 if (options.firstDay != null) { 17313 17314 var _week = createObject(localeData._week); // _week: { dow: # } 17315 17316 _week.dow = options.firstDay; 17317 17318 localeData._week = _week; 17319 17320 } 17321 17322 17323 17324 // assign a normalized value, to be used by our .week() moment extension 17325 17326 localeData._fullCalendar_weekCalc = (function(weekCalc) { 17327 17328 if (typeof weekCalc === 'function') { 17329 17330 return weekCalc; 17331 17332 } 17333 17334 else if (weekCalc === 'local') { 17335 17336 return weekCalc; 17337 17338 } 17339 17340 else if (weekCalc === 'iso' || weekCalc === 'ISO') { 17341 17342 return 'ISO'; 17343 17344 } 17345 17346 })(options.weekNumberCalculation); 17347 17348 17349 17350 17351 17352 17353 17354 // Calendar-specific Date Utilities 17355 17356 // ----------------------------------------------------------------------------------- 17357 17358 17359 17360 17361 17362 t.defaultAllDayEventDuration = moment.duration(options.defaultAllDayEventDuration); 17363 17364 t.defaultTimedEventDuration = moment.duration(options.defaultTimedEventDuration); 17365 17366 17367 17368 17369 17370 // Builds a moment using the settings of the current calendar: timezone and language. 17371 17372 // Accepts anything the vanilla moment() constructor accepts. 17373 17374 t.moment = function() { 17375 17376 var mom; 17377 17378 17379 17380 if (options.timezone === 'local') { 17381 17382 mom = FC.moment.apply(null, arguments); 17383 17384 17385 17386 // Force the moment to be local, because FC.moment doesn't guarantee it. 17387 17388 if (mom.hasTime()) { // don't give ambiguously-timed moments a local zone 17389 17390 mom.local(); 17391 17392 } 17393 17394 } 17395 17396 else if (options.timezone === 'UTC') { 17397 17398 mom = FC.moment.utc.apply(null, arguments); // process as UTC 17399 17400 } 17401 17402 else { 17403 17404 mom = FC.moment.parseZone.apply(null, arguments); // let the input decide the zone 17405 17406 } 17407 17408 17409 17410 if ('_locale' in mom) { // moment 2.8 and above 17411 17412 mom._locale = localeData; 17413 17414 } 17415 17416 else { // pre-moment-2.8 17417 17418 mom._lang = localeData; 17419 17420 } 17421 17422 17423 17424 return mom; 17425 17426 }; 17427 17428 17429 17430 17431 17432 // Returns a boolean about whether or not the calendar knows how to calculate 17433 17434 // the timezone offset of arbitrary dates in the current timezone. 17435 17436 t.getIsAmbigTimezone = function() { 17437 17438 return options.timezone !== 'local' && options.timezone !== 'UTC'; 17439 17440 }; 17441 17442 17443 17444 17445 17446 // Returns a copy of the given date in the current timezone. Has no effect on dates without times. 17447 17448 t.applyTimezone = function(date) { 17449 17450 if (!date.hasTime()) { 17451 17452 return date.clone(); 17453 17454 } 17455 17456 17457 17458 var zonedDate = t.moment(date.toArray()); 17459 17460 var timeAdjust = date.time() - zonedDate.time(); 17461 17462 var adjustedZonedDate; 17463 17464 17465 17466 // Safari sometimes has problems with this coersion when near DST. Adjust if necessary. (bug #2396) 17467 17468 if (timeAdjust) { // is the time result different than expected? 17469 17470 adjustedZonedDate = zonedDate.clone().add(timeAdjust); // add milliseconds 17471 17472 if (date.time() - adjustedZonedDate.time() === 0) { // does it match perfectly now? 17473 17474 zonedDate = adjustedZonedDate; 17475 17476 } 17477 17478 } 17479 17480 17481 17482 return zonedDate; 17483 17484 }; 17485 17486 17487 17488 17489 17490 // Returns a moment for the current date, as defined by the client's computer or from the `now` option. 17491 17492 // Will return an moment with an ambiguous timezone. 17493 17494 t.getNow = function() { 17495 17496 var now = options.now; 17497 17498 if (typeof now === 'function') { 17499 17500 now = now(); 17501 17502 } 17503 17504 return t.moment(now).stripZone(); 17505 17506 }; 17507 17508 17509 17510 17511 17512 // Get an event's normalized end date. If not present, calculate it from the defaults. 17513 17514 t.getEventEnd = function(event) { 17515
17516 if (event.end) { 17517 17518 return event.end.clone(); 17519 17520 } 17521 17522 else { 17523 17524 return t.getDefaultEventEnd(event.allDay, event.start); 17525 17526 } 17527 17528 }; 17529 17530 17531 17532 17533 17534 // Given an event's allDay status and start date, return what its fallback end date should be. 17535 17536 // TODO: rename to computeDefaultEventEnd 17537 17538 t.getDefaultEventEnd = function(allDay, zonedStart) { 17539 17540 var end = zonedStart.clone(); 17541 17542 17543 17544 if (allDay) { 17545 17546 end.stripTime().add(t.defaultAllDayEventDuration); 17547 17548 } 17549 17550 else { 17551 17552 end.add(t.defaultTimedEventDuration); 17553 17554 } 17555 17556 17557 17558 if (t.getIsAmbigTimezone()) { 17559 17560 end.stripZone(); // we don't know what the tzo should be 17561 17562 } 17563 17564 17565 17566 return end; 17567 17568 }; 17569 17570 17571 17572 17573 17574 // Produces a human-readable string for the given duration. 17575 17576 // Side-effect: changes the locale of the given duration. 17577 17578 t.humanizeDuration = function(duration) { 17579 17580 return (duration.locale || duration.lang).call(duration, options.lang) // works moment-pre-2.8 17581 17582 .humanize(); 17583 17584 }; 17585 17586 17587 17588 17589 17590 17591 17592 // Imports 17593 17594 // ----------------------------------------------------------------------------------- 17595 17596 17597 17598 17599 17600 EventManager.call(t, options); 17601 17602 var isFetchNeeded = t.isFetchNeeded; 17603 17604 var fetchEvents = t.fetchEvents; 17605 17606 17607 17608 17609 17610 17611 17612 // Locals 17613 17614 // ----------------------------------------------------------------------------------- 17615 17616 17617 17618 17619 17620 var _element = element[0]; 17621 17622 var header; 17623 17624 var headerElement; 17625 17626 var content; 17627 17628 var tm; // for making theme classes 17629 17630 var currentView; // NOTE: keep this in sync with this.view 17631 17632 var viewsByType = {}; // holds all instantiated view instances, current or not 17633 17634 var suggestedViewHeight; 17635 17636 var windowResizeProxy; // wraps the windowResize function 17637 17638 var ignoreWindowResize = 0; 17639 17640 var events = []; 17641 17642 var date; // unzoned 17643 17644 17645 17646 17647 17648 17649 17650 // Main Rendering 17651 17652 // ----------------------------------------------------------------------------------- 17653 17654 17655 17656 17657 17658 // compute the initial ambig-timezone date 17659 17660 if (options.defaultDate != null) { 17661 17662 date = t.moment(options.defaultDate).stripZone(); 17663 17664 } 17665 17666 else { 17667 17668 date = t.getNow(); // getNow already returns unzoned 17669 17670 } 17671 17672 17673 17674 17675 17676 function render() { 17677 17678 if (!content) { 17679 17680 initialRender(); 17681 17682 } 17683 17684 else if (elementVisible()) { 17685 17686 // mainly for the public API 17687 17688 calcSize(); 17689 17690 renderView(); 17691 17692 } 17693 17694 } 17695 17696 17697 17698 17699 17700 function initialRender() { 17701 17702 tm = options.theme ? 'ui' : 'fc'; 17703 17704 element.addClass('fc'); 17705 17706 17707 17708 if (options.isRTL) { 17709 17710 element.addClass('fc-rtl'); 17711 17712 } 17713 17714 else { 17715 17716 element.addClass('fc-ltr'); 17717 17718 } 17719 17720 17721 17722 if (options.theme) { 17723 17724 element.addClass('ui-widget'); 17725 17726 } 17727 17728 else { 17729 17730 element.addClass('fc-unthemed'); 17731 17732 } 17733 17734 17735 17736 content = $("<div class='fc-view-container'/>").prependTo(element); 17737 17738 17739 17740 header = t.header = new Header(t, options); 17741 17742 headerElement = header.render(); 17743 17744 if (headerElement) { 17745 17746 element.prepend(headerElement); 17747 17748 } 17749 17750 17751 17752 renderView(options.defaultView); 17753 17754 17755 17756 if (options.handleWindowResize) { 17757 17758 windowResizeProxy = debounce(windowResize, options.windowResizeDelay); // prevents rapid calls 17759 17760 $(window).resize(windowResizeProxy); 17761 17762 } 17763 17764 } 17765 17766 17767 17768 17769 17770 function destroy() { 17771 17772 17773 17774 if (currentView) { 17775 17776 currentView.removeElement(); 17777 17778 17779 17780 // NOTE: don't null-out currentView/t.view in case API methods are called after destroy. 17781 17782 // It is still the "current" view, just not rendered. 17783 17784 } 17785 17786 17787 17788 header.removeElement(); 17789 17790 content.remove(); 17791 17792 element.removeClass('fc fc-ltr fc-rtl fc-unthemed ui-widget'); 17793 17794 17795 17796 if (windowResizeProxy) { 17797 17798 $(window).unbind('resize', windowResizeProxy); 17799 17800 } 17801 17802 } 17803 17804 17805 17806 17807 17808 function elementVisible() { 17809 17810 return element.is(':visible'); 17811 17812 } 17813 17814 17815 17816 17817 17818 17819 17820 // View Rendering 17821 17822 // ----------------------------------------------------------------------------------- 17823 17824 17825 17826 17827 17828 // Renders a view because of a date change, view-type change, or for the first time. 17829 17830 // If not given a viewType, keep the current view but render different dates. 17831 17832 function renderView(viewType) { 17833 17834 ignoreWindowResize++; 17835 17836 17837 17838 // if viewType is changing, remove the old view's rendering 17839 17840 if (currentView && viewType && currentView.type !== viewType) { 17841 17842 header.deactivateButton(currentView.type); 17843 17844 freezeContentHeight(); // prevent a scroll jump when view element is removed 17845 17846 currentView.removeElement(); 17847 17848 currentView = t.view = null; 17849 17850 } 17851 17852 17853 17854 // if viewType changed, or the view was never created, create a fresh view 17855 17856 if (!currentView && viewType) { 17857 17858 currentView = t.view = 17859 17860 viewsByType[viewType] || 17861 17862 (viewsByType[viewType] = t.instantiateView(viewType)); 17863 17864 17865 17866 currentView.setElement( 17867 17868 $("<div class='fc-view fc-" + viewType + "-view' />").appendTo(content) 17869 17870 ); 17871 17872 header.activateButton(viewType); 17873 17874 } 17875 17876 17877 17878 if (currentView) { 17879 17880 17881 17882 // in case the view should render a period of time that is completely hidden 17883 17884 date = currentView.massageCurrentDate(date); 17885 17886 17887 17888 // render or rerender the view 17889 17890 if ( 17891 17892 !currentView.displaying || 17893 17894 !date.isWithin(currentView.intervalStart, currentView.intervalEnd) // implicit date window change 17895 17896 ) { 17897 17898 if (elementVisible()) { 17899 17900 17901 17902 currentView.display(date); // will call freezeContentHeight 17903 17904 unfreezeContentHeight(); // immediately unfreeze regardless of whether display is async 17905 17906 17907 17908 // need to do this after View::render, so dates are calculated 17909 17910 updateHeaderTitle(); 17911 17912 updateTodayButton(); 17913 17914 17915 17916 getAndRenderEvents(); 17917 17918 } 17919 17920 } 17921 17922 } 17923 17924 17925 17926 unfreezeContentHeight(); // undo any lone freezeContentHeight calls 17927 17928 ignoreWindowResize--; 17929 17930 } 17931 17932 17933 17934 17935 17936 17937 17938 // Resizing 17939 17940 // ----------------------------------------------------------------------------------- 17941 17942 17943 17944 17945 17946 t.getSuggestedViewHeight = function() { 17947 17948 if (suggestedViewHeight === undefined) { 17949 17950 calcSize(); 17951 17952 } 17953 17954 return suggestedViewHeight; 17955 17956 }; 17957 17958 17959 17960 17961 17962 t.isHeightAuto = function() { 17963 17964 return options.contentHeight === 'auto' || options.height === 'auto'; 17965 17966 }; 17967 17968 17969 17970 17971 17972 function updateSize(shouldRecalc) { 17973 17974 if (elementVisible()) { 17975 17976 17977 17978 if (shouldRecalc) { 17979 17980 _calcSize(); 17981 17982 } 17983 17984 17985 17986 ignoreWindowResize++; 17987 17988 currentView.updateSize(true); // isResize=true. will poll getSuggestedViewHeight() and isHeightAuto() 17989 17990 ignoreWindowResize--; 17991 17992 17993 17994 return true; // signal success 17995 17996 } 17997 17998 } 17999 18000 18001 18002 18003 18004 function calcSize() { 18005 18006 if (elementVisible()) { 18007 18008 _calcSize(); 18009 18010 } 18011 18012 } 18013 18014 18015 18016 18017 18018 function _calcSize() { // assumes elementVisible 18019 18020 if (typeof options.contentHeight === 'number') { // exists and not 'auto' 18021 18022 suggestedViewHeight = options.contentHeight; 18023 18024 } 18025 18026 else if (typeof options.height === 'number') { // exists and not 'auto' 18027 18028 suggestedViewHeight = options.height - (headerElement ? headerElement.outerHeight(true) : 0); 18029 18030 } 18031 18032 else { 18033 18034 suggestedViewHeight = Math.round(content.width() / Math.max(options.aspectRatio, .5)); 18035 18036 } 18037 18038 } 18039 18040 18041 18042 18043 18044 function windowResize(ev) { 18045 18046 if ( 18047 18048 !ignoreWindowResize && 18049 18050 ev.target === window && // so we don't process jqui "resize" events that have bubbled up 18051 18052 currentView.start // view has already been rendered 18053 18054 ) { 18055 18056 if (updateSize(true)) { 18057 18058 currentView.trigger('windowResize', _element); 18059 18060 } 18061 18062 } 18063 18064 } 18065 18066 18067 18068 18069 18070 18071 18072 /* Event Fetching/Rendering 18073 18074 -----------------------------------------------------------------------------*/ 18075 18076 // TODO: going forward, most of this stuff should be directly handled by the view 18077 18078 18079 18080 18081 18082 function refetchEvents() { // can be called as an API method 18083 18084 destroyEvents(); // so that events are cleared before user starts waiting for AJAX 18085 18086 fetchAndRenderEvents(); 18087 18088 } 18089 18090 18091 18092 18093 18094 function renderEvents() { // destroys old events if previously rendered 18095 18096 if (elementVisible()) { 18097 18098 freezeContentHeight(); 18099 18100 currentView.displayEvents(events); 18101 18102 unfreezeContentHeight(); 18103 18104 } 18105 18106 } 18107 18108 18109 18110 18111 18112 function destroyEvents() { 18113 18114 freezeContentHeight(); 18115 18116 currentView.clearEvents(); 18117 18118 unfreezeContentHeight(); 18119 18120 } 18121 18122 18123 18124 18125 18126 function getAndRenderEvents() { 18127 18128 if (!options.lazyFetching || isFetchNeeded(currentView.start, currentView.end)) { 18129 18130 fetchAndRenderEvents(); 18131 18132 } 18133 18134 else { 18135 18136 renderEvents(); 18137 18138 } 18139 18140 } 18141 18142 18143 18144 18145 18146 function fetchAndRenderEvents() { 18147 18148 fetchEvents(currentView.start, currentView.end); 18149 18150 // ... will call reportEvents 18151 18152 // ... which will call renderEvents 18153 18154 } 18155 18156 18157 18158 18159 18160 // called when event data arrives 18161 18162 function reportEvents(_events) { 18163 18164 events = _events; 18165 18166 renderEvents(); 18167 18168 } 18169 18170 18171 18172 18173 18174 // called when a single event's data has been changed 18175 18176 function reportEventChange() { 18177 18178 renderEvents(); 18179 18180 } 18181 18182 18183 18184 18185 18186 18187 18188 /* Header Updating 18189 18190 -----------------------------------------------------------------------------*/ 18191 18192 18193 18194 18195 18196 function updateHeaderTitle() { 18197 18198 header.updateTitle(currentView.title); 18199 18200 } 18201 18202 18203 18204 18205 18206 function updateTodayButton() { 18207 18208 var now = t.getNow(); 18209 18210 if (now.isWithin(currentView.intervalStart, currentView.intervalEnd)) { 18211 18212 header.disableButton('today'); 18213 18214 } 18215 18216 else { 18217 18218 header.enableButton('today'); 18219 18220 } 18221 18222 } 18223 18224 18225 18226 18227 18228 18229
18230 /* Selection 18231 18232 -----------------------------------------------------------------------------*/ 18233 18234 18235 18236 18237 18238 // this public method receives start/end dates in any format, with any timezone 18239 18240 function select(zonedStartInput, zonedEndInput) { 18241 18242 currentView.select( 18243 18244 t.buildSelectSpan.apply(t, arguments) 18245 18246 ); 18247 18248 } 18249 18250 18251 18252 18253 18254 function unselect() { // safe to be called before renderView 18255 18256 if (currentView) { 18257 18258 currentView.unselect(); 18259 18260 } 18261 18262 } 18263 18264 18265 18266 18267 18268 18269 18270 /* Date 18271 18272 -----------------------------------------------------------------------------*/ 18273 18274 18275 18276 18277 18278 function prev() { 18279 18280 date = currentView.computePrevDate(date); 18281 18282 renderView(); 18283 18284 } 18285 18286 18287 18288 18289 18290 function next() { 18291 18292 date = currentView.computeNextDate(date); 18293 18294 renderView(); 18295 18296 } 18297 18298 18299 18300 18301 18302 function prevYear() { 18303 18304 date.add(-1, 'years'); 18305 18306 renderView(); 18307 18308 } 18309 18310 18311 18312 18313 18314 function nextYear() { 18315 18316 date.add(1, 'years'); 18317 18318 renderView(); 18319 18320 } 18321 18322 18323 18324 18325 18326 function today() { 18327 18328 date = t.getNow(); 18329 18330 renderView(); 18331 18332 } 18333 18334 18335 18336 18337 18338 function gotoDate(zonedDateInput) { 18339 18340 date = t.moment(zonedDateInput).stripZone(); 18341 18342 renderView(); 18343 18344 } 18345 18346 18347 18348 18349 18350 function incrementDate(delta) { 18351 18352 date.add(moment.duration(delta)); 18353 18354 renderView(); 18355 18356 } 18357 18358 18359 18360 18361 18362 // Forces navigation to a view for the given date. 18363 18364 // `viewType` can be a specific view name or a generic one like "week" or "day". 18365 18366 function zoomTo(newDate, viewType) { 18367 18368 var spec; 18369 18370 18371 18372 viewType = viewType || 'day'; // day is default zoom 18373 18374 spec = t.getViewSpec(viewType) || t.getUnitViewSpec(viewType); 18375 18376 18377 18378 date = newDate.clone(); 18379 18380 renderView(spec ? spec.type : null); 18381 18382 } 18383 18384 18385 18386 18387 18388 // for external API 18389 18390 function getDate() { 18391 18392 return t.applyTimezone(date); // infuse the calendar's timezone 18393 18394 } 18395 18396 18397 18398 18399 18400 18401 18402 /* Height "Freezing" 18403 18404 -----------------------------------------------------------------------------*/ 18405 18406 // TODO: move this into the view 18407 18408 18409 18410 t.freezeContentHeight = freezeContentHeight; 18411 18412 t.unfreezeContentHeight = unfreezeContentHeight; 18413 18414 18415 18416 18417 18418 function freezeContentHeight() { 18419 18420 content.css({ 18421 18422 width: '100%', 18423 18424 height: content.height(), 18425 18426 overflow: 'hidden' 18427 18428 }); 18429 18430 } 18431 18432 18433 18434 18435 18436 function unfreezeContentHeight() { 18437 18438 content.css({ 18439 18440 width: '', 18441 18442 height: '', 18443 18444 overflow: '' 18445 18446 }); 18447 18448 } 18449 18450 18451 18452 18453 18454 18455 18456 /* Misc 18457 18458 -----------------------------------------------------------------------------*/ 18459 18460 18461 18462 18463 18464 function getCalendar() { 18465 18466 return t; 18467 18468 } 18469 18470 18471 18472 18473 18474 function getView() { 18475 18476 return currentView; 18477 18478 } 18479 18480 18481 18482 18483 18484 function option(name, value) { 18485 18486 if (value === undefined) { 18487 18488 return options[name]; 18489 18490 } 18491 18492 if (name == 'height' || name == 'contentHeight' || name == 'aspectRatio') { 18493 18494 options[name] = value; 18495 18496 updateSize(true); // true = allow recalculation of height 18497 18498 } 18499 18500 } 18501 18502 18503 18504 18505 18506 function trigger(name, thisObj) { // overrides the Emitter's trigger method :( 18507 18508 var args = Array.prototype.slice.call(arguments, 2); 18509 18510 18511 18512 thisObj = thisObj || _element; 18513 18514 this.triggerWith(name, thisObj, args); // Emitter's method 18515 18516 18517 18518 if (options[name]) { 18519 18520 return options[name].apply(thisObj, args); 18521 18522 } 18523 18524 } 18525 18526 18527 18528 t.initialize(); 18529 18530 } 18531 18532 18533 18534 ;; 18535 18536 18537 18538 Calendar.defaults = { 18539 18540 18541 18542 titleRangeSeparator: ' \u2014 ', // emphasized dash 18543 18544 monthYearFormat: 'MMMM YYYY', // required for en. other languages rely on datepicker computable option 18545 18546 18547 18548 defaultTimedEventDuration: '02:00:00', 18549 18550 defaultAllDayEventDuration: { days: 1 }, 18551 18552 forceEventDuration: false, 18553 18554 nextDayThreshold: '09:00:00', // 9am 18555 18556 18557 18558 // display 18559 18560 defaultView: 'month', 18561 18562 aspectRatio: 1.35, 18563 18564 header: { 18565 18566 left: 'title', 18567 18568 center: '', 18569 18570 right: 'today prev,next' 18571 18572 }, 18573 18574 weekends: true, 18575 18576 weekNumbers: false, 18577 18578 18579 18580 weekNumberTitle: 'W', 18581 18582 weekNumberCalculation: 'local', 18583 18584 18585 18586 //editable: false, 18587 18588 18589 18590 scrollTime: '06:00:00', 18591 18592 18593 18594 // event ajax 18595 18596 lazyFetching: true, 18597 18598 startParam: 'start', 18599 18600 endParam: 'end', 18601 18602 timezoneParam: 'timezone', 18603 18604 18605 18606 timezone: false, 18607 18608 18609 18610 //allDayDefault: undefined, 18611 18612 18613 18614 // locale 18615 18616 isRTL: false, 18617 18618 buttonText: { 18619 18620 prev: "prev", 18621 18622 next: "next", 18623 18624 prevYear: "prev year", 18625 18626 nextYear: "next year", 18627 18628 year: 'year', // TODO: locale files need to specify this 18629 18630 today: 'today', 18631 18632 month: 'month', 18633 18634 week: 'week', 18635 18636 day: 'day' 18637 18638 }, 18639 18640 18641 18642 buttonIcons: { 18643 18644 prev: 'left-single-arrow', 18645 18646 next: 'right-single-arrow', 18647 18648 prevYear: 'left-double-arrow', 18649 18650 nextYear: 'right-double-arrow' 18651 18652 }, 18653 18654 18655 18656 // jquery-ui theming 18657 18658 theme: false, 18659 18660 themeButtonIcons: { 18661 18662 prev: 'circle-triangle-w', 18663 18664 next: 'circle-triangle-e', 18665 18666 prevYear: 'seek-prev', 18667 18668 nextYear: 'seek-next' 18669 18670 }, 18671 18672 18673 18674 //eventResizableFromStart: false, 18675 18676 dragOpacity: .75, 18677 18678 dragRevertDuration: 500, 18679 18680 dragScroll: true, 18681 18682 18683 18684 //selectable: false, 18685 18686 unselectAuto: true, 18687 18688 18689 18690 dropAccept: '*', 18691 18692 18693 18694 eventOrder: 'title', 18695 18696 18697 18698 eventLimit: false, 18699 18700 eventLimitText: 'more', 18701 18702 eventLimitClick: 'popover', 18703 18704 dayPopoverFormat: 'LL', 18705 18706 18707 18708 handleWindowResize: true, 18709 18710 windowResizeDelay: 200 // milliseconds before an updateSize happens 18711 18712 18713 18714 }; 18715 18716 18717 18718 18719 18720 Calendar.englishDefaults = { // used by lang.js 18721 18722 dayPopoverFormat: 'dddd, MMMM D' 18723 18724 }; 18725 18726 18727 18728 18729 18730 Calendar.rtlDefaults = { // right-to-left defaults 18731 18732 header: { // TODO: smarter solution (first/center/last ?) 18733
18734 left: 'next,prev today', 18735 18736 center: '', 18737 18738 right: 'title' 18739 18740 }, 18741 18742 buttonIcons: { 18743 18744 prev: 'right-single-arrow', 18745 18746 next: 'left-single-arrow', 18747 18748 prevYear: 'right-double-arrow', 18749 18750 nextYear: 'left-double-arrow' 18751 18752 }, 18753 18754 themeButtonIcons: { 18755 18756 prev: 'circle-triangle-e', 18757 18758 next: 'circle-triangle-w', 18759 18760 nextYear: 'seek-prev', 18761 18762 prevYear: 'seek-next' 18763 18764 } 18765 18766 }; 18767 18768 18769 18770 ;; 18771 18772 18773 18774 var langOptionHash = FC.langs = {}; // initialize and expose 18775 18776 18777 18778 18779 18780// TODO: document the structure and ordering of a FullCalendar lang file 18781 18782// TODO: rename everything "lang" to "locale", like what the moment project did 18783 18784 18785 18786 18787 18788// Initialize jQuery UI datepicker translations while using some of the translations 18789 18790// Will set this as the default language for datepicker. 18791 18792 FC.datepickerLang = function(langCode, dpLangCode, dpOptions) { 18793 18794 18795 18796 // get the FullCalendar internal option hash for this language. create if necessary 18797 18798 var fcOptions = langOptionHash[langCode] || (langOptionHash[langCode] = {}); 18799 18800 18801 18802 // transfer some simple options from datepicker to fc 18803 18804 fcOptions.isRTL = dpOptions.isRTL; 18805 18806 fcOptions.weekNumberTitle = dpOptions.weekHeader; 18807 18808 18809 18810 // compute some more complex options from datepicker 18811 18812 $.each(dpComputableOptions, function(name, func) { 18813 18814 fcOptions[name] = func(dpOptions); 18815 18816 }); 18817 18818 18819 18820 // is jQuery UI Datepicker is on the page? 18821 18822 if ($.datepicker) { 18823 18824 18825 18826 // Register the language data. 18827 18828 // FullCalendar and MomentJS use language codes like "pt-br" but Datepicker 18829 18830 // does it like "pt-BR" or if it doesn't have the language, maybe just "pt". 18831 18832 // Make an alias so the language can be referenced either way. 18833 18834 $.datepicker.regional[dpLangCode] = 18835 18836 $.datepicker.regional[langCode] = // alias 18837 18838 dpOptions; 18839 18840 18841 18842 // Alias 'en' to the default language data. Do this every time. 18843 18844 $.datepicker.regional.en = $.datepicker.regional['']; 18845 18846 18847 18848 // Set as Datepicker's global defaults. 18849 18850 $.datepicker.setDefaults(dpOptions); 18851 18852 } 18853 18854 }; 18855 18856 18857 18858 18859 18860// Sets FullCalendar-specific translations. Will set the language as the global default. 18861 18862 FC.lang = function(langCode, newFcOptions) { 18863 18864 var fcOptions; 18865 18866 var momOptions; 18867 18868 18869 18870 // get the FullCalendar internal option hash for this language. create if necessary 18871 18872 fcOptions = langOptionHash[langCode] || (langOptionHash[langCode] = {}); 18873 18874 18875 18876 // provided new options for this language? merge them in 18877 18878 if (newFcOptions) { 18879 18880 fcOptions = langOptionHash[langCode] = mergeOptions([ fcOptions, newFcOptions ]); 18881 18882 } 18883 18884 18885 18886 // compute language options that weren't defined. 18887 18888 // always do this. newFcOptions can be undefined when initializing from i18n file, 18889 18890 // so no way to tell if this is an initialization or a default-setting. 18891 18892 momOptions = getMomentLocaleData(langCode); // will fall back to en 18893 18894 $.each(momComputableOptions, function(name, func) { 18895 18896 if (fcOptions[name] == null) { 18897 18898 fcOptions[name] = func(momOptions, fcOptions); 18899 18900 } 18901 18902 }); 18903 18904 18905 18906 // set it as the default language for FullCalendar 18907 18908 Calendar.defaults.lang = langCode; 18909 18910 }; 18911 18912 18913 18914 18915 18916// NOTE: can't guarantee any of these computations will run because not every language has datepicker 18917 18918// configs, so make sure there are English fallbacks for these in the defaults file. 18919 18920 var dpComputableOptions = { 18921 18922 18923 18924 buttonText: function(dpOptions) { 18925 18926 return { 18927 18928 // the translations sometimes wrongly contain HTML entities 18929 18930 prev: stripHtmlEntities(dpOptions.prevText), 18931 18932 next: stripHtmlEntities(dpOptions.nextText), 18933 18934 today: stripHtmlEntities(dpOptions.currentText) 18935 18936 }; 18937 18938 }, 18939 18940 18941 18942 // Produces format strings like "MMMM YYYY" -> "September 2014" 18943 18944 monthYearFormat: function(dpOptions) { 18945 18946 return dpOptions.showMonthAfterYear ? 18947 18948 'YYYY[' + dpOptions.yearSuffix + '] MMMM' : 18949 18950 'MMMM YYYY[' + dpOptions.yearSuffix + ']'; 18951 18952 } 18953 18954 18955 18956 }; 18957 18958 18959 18960 var momComputableOptions = { 18961 18962 18963 18964 // Produces format strings like "ddd M/D" -> "Fri 9/15" 18965 18966 dayOfMonthFormat: function(momOptions, fcOptions) { 18967 18968 var format = momOptions.longDateFormat('l'); // for the format like "M/D/YYYY" 18969 18970 18971 18972 // strip the year off the edge, as well as other misc non-whitespace chars 18973
18974 format = format.replace(/^Y+[^\w\s]*|[^\w\s]*Y+$/g, ''); 18975 18976 18977 18978 if (fcOptions.isRTL) { 18979 18980 format += ' ddd'; // for RTL, add day-of-week to end 18981 18982 } 18983 18984 else { 18985 18986 format = 'ddd ' + format; // for LTR, add day-of-week to beginning 18987 18988 } 18989 18990 return format; 18991 18992 }, 18993 18994 18995 18996 // Produces format strings like "h:mma" -> "6:00pm" 18997 18998 mediumTimeFormat: function(momOptions) { // can't be called `timeFormat` because collides with option 18999 19000 return momOptions.longDateFormat('LT') 19001 19002 .replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand 19003 19004 }, 19005 19006 19007 19008 // Produces format strings like "h(:mm)a" -> "6pm" / "6:30pm" 19009 19010 smallTimeFormat: function(momOptions) { 19011 19012 return momOptions.longDateFormat('LT') 19013 19014 .replace(':mm', '(:mm)') 19015 19016 .replace(/(\Wmm)$/, '($1)') // like above, but for foreign langs 19017 19018 .replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand 19019 19020 }, 19021 19022 19023 19024 // Produces format strings like "h(:mm)t" -> "6p" / "6:30p" 19025 19026 extraSmallTimeFormat: function(momOptions) { 19027 19028 return momOptions.longDateFormat('LT') 19029 19030 .replace(':mm', '(:mm)') 19031 19032 .replace(/(\Wmm)$/, '($1)') // like above, but for foreign langs 19033 19034 .replace(/\s*a$/i, 't'); // convert to AM/PM/am/pm to lowercase one-letter. remove any spaces beforehand 19035 19036 }, 19037 19038 19039 19040 // Produces format strings like "ha" / "H" -> "6pm" / "18" 19041 19042 hourFormat: function(momOptions) { 19043 19044 return momOptions.longDateFormat('LT') 19045 19046 .replace(':mm', '') 19047 19048 .replace(/(\Wmm)$/, '') // like above, but for foreign langs 19049 19050 .replace(/\s*a$/i, 'a'); // convert AM/PM/am/pm to lowercase. remove any spaces beforehand 19051 19052 }, 19053 19054 19055 19056 // Produces format strings like "h:mm" -> "6:30" (with no AM/PM) 19057 19058 noMeridiemTimeFormat: function(momOptions) { 19059 19060 return momOptions.longDateFormat('LT') 19061 19062 .replace(/\s*a$/i, ''); // remove trailing AM/PM 19063 19064 } 19065 19066 19067 19068 }; 19069 19070 19071 19072 19073 19074// options that should be computed off live calendar options (considers override options) 19075 19076// TODO: best place for this? related to lang? 19077 19078// TODO: flipping text based on isRTL is a bad idea because the CSS `direction` might want to handle it 19079 19080 var instanceComputableOptions = { 19081 19082 19083 19084 // Produces format strings for results like "Mo 16" 19085 19086 smallDayDateFormat: function(options) { 19087 19088 return options.isRTL ? 19089 19090 'D dd' : 19091 19092 'dd D'; 19093 19094 }, 19095 19096 19097 19098 // Produces format strings for results like "Wk 5" 19099 19100 weekFormat: function(options) { 19101 19102 return options.isRTL ? 19103 19104 'w[ ' + options.weekNumberTitle + ']' : 19105 19106 '[' + options.weekNumberTitle + ' ]w'; 19107 19108 }, 19109 19110 19111 19112 // Produces format strings for results like "Wk5" 19113 19114 smallWeekFormat: function(options) { 19115 19116 return options.isRTL ? 19117 19118 'w[' + options.weekNumberTitle + ']' : 19119 19120 '[' + options.weekNumberTitle + ']w'; 19121 19122 } 19123 19124 19125 19126 }; 19127 19128 19129 19130 function populateInstanceComputableOptions(options) { 19131 19132 $.each(instanceComputableOptions, function(name, func) { 19133 19134 if (options[name] == null) { 19135 19136 options[name] = func(options); 19137 19138 } 19139 19140 }); 19141 19142 } 19143 19144 19145 19146 19147 19148// Returns moment's internal locale data. If doesn't exist, returns English. 19149 19150// Works with moment-pre-2.8 19151 19152 function getMomentLocaleData(langCode) { 19153 19154 var func = moment.localeData || moment.langData; 19155 19156 return func.call(moment, langCode) || 19157 19158 func.call(moment, 'en'); // the newer localData could return null, so fall back to en 19159 19160 } 19161 19162 19163 19164 19165 19166// Initialize English by forcing computation of moment-derived options. 19167 19168// Also, sets it as the default. 19169 19170 FC.lang('en', Calendar.englishDefaults); 19171 19172 19173 19174 ;; 19175 19176 19177 19178 /* Top toolbar area with buttons and title 19179 19180 ----------------------------------------------------------------------------------------------------------------------*/ 19181 19182// TODO: rename all header-related things to "toolbar" 19183 19184 19185 19186 function Header(calendar, options) { 19187 19188 var t = this; 19189 19190 19191 19192 // exports 19193 19194 t.render = render; 19195 19196 t.removeElement = removeElement; 19197 19198 t.updateTitle = updateTitle; 19199 19200 t.activateButton = activateButton; 19201 19202 t.deactivateButton = deactivateButton; 19203 19204 t.disableButton = disableButton; 19205 19206 t.enableButton = enableButton; 19207 19208 t.getViewsWithButtons = getViewsWithButtons; 19209 19210 19211 19212 // locals 19213 19214 var el = $(); 19215 19216 var viewsWithButtons = []; 19217 19218 var tm; 19219 19220 19221 19222 19223 19224 function render() { 19225 19226 var sections = options.header; 19227 19228 19229 19230 tm = options.theme ? 'ui' : 'fc'; 19231 19232 19233 19234 if (sections) { 19235 19236 el = $("<div class='fc-toolbar'/>") 19237 19238 .append(renderSection('left')) 19239 19240 .append(renderSection('right')) 19241 19242 .append(renderSection('center')) 19243 19244 .append('<div class="fc-clear"/>'); 19245 19246 19247 19248 return el; 19249 19250 } 19251 19252 } 19253 19254 19255 19256 19257 19258 function removeElement() { 19259 19260 el.remove(); 19261 19262 el = $(); 19263 19264 } 19265 19266 19267 19268 19269
19270 function renderSection(position) { 19271 19272 var sectionEl = $('<div class="fc-' + position + '"/>'); 19273 19274 var buttonStr = options.header[position]; 19275 19276 19277 19278 if (buttonStr) { 19279 19280 $.each(buttonStr.split(' '), function(i) { 19281 19282 var groupChildren = $(); 19283 19284 var isOnlyButtons = true; 19285 19286 var groupEl; 19287 19288 19289 19290 $.each(this.split(','), function(j, buttonName) { 19291 19292 var customButtonProps; 19293 19294 var viewSpec; 19295 19296 var buttonClick; 19297 19298 var overrideText; // text explicitly set by calendar's constructor options. overcomes icons 19299 19300 var defaultText; 19301 19302 var themeIcon; 19303 19304 var normalIcon; 19305 19306 var innerHtml; 19307 19308 var classes; 19309 19310 var button; // the element 19311 19312 19313 19314 if (buttonName == 'title') { 19315 19316 groupChildren = groupChildren.add($('<h2> </h2>')); // we always want it to take up height 19317 19318 isOnlyButtons = false; 19319 19320 } 19321 19322 else { 19323 19324 if ((customButtonProps = (calendar.options.customButtons || {})[buttonName])) { 19325 19326 buttonClick = function(ev) { 19327 19328 if (customButtonProps.click) { 19329 19330 customButtonProps.click.call(button[0], ev); 19331 19332 } 19333 19334 }; 19335 19336 overrideText = ''; // icons will override text 19337 19338 defaultText = customButtonProps.text; 19339 19340 } 19341 19342 else if ((viewSpec = calendar.getViewSpec(buttonName))) { 19343 19344 buttonClick = function() { 19345 19346 calendar.changeView(buttonName); 19347 19348 }; 19349 19350 viewsWithButtons.push(buttonName); 19351 19352 overrideText = viewSpec.buttonTextOverride; 19353 19354 defaultText = viewSpec.buttonTextDefault; 19355 19356 } 19357 19358 else if (calendar[buttonName]) { // a calendar method 19359 19360 buttonClick = function() { 19361 19362 calendar[buttonName](); 19363 19364 }; 19365 19366 overrideText = (calendar.overrides.buttonText || {})[buttonName]; 19367 19368 defaultText = options.buttonText[buttonName]; // everything else is considered default 19369 19370 } 19371 19372 19373 19374 if (buttonClick) { 19375 19376 19377 19378 themeIcon = 19379 19380 customButtonProps ? 19381 19382 customButtonProps.themeIcon : 19383 19384 options.themeButtonIcons[buttonName]; 19385 19386 19387 19388 normalIcon = 19389 19390 customButtonProps ? 19391 19392 customButtonProps.icon : 19393 19394 options.buttonIcons[buttonName]; 19395 19396 19397 19398 if (overrideText) { 19399 19400 innerHtml = htmlEscape(overrideText); 19401 19402 } 19403 19404 else if (themeIcon && options.theme) { 19405 19406 innerHtml = "<span class='ui-icon ui-icon-" + themeIcon + "'></span>"; 19407 19408 } 19409 19410 else if (normalIcon && !options.theme) { 19411 19412 innerHtml = "<span class='fc-icon fc-icon-" + normalIcon + "'></span>"; 19413 19414 } 19415 19416 else { 19417 19418 innerHtml = htmlEscape(defaultText); 19419 19420 } 19421 19422 19423 19424 classes = [ 19425 19426 'fc-' + buttonName + '-button', 19427 19428 tm + '-button', 19429 19430 tm + '-state-default' 19431 19432 ]; 19433 19434 19435 19436 button = $( // type="button" so that it doesn't submit a form 19437 19438 '<button type="button" class="' + classes.join(' ') + '">' + 19439 19440 innerHtml + 19441 19442 '</button>' 19443 19444 ) 19445 19446 .click(function(ev) { 19447 19448 // don't process clicks for disabled buttons 19449 19450 if (!button.hasClass(tm + '-state-disabled')) { 19451 19452 19453 19454 buttonClick(ev); 19455 19456 19457 19458 // after the click action, if the button becomes the "active" tab, or disabled, 19459 19460 // it should never have a hover class, so remove it now. 19461 19462 if ( 19463 19464 button.hasClass(tm + '-state-active') || 19465 19466 button.hasClass(tm + '-state-disabled') 19467 19468 ) { 19469 19470 button.removeClass(tm + '-state-hover'); 19471 19472 } 19473 19474 } 19475 19476 }) 19477 19478 .mousedown(function() { 19479 19480 // the *down* effect (mouse pressed in). 19481 19482 // only on buttons that are not the "active" tab, or disabled 19483 19484 button 19485 19486 .not('.' + tm + '-state-active') 19487 19488 .not('.' + tm + '-state-disabled') 19489 19490 .addClass(tm + '-state-down'); 19491 19492 }) 19493 19494 .mouseup(function() { 19495 19496 // undo the *down* effect 19497 19498 button.removeClass(tm + '-state-down'); 19499 19500 }) 19501 19502 .hover( 19503 19504 function() { 19505 19506 // the *hover* effect. 19507 19508 // only on buttons that are not the "active" tab, or disabled 19509 19510 button 19511 19512 .not('.' + tm + '-state-active') 19513 19514 .not('.' + tm + '-state-disabled') 19515 19516 .addClass(tm + '-state-hover'); 19517 19518 }, 19519 19520 function() { 19521
19522 // undo the *hover* effect 19523 19524 button 19525 19526 .removeClass(tm + '-state-hover') 19527 19528 .removeClass(tm + '-state-down'); // if mouseleave happens before mouseup 19529 19530 } 19531 19532 ); 19533 19534 19535 19536 groupChildren = groupChildren.add(button); 19537 19538 } 19539 19540 } 19541 19542 }); 19543 19544 19545 19546 if (isOnlyButtons) { 19547 19548 groupChildren 19549 19550 .first().addClass(tm + '-corner-left').end() 19551 19552 .last().addClass(tm + '-corner-right').end(); 19553 19554 } 19555 19556 19557 19558 if (groupChildren.length > 1) { 19559 19560 groupEl = $('<div/>'); 19561 19562 if (isOnlyButtons) { 19563 19564 groupEl.addClass('fc-button-group'); 19565 19566 } 19567 19568 groupEl.append(groupChildren); 19569 19570 sectionEl.append(groupEl); 19571 19572 } 19573 19574 else { 19575 19576 sectionEl.append(groupChildren); // 1 or 0 children 19577 19578 } 19579 19580 }); 19581 19582 } 19583 19584 19585 19586 return sectionEl; 19587 19588 } 19589 19590 19591 19592 19593 19594 function updateTitle(text) { 19595 19596 el.find('h2').text(text); 19597 19598 } 19599 19600 19601 19602 19603 19604 function activateButton(buttonName) { 19605 19606 el.find('.fc-' + buttonName + '-button') 19607 19608 .addClass(tm + '-state-active'); 19609 19610 } 19611 19612 19613 19614 19615 19616 function deactivateButton(buttonName) { 19617 19618 el.find('.fc-' + buttonName + '-button') 19619 19620 .removeClass(tm + '-state-active'); 19621 19622 } 19623 19624 19625 19626 19627 19628 function disableButton(buttonName) { 19629 19630 el.find('.fc-' + buttonName + '-button') 19631 19632 .attr('disabled', 'disabled') 19633 19634 .addClass(tm + '-state-disabled'); 19635 19636 } 19637 19638 19639 19640 19641 19642 function enableButton(buttonName) { 19643 19644 el.find('.fc-' + buttonName + '-button') 19645 19646 .removeAttr('disabled') 19647 19648 .removeClass(tm + '-state-disabled'); 19649 19650 } 19651 19652 19653 19654 19655 19656 function getViewsWithButtons() { 19657 19658 return viewsWithButtons; 19659 19660 } 19661 19662 19663 19664 } 19665 19666 19667 19668 ;; 19669 19670 19671 19672 FC.sourceNormalizers = []; 19673 19674 FC.sourceFetchers = []; 19675 19676 19677 19678 var ajaxDefaults = { 19679 19680 dataType: 'json', 19681 19682 cache: false 19683 19684 }; 19685 19686 19687 19688 var eventGUID = 1; 19689 19690 19691 19692 19693 19694 function EventManager(options) { // assumed to be a calendar 19695 19696 var t = this; 19697 19698 19699 19700 19701 19702 // exports 19703 19704 t.isFetchNeeded = isFetchNeeded; 19705 19706 t.fetchEvents = fetchEvents; 19707 19708 t.addEventSource = addEventSource; 19709 19710 t.removeEventSource = removeEventSource; 19711 19712 t.updateEvent = updateEvent; 19713 19714 t.renderEvent = renderEvent; 19715 19716 t.removeEvents = removeEvents; 19717 19718 t.clientEvents = clientEvents; 19719 19720 t.mutateEvent = mutateEvent; 19721 19722 t.normalizeEventDates = normalizeEventDates; 19723 19724 t.normalizeEventTimes = normalizeEventTimes; 19725 19726 19727 19728 19729 19730 // imports 19731 19732 var reportEvents = t.reportEvents; 19733 19734 19735 19736 19737 19738 // locals 19739 19740 var stickySource = { events: [] }; 19741 19742 var sources = [ stickySource ]; 19743 19744 var rangeStart, rangeEnd; 19745 19746 var currentFetchID = 0; 19747
19748 var pendingSourceCnt = 0; 19749 19750 var cache = []; // holds events that have already been expanded 19751 19752 19753 19754 19755 19756 $.each( 19757 19758 (options.events ? [ options.events ] : []).concat(options.eventSources || []), 19759 19760 function(i, sourceInput) { 19761 19762 var source = buildEventSource(sourceInput); 19763 19764 if (source) { 19765 19766 sources.push(source); 19767 19768 } 19769 19770 } 19771 19772 ); 19773 19774 19775 19776 19777 19778 19779 19780 /* Fetching 19781 19782 -----------------------------------------------------------------------------*/ 19783 19784 19785 19786 19787 19788 // start and end are assumed to be unzoned 19789 19790 function isFetchNeeded(start, end) { 19791 19792 return !rangeStart || // nothing has been fetched yet? 19793 19794 start < rangeStart || end > rangeEnd; // is part of the new range outside of the old range? 19795 19796 } 19797 19798 19799 19800 19801 19802 function fetchEvents(start, end) { 19803 19804 rangeStart = start; 19805 19806 rangeEnd = end; 19807 19808 cache = []; 19809 19810 var fetchID = ++currentFetchID; 19811 19812 var len = sources.length; 19813 19814 pendingSourceCnt = len; 19815 19816 for (var i=0; i<len; i++) { 19817 19818 fetchEventSource(sources[i], fetchID); 19819 19820 } 19821 19822 } 19823 19824 19825 19826 19827 19828 function fetchEventSource(source, fetchID) { 19829 19830 _fetchEventSource(source, function(eventInputs) { 19831 19832 var isArraySource = $.isArray(source.events); 19833 19834 var i, eventInput; 19835 19836 var abstractEvent; 19837 19838 19839 19840 if (fetchID == currentFetchID) { 19841 19842 19843 19844 if (eventInputs) { 19845 19846 for (i = 0; i < eventInputs.length; i++) { 19847 19848 eventInput = eventInputs[i]; 19849 19850 19851 19852 if (isArraySource) { // array sources have already been convert to Event Objects 19853 19854 abstractEvent = eventInput; 19855 19856 } 19857 19858 else { 19859 19860 abstractEvent = buildEventFromInput(eventInput, source); 19861 19862 } 19863 19864 19865 19866 if (abstractEvent) { // not false (an invalid event) 19867 19868 cache.push.apply( 19869 19870 cache, 19871 19872 expandEvent(abstractEvent) // add individual expanded events to the cache 19873 19874 ); 19875 19876 } 19877 19878 } 19879 19880 } 19881 19882 19883 19884 pendingSourceCnt--; 19885 19886 if (!pendingSourceCnt) { 19887 19888 reportEvents(cache); 19889 19890 } 19891 19892 } 19893 19894 }); 19895 19896 } 19897 19898 19899 19900 19901 19902 function _fetchEventSource(source, callback) { 19903 19904 var i; 19905 19906 var fetchers = FC.sourceFetchers; 19907 19908 var res; 19909 19910 19911 19912 for (i=0; i<fetchers.length; i++) { 19913 19914 res = fetchers[i].call( 19915 19916 t, // this, the Calendar object 19917 19918 source, 19919 19920 rangeStart.clone(), 19921 19922 rangeEnd.clone(), 19923 19924 options.timezone, 19925 19926 callback 19927 19928 ); 19929 19930 19931 19932 if (res === true) { 19933 19934 // the fetcher is in charge. made its own async request 19935 19936 return; 19937 19938 } 19939 19940 else if (typeof res == 'object') { 19941 19942 // the fetcher returned a new source. process it 19943 19944 _fetchEventSource(res, callback); 19945 19946 return; 19947 19948 } 19949 19950 } 19951 19952 19953 19954 var events = source.events; 19955 19956 if (events) { 19957 19958 if ($.isFunction(events)) { 19959 19960 t.pushLoading(); 19961 19962 events.call( 19963 19964 t, // this, the Calendar object 19965 19966 rangeStart.clone(), 19967 19968 rangeEnd.clone(), 19969 19970 options.timezone, 19971 19972 function(events) { 19973 19974 callback(events); 19975 19976 t.popLoading(); 19977 19978 } 19979 19980 ); 19981 19982 } 19983 19984 else if ($.isArray(events)) { 19985 19986 callback(events); 19987 19988 } 19989 19990 else { 19991 19992 callback(); 19993 19994 } 19995 19996 }else{ 19997 19998 var url = source.url; 19999 20000 if (url) { 20001 20002 var success = source.success; 20003 20004 var error = source.error; 20005 20006 var complete = source.complete; 20007 20008 20009 20010 // retrieve any outbound GET/POST $.ajax data from the options 20011 20012 var customData; 20013 20014 if ($.isFunction(source.data)) { 20015 20016 // supplied as a function that returns a key/value object 20017 20018 customData = source.data(); 20019 20020 } 20021 20022 else { 20023 20024 // supplied as a straight key/value object 20025 20026 customData = source.data; 20027 20028 } 20029 20030 20031 20032 // use a copy of the custom data so we can modify the parameters 20033 20034 // and not affect the passed-in object. 20035 20036 var data = $.extend({}, customData || {}); 20037 20038 20039 20040 var startParam = firstDefined(source.startParam, options.startParam); 20041 20042 var endParam = firstDefined(source.endParam, options.endParam); 20043 20044 var timezoneParam = firstDefined(source.timezoneParam, options.timezoneParam); 20045 20046 20047 20048 if (startParam) { 20049 20050 data[startParam] = rangeStart.format(); 20051 20052 } 20053 20054 if (endParam) { 20055 20056 data[endParam] = rangeEnd.format(); 20057 20058 } 20059 20060 if (options.timezone && options.timezone != 'local') { 20061 20062 data[timezoneParam] = options.timezone; 20063 20064 } 20065 20066 20067 20068 t.pushLoading(); 20069 20070 $.ajax($.extend({}, ajaxDefaults, source, { 20071 20072 data: data, 20073 20074 success: function(events) { 20075 20076 events = events || []; 20077 20078 var res = applyAll(success, this, arguments); 20079 20080 if ($.isArray(res)) { 20081 20082 events = res; 20083 20084 } 20085 20086 callback(events); 20087 20088 }, 20089 20090 error: function() { 20091 20092 applyAll(error, this, arguments); 20093 20094 callback(); 20095 20096 }, 20097 20098 complete: function() { 20099 20100 applyAll(complete, this, arguments); 20101 20102 t.popLoading(); 20103 20104 } 20105 20106 })); 20107 20108 }else{ 20109 20110 callback(); 20111 20112 } 20113 20114 } 20115 20116 } 20117 20118 20119 20120 20121 20122 20123
20124 /* Sources 20125 20126 -----------------------------------------------------------------------------*/ 20127 20128 20129 20130 20131 20132 function addEventSource(sourceInput) { 20133 20134 var source = buildEventSource(sourceInput); 20135 20136 if (source) { 20137 20138 sources.push(source); 20139 20140 pendingSourceCnt++; 20141 20142 fetchEventSource(source, currentFetchID); // will eventually call reportEvents 20143 20144 } 20145 20146 } 20147 20148 20149 20150 20151 20152 function buildEventSource(sourceInput) { // will return undefined if invalid source 20153 20154 var normalizers = FC.sourceNormalizers; 20155 20156 var source; 20157 20158 var i; 20159 20160 20161 20162 if ($.isFunction(sourceInput) || $.isArray(sourceInput)) { 20163 20164 source = { events: sourceInput }; 20165 20166 } 20167 20168 else if (typeof sourceInput === 'string') { 20169 20170 source = { url: sourceInput }; 20171 20172 } 20173 20174 else if (typeof sourceInput === 'object') { 20175 20176 source = $.extend({}, sourceInput); // shallow copy 20177 20178 } 20179 20180 20181 20182 if (source) { 20183 20184 20185 20186 // TODO: repeat code, same code for event classNames 20187 20188 if (source.className) { 20189 20190 if (typeof source.className === 'string') { 20191 20192 source.className = source.className.split(/\s+/); 20193 20194 } 20195 20196 // otherwise, assumed to be an array 20197 20198 } 20199 20200 else { 20201 20202 source.className = []; 20203 20204 } 20205 20206 20207 20208 // for array sources, we convert to standard Event Objects up front 20209 20210 if ($.isArray(source.events)) { 20211 20212 source.origArray = source.events; // for removeEventSource 20213 20214 source.events = $.map(source.events, function(eventInput) { 20215 20216 return buildEventFromInput(eventInput, source); 20217 20218 }); 20219 20220 } 20221 20222 20223 20224 for (i=0; i<normalizers.length; i++) { 20225 20226 normalizers[i].call(t, source); 20227 20228 } 20229 20230 20231 20232 return source; 20233 20234 } 20235 20236 } 20237 20238 20239 20240 20241 20242 function removeEventSource(source) { 20243 20244 sources = $.grep(sources, function(src) { 20245 20246 return !isSourcesEqual(src, source); 20247 20248 }); 20249 20250 // remove all client events from that source 20251 20252 cache = $.grep(cache, function(e) { 20253 20254 return !isSourcesEqual(e.source, source); 20255 20256 }); 20257 20258 reportEvents(cache); 20259 20260 } 20261 20262 20263 20264 20265 20266 function isSourcesEqual(source1, source2) { 20267 20268 return source1 && source2 && getSourcePrimitive(source1) == getSourcePrimitive(source2); 20269 20270 } 20271 20272 20273 20274 20275 20276 function getSourcePrimitive(source) { 20277 20278 return ( 20279 20280 (typeof source === 'object') ? // a normalized event source? 20281 20282 (source.origArray || source.googleCalendarId || source.url || source.events) : // get the primitive 20283 20284 null 20285 20286 ) || 20287 20288 source; // the given argument *is* the primitive 20289 20290 } 20291 20292 20293 20294 20295 20296 20297 20298 /* Manipulation 20299 20300 -----------------------------------------------------------------------------*/ 20301 20302 20303 20304 20305 20306 // Only ever called from the externally-facing API 20307 20308 function updateEvent(event) { 20309 20310 20311 20312 // massage start/end values, even if date string values 20313 20314 event.start = t.moment(event.start); 20315 20316 if (event.end) { 20317 20318 event.end = t.moment(event.end); 20319 20320 } 20321 20322 else { 20323 20324 event.end = null; 20325 20326 } 20327 20328 20329 20330 mutateEvent(event, getMiscEventProps(event)); // will handle start/end/allDay normalization 20331 20332 reportEvents(cache); // reports event modifications (so we can redraw) 20333 20334 } 20335 20336 20337 20338 20339 20340 // Returns a hash of misc event properties that should be copied over to related events. 20341 20342 function getMiscEventProps(event) { 20343 20344 var props = {}; 20345 20346 20347 20348 $.each(event, function(name, val) { 20349 20350 if (isMiscEventPropName(name)) { 20351 20352 if (val !== undefined && isAtomic(val)) { // a defined non-object 20353 20354 props[name] = val; 20355 20356 } 20357 20358 } 20359 20360 }); 20361 20362 20363 20364 return props; 20365 20366 } 20367 20368 20369 20370 // non-date-related, non-id-related, non-secret 20371 20372 function isMiscEventPropName(name) { 20373 20374 return !/^_|^(id|allDay|start|end)$/.test(name); 20375 20376 } 20377 20378 20379 20380 20381 20382 // returns the expanded events that were created 20383 20384 function renderEvent(eventInput, stick) { 20385 20386 var abstractEvent = buildEventFromInput(eventInput); 20387 20388 var events; 20389 20390 var i, event; 20391 20392 20393 20394 if (abstractEvent) { // not false (a valid input) 20395 20396 events = expandEvent(abstractEvent); 20397 20398 20399 20400 for (i = 0; i < events.length; i++) { 20401 20402 event = events[i]; 20403 20404 20405 20406 if (!event.source) { 20407 20408 if (stick) { 20409 20410 stickySource.events.push(event); 20411 20412 event.source = stickySource; 20413 20414 } 20415 20416 cache.push(event); 20417 20418 } 20419 20420 } 20421 20422 20423 20424 reportEvents(cache); 20425 20426 20427 20428 return events; 20429 20430 } 20431 20432 20433 20434 return []; 20435 20436 } 20437 20438 20439 20440 20441 20442 function removeEvents(filter) { 20443 20444 var eventID; 20445 20446 var i; 20447 20448 20449 20450 if (filter == null) { // null or undefined. remove all events 20451 20452 filter = function() { return true; }; // will always match 20453 20454 } 20455 20456 else if (!$.isFunction(filter)) { // an event ID 20457 20458 eventID = filter + ''; 20459 20460 filter = function(event) { 20461 20462 return event._id == eventID; 20463 20464 }; 20465 20466 } 20467 20468 20469 20470 // Purge event(s) from our local cache 20471 20472 cache = $.grep(cache, filter, true); // inverse=true 20473 20474 20475 20476 // Remove events from array sources. 20477 20478 // This works because they have been converted to official Event Objects up front. 20479 20480 // (and as a result, event._id has been calculated). 20481 20482 for (i=0; i<sources.length; i++) { 20483 20484 if ($.isArray(sources[i].events)) { 20485 20486 sources[i].events = $.grep(sources[i].events, filter, true); 20487 20488 } 20489 20490 } 20491 20492 20493 20494 reportEvents(cache); 20495 20496 } 20497 20498 20499 20500 20501 20502 function clientEvents(filter) { 20503 20504 if ($.isFunction(filter)) { 20505 20506 return $.grep(cache, filter); 20507 20508 } 20509 20510 else if (filter != null) { // not null, not undefined. an event ID 20511 20512 filter += ''; 20513 20514 return $.grep(cache, function(e) { 20515 20516 return e._id == filter; 20517 20518 }); 20519 20520 } 20521 20522 return cache; // else, return all 20523 20524 } 20525 20526 20527 20528 20529 20530 20531 20532 /* Event Normalization 20533 20534 -----------------------------------------------------------------------------*/ 20535 20536 20537 20538 20539 20540 // Given a raw object with key/value properties, returns an "abstract" Event object. 20541 20542 // An "abstract" event is an event that, if recurring, will not have been expanded yet. 20543
20544 // Will return `false` when input is invalid. 20545 20546 // `source` is optional 20547 20548 function buildEventFromInput(input, source) { 20549 20550 var out = {}; 20551 20552 var start, end; 20553 20554 var allDay; 20555 20556 20557 20558 if (options.eventDataTransform) { 20559 20560 input = options.eventDataTransform(input); 20561 20562 } 20563 20564 if (source && source.eventDataTransform) { 20565 20566 input = source.eventDataTransform(input); 20567 20568 } 20569 20570 20571 20572 // Copy all properties over to the resulting object. 20573 20574 // The special-case properties will be copied over afterwards. 20575 20576 $.extend(out, input); 20577 20578 20579 20580 if (source) { 20581 20582 out.source = source; 20583 20584 } 20585 20586 20587 20588 out._id = input._id || (input.id === undefined ? '_fc' + eventGUID++ : input.id + ''); 20589 20590 20591 20592 if (input.className) { 20593 20594 if (typeof input.className == 'string') { 20595 20596 out.className = input.className.split(/\s+/); 20597 20598 } 20599 20600 else { // assumed to be an array 20601 20602 out.className = input.className; 20603 20604 } 20605 20606 } 20607 20608 else { 20609 20610 out.className = []; 20611 20612 } 20613 20614 20615 20616 start = input.start || input.date; // "date" is an alias for "start" 20617 20618 end = input.end; 20619 20620 20621 20622 // parse as a time (Duration) if applicable 20623 20624 if (isTimeString(start)) { 20625 20626 start = moment.duration(start); 20627 20628 } 20629 20630 if (isTimeString(end)) { 20631 20632 end = moment.duration(end); 20633 20634 } 20635 20636 20637 20638 if (input.dow || moment.isDuration(start) || moment.isDuration(end)) { 20639 20640 20641 20642 // the event is "abstract" (recurring) so don't calculate exact start/end dates just yet 20643 20644 out.start = start ? moment.duration(start) : null; // will be a Duration or null 20645 20646 out.end = end ? moment.duration(end) : null; // will be a Duration or null 20647 20648 out._recurring = true; // our internal marker 20649 20650 } 20651 20652 else { 20653 20654 20655 20656 if (start) { 20657 20658 start = t.moment(start); 20659 20660 if (!start.isValid()) { 20661 20662 return false; 20663 20664 } 20665 20666 } 20667 20668 20669 20670 if (end) { 20671 20672 end = t.moment(end); 20673 20674 if (!end.isValid()) { 20675 20676 end = null; // let defaults take over 20677 20678 } 20679 20680 } 20681 20682 20683 20684 allDay = input.allDay; 20685 20686 if (allDay === undefined) { // still undefined? fallback to default 20687 20688 allDay = firstDefined( 20689 20690 source ? source.allDayDefault : undefined, 20691 20692 options.allDayDefault 20693 20694 ); 20695 20696 // still undefined? normalizeEventDates will calculate it 20697 20698 } 20699 20700 20701 20702 assignDatesToEvent(start, end, allDay, out); 20703 20704 } 20705 20706 20707 20708 return out; 20709 20710 } 20711 20712 20713 20714 20715 20716 // Normalizes and assigns the given dates to the given partially-formed event object. 20717 20718 // NOTE: mutates the given start/end moments. does not make a copy. 20719 20720 function assignDatesToEvent(start, end, allDay, event) { 20721 20722 event.start = start; 20723 20724 event.end = end; 20725 20726 event.allDay = allDay; 20727 20728 normalizeEventDates(event); 20729 20730 backupEventDates(event); 20731 20732 } 20733 20734 20735 20736 20737 20738 // Ensures proper values for allDay/start/end. Accepts an Event object, or a plain object with event-ish properties. 20739 20740 // NOTE: Will modify the given object. 20741 20742 function normalizeEventDates(eventProps) { 20743 20744 20745 20746 normalizeEventTimes(eventProps); 20747 20748 20749 20750 if (eventProps.end && !eventProps.end.isAfter(eventProps.start)) { 20751 20752 eventProps.end = null; 20753 20754 } 20755 20756 20757 20758 if (!eventProps.end) { 20759 20760 if (options.forceEventDuration) { 20761 20762 eventProps.end = t.getDefaultEventEnd(eventProps.allDay, eventProps.start); 20763 20764 } 20765 20766 else { 20767 20768 eventProps.end = null; 20769 20770 } 20771 20772 } 20773 20774 } 20775 20776 20777 20778 20779 20780 // Ensures the allDay property exists and the timeliness of the start/end dates are consistent 20781 20782 function normalizeEventTimes(eventProps) { 20783 20784 if (eventProps.allDay == null) { 20785 20786 eventProps.allDay = !(eventProps.start.hasTime() || (eventProps.end && eventProps.end.hasTime())); 20787 20788 } 20789 20790 20791 20792 if (eventProps.allDay) { 20793 20794 eventProps.start.stripTime(); 20795 20796 if (eventProps.end) { 20797 20798 // TODO: consider nextDayThreshold here? If so, will require a lot of testing and adjustment 20799 20800 eventProps.end.stripTime(); 20801 20802 } 20803 20804 } 20805 20806 else { 20807 20808 if (!eventProps.start.hasTime()) { 20809 20810 eventProps.start = t.applyTimezone(eventProps.start.time(0)); // will assign a 00:00 time 20811 20812 } 20813 20814 if (eventProps.end && !eventProps.end.hasTime()) { 20815 20816 eventProps.end = t.applyTimezone(eventProps.end.time(0)); // will assign a 00:00 time 20817 20818 } 20819 20820 } 20821 20822 } 20823 20824 20825 20826 20827 20828 // If the given event is a recurring event, break it down into an array of individual instances. 20829 20830 // If not a recurring event, return an array with the single original event. 20831
20832 // If given a falsy input (probably because of a failed buildEventFromInput call), returns an empty array. 20833 20834 // HACK: can override the recurring window by providing custom rangeStart/rangeEnd (for businessHours). 20835 20836 function expandEvent(abstractEvent, _rangeStart, _rangeEnd) { 20837 20838 var events = []; 20839 20840 var dowHash; 20841 20842 var dow; 20843 20844 var i; 20845 20846 var date; 20847 20848 var startTime, endTime; 20849 20850 var start, end; 20851 20852 var event; 20853 20854 20855 20856 _rangeStart = _rangeStart || rangeStart; 20857 20858 _rangeEnd = _rangeEnd || rangeEnd; 20859 20860 20861 20862 if (abstractEvent) { 20863 20864 if (abstractEvent._recurring) { 20865 20866 20867 20868 // make a boolean hash as to whether the event occurs on each day-of-week 20869 20870 if ((dow = abstractEvent.dow)) { 20871 20872 dowHash = {}; 20873 20874 for (i = 0; i < dow.length; i++) { 20875 20876 dowHash[dow[i]] = true; 20877 20878 } 20879 20880 } 20881 20882 20883 20884 // iterate through every day in the current range 20885 20886 date = _rangeStart.clone().stripTime(); // holds the date of the current day 20887 20888 while (date.isBefore(_rangeEnd)) { 20889 20890 20891 20892 if (!dowHash || dowHash[date.day()]) { // if everyday, or this particular day-of-week 20893 20894 20895 20896 startTime = abstractEvent.start; // the stored start and end properties are times (Durations) 20897 20898 endTime = abstractEvent.end; // " 20899 20900 start = date.clone(); 20901 20902 end = null; 20903 20904 20905 20906 if (startTime) { 20907 20908 start = start.time(startTime); 20909 20910 } 20911 20912 if (endTime) { 20913 20914 end = date.clone().time(endTime); 20915 20916 } 20917 20918 20919 20920 event = $.extend({}, abstractEvent); // make a copy of the original 20921 20922 assignDatesToEvent( 20923 20924 start, end, 20925 20926 !startTime && !endTime, // allDay? 20927 20928 event 20929 20930 ); 20931 20932 events.push(event); 20933 20934 } 20935 20936 20937 20938 date.add(1, 'days'); 20939 20940 } 20941 20942 } 20943 20944 else { 20945 20946 events.push(abstractEvent); // return the original event. will be a one-item array 20947 20948 } 20949 20950 } 20951 20952 20953 20954 return events; 20955 20956 } 20957 20958 20959 20960 20961 20962 20963 20964 /* Event Modification Math 20965 20966 -----------------------------------------------------------------------------------------*/ 20967 20968 20969 20970 20971 20972 // Modifies an event and all related events by applying the given properties. 20973 20974 // Special date-diffing logic is used for manipulation of dates. 20975 20976 // If `props` does not contain start/end dates, the updated values are assumed to be the event's current start/end. 20977 20978 // All date comparisons are done against the event's pristine _start and _end dates. 20979 20980 // Returns an object with delta information and a function to undo all operations. 20981 20982 // For making computations in a granularity greater than day/time, specify largeUnit. 20983 20984 // NOTE: The given `newProps` might be mutated for normalization purposes. 20985 20986 function mutateEvent(event, newProps, largeUnit) { 20987 20988 var miscProps = {}; 20989 20990 var oldProps; 20991 20992 var clearEnd; 20993 20994 var startDelta; 20995 20996 var endDelta; 20997 20998 var durationDelta; 20999 21000 var undoFunc; 21001 21002 21003 21004 // diffs the dates in the appropriate way, returning a duration 21005 21006 function diffDates(date1, date0) { // date1 - date0 21007 21008 if (largeUnit) { 21009 21010 return diffByUnit(date1, date0, largeUnit); 21011 21012 } 21013 21014 else if (newProps.allDay) { 21015 21016 return diffDay(date1, date0); 21017 21018 } 21019 21020 else { 21021 21022 return diffDayTime(date1, date0); 21023 21024 } 21025 21026 } 21027 21028 21029 21030 newProps = newProps || {}; 21031 21032 21033 21034 // normalize new date-related properties 21035 21036 if (!newProps.start) { 21037 21038 newProps.start = event.start.clone(); 21039 21040 } 21041 21042 if (newProps.end === undefined) { 21043 21044 newProps.end = event.end ? event.end.clone() : null; 21045 21046 } 21047 21048 if (newProps.allDay == null) { // is null or undefined? 21049 21050 newProps.allDay = event.allDay; 21051 21052 } 21053 21054 normalizeEventDates(newProps); 21055 21056 21057 21058 // create normalized versions of the original props to compare against 21059 21060 // need a real end value, for diffing 21061 21062 oldProps = { 21063 21064 start: event._start.clone(), 21065 21066 end: event._end ? event._end.clone() : t.getDefaultEventEnd(event._allDay, event._start), 21067 21068 allDay: newProps.allDay // normalize the dates in the same regard as the new properties 21069 21070 }; 21071 21072 normalizeEventDates(oldProps); 21073 21074 21075 21076 // need to clear the end date if explicitly changed to null 21077 21078 clearEnd = event._end !== null && newProps.end === null; 21079 21080 21081 21082 // compute the delta for moving the start date 21083 21084 startDelta = diffDates(newProps.start, oldProps.start); 21085 21086 21087 21088 // compute the delta for moving the end date 21089 21090 if (newProps.end) { 21091 21092 endDelta = diffDates(newProps.end, oldProps.end); 21093 21094 durationDelta = endDelta.subtract(startDelta); 21095 21096 } 21097 21098 else { 21099 21100 durationDelta = null; 21101 21102 } 21103 21104 21105 21106 // gather all non-date-related properties 21107 21108 $.each(newProps, function(name, val) { 21109 21110 if (isMiscEventPropName(name)) { 21111 21112 if (val !== undefined) { 21113 21114 miscProps[name] = val; 21115 21116 } 21117 21118 } 21119 21120 }); 21121 21122 21123 21124 // apply the operations to the event and all related events 21125 21126 undoFunc = mutateEvents( 21127 21128 clientEvents(event._id), // get events with this ID 21129 21130 clearEnd, 21131 21132 newProps.allDay, 21133 21134 startDelta, 21135 21136 durationDelta, 21137 21138 miscProps 21139 21140 ); 21141 21142 21143 21144 return { 21145 21146 dateDelta: startDelta, 21147 21148 durationDelta: durationDelta, 21149 21150 undo: undoFunc 21151 21152 }; 21153 21154 } 21155 21156 21157 21158 21159 21160 // Modifies an array of events in the following ways (operations are in order): 21161 21162 // - clear the event's `end` 21163 21164 // - convert the event to allDay 21165 21166 // - add `dateDelta` to the start and end 21167 21168 // - add `durationDelta` to the event's duration 21169 21170 // - assign `miscProps` to the event 21171 21172 // 21173 21174 // Returns a function that can be called to undo all the operations. 21175 21176 // 21177 21178 // TODO: don't use so many closures. possible memory issues when lots of events with same ID. 21179 21180 // 21181 21182 function mutateEvents(events, clearEnd, allDay, dateDelta, durationDelta, miscProps) { 21183 21184 var isAmbigTimezone = t.getIsAmbigTimezone(); 21185
21186 var undoFunctions = []; 21187 21188 21189 21190 // normalize zero-length deltas to be null 21191 21192 if (dateDelta && !dateDelta.valueOf()) { dateDelta = null; } 21193 21194 if (durationDelta && !durationDelta.valueOf()) { durationDelta = null; } 21195 21196 21197 21198 $.each(events, function(i, event) { 21199 21200 var oldProps; 21201 21202 var newProps; 21203 21204 21205 21206 // build an object holding all the old values, both date-related and misc. 21207 21208 // for the undo function. 21209 21210 oldProps = { 21211 21212 start: event.start.clone(), 21213 21214 end: event.end ? event.end.clone() : null, 21215 21216 allDay: event.allDay 21217 21218 }; 21219 21220 $.each(miscProps, function(name) { 21221 21222 oldProps[name] = event[name]; 21223 21224 }); 21225 21226 21227 21228 // new date-related properties. work off the original date snapshot. 21229 21230 // ok to use references because they will be thrown away when backupEventDates is called. 21231 21232 newProps = { 21233 21234 start: event._start, 21235 21236 end: event._end, 21237 21238 allDay: allDay // normalize the dates in the same regard as the new properties 21239 21240 }; 21241 21242 normalizeEventDates(newProps); // massages start/end/allDay 21243 21244 21245 21246 // strip or ensure the end date 21247 21248 if (clearEnd) { 21249 21250 newProps.end = null; 21251 21252 } 21253 21254 else if (durationDelta && !newProps.end) { // the duration translation requires an end date 21255 21256 newProps.end = t.getDefaultEventEnd(newProps.allDay, newProps.start); 21257 21258 } 21259 21260 21261 21262 if (dateDelta) { 21263 21264 newProps.start.add(dateDelta); 21265 21266 if (newProps.end) { 21267 21268 newProps.end.add(dateDelta); 21269 21270 } 21271 21272 } 21273 21274 21275 21276 if (durationDelta) { 21277 21278 newProps.end.add(durationDelta); // end already ensured above 21279 21280 } 21281 21282 21283 21284 // if the dates have changed, and we know it is impossible to recompute the 21285 21286 // timezone offsets, strip the zone. 21287 21288 if ( 21289 21290 isAmbigTimezone && 21291 21292 !newProps.allDay && 21293 21294 (dateDelta || durationDelta) 21295 21296 ) { 21297 21298 newProps.start.stripZone(); 21299 21300 if (newProps.end) { 21301 21302 newProps.end.stripZone(); 21303 21304 } 21305 21306 } 21307 21308 21309 21310 $.extend(event, miscProps, newProps); // copy over misc props, then date-related props 21311 21312 backupEventDates(event); // regenerate internal _start/_end/_allDay 21313 21314 21315 21316 undoFunctions.push(function() { 21317 21318 $.extend(event, oldProps); 21319 21320 backupEventDates(event); // regenerate internal _start/_end/_allDay 21321 21322 }); 21323 21324 }); 21325 21326 21327 21328 return function() { 21329 21330 for (var i = 0; i < undoFunctions.length; i++) { 21331 21332 undoFunctions[i](); 21333 21334 } 21335 21336 }; 21337 21338 } 21339 21340 21341 21342 21343 21344 /* Business Hours 21345 21346 -----------------------------------------------------------------------------------------*/ 21347 21348 21349 21350 t.getBusinessHoursEvents = getBusinessHoursEvents; 21351 21352 21353 21354 21355 21356 // Returns an array of events as to when the business hours occur in the given view. 21357 21358 // Abuse of our event system :( 21359 21360 function getBusinessHoursEvents(wholeDay) { 21361 21362 var optionVal = options.businessHours; 21363 21364 var defaultVal = { 21365 21366 className: 'fc-nonbusiness', 21367 21368 start: '09:00', 21369 21370 end: '17:00', 21371 21372 dow: [ 1, 2, 3, 4, 5 ], // monday - friday 21373 21374 rendering: 'inverse-background' 21375 21376 }; 21377 21378 var view = t.getView(); 21379 21380 var eventInput; 21381 21382 21383 21384 if (optionVal) { // `true` (which means "use the defaults") or an override object 21385 21386 eventInput = $.extend( 21387 21388 {}, // copy to a new object in either case 21389 21390 defaultVal, 21391 21392 typeof optionVal === 'object' ? optionVal : {} // override the defaults 21393 21394 ); 21395 21396 } 21397 21398 21399 21400 if (eventInput) { 21401 21402 21403 21404 // if a whole-day series is requested, clear the start/end times 21405 21406 if (wholeDay) { 21407 21408 eventInput.start = null; 21409 21410 eventInput.end = null; 21411 21412 } 21413 21414 21415 21416 return expandEvent( 21417 21418 buildEventFromInput(eventInput), 21419 21420 view.start, 21421 21422 view.end 21423 21424 ); 21425 21426 } 21427 21428 21429 21430 return []; 21431 21432 } 21433 21434 21435 21436 21437 21438 /* Overlapping / Constraining 21439 21440 -----------------------------------------------------------------------------------------*/ 21441 21442 21443 21444 t.isEventSpanAllowed = isEventSpanAllowed; 21445 21446 t.isExternalSpanAllowed = isExternalSpanAllowed; 21447 21448 t.isSelectionSpanAllowed = isSelectionSpanAllowed; 21449 21450 21451 21452 21453 21454 // Determines if the given event can be relocated to the given span (unzoned start/end with other misc data) 21455 21456 function isEventSpanAllowed(span, event) { 21457 21458 var source = event.source || {}; 21459 21460 var constraint = firstDefined( 21461 21462 event.constraint, 21463 21464 source.constraint, 21465 21466 options.eventConstraint 21467 21468 ); 21469 21470 var overlap = firstDefined( 21471 21472 event.overlap, 21473 21474 source.overlap, 21475 21476 options.eventOverlap 21477 21478 ); 21479 21480 return isSpanAllowed(span, constraint, overlap, event); 21481 21482 } 21483 21484 21485 21486 21487 21488 // Determines if an external event can be relocated to the given span (unzoned start/end with other misc data) 21489 21490 function isExternalSpanAllowed(eventSpan, eventLocation, eventProps) { 21491 21492 var eventInput; 21493 21494 var event; 21495 21496 21497 21498 // note: very similar logic is in View's reportExternalDrop 21499 21500 if (eventProps) { 21501 21502 eventInput = $.extend({}, eventProps, eventLocation); 21503 21504 event = expandEvent(buildEventFromInput(eventInput))[0]; 21505 21506 } 21507 21508 21509 21510 if (event) { 21511 21512 return isEventSpanAllowed(eventSpan, event); 21513 21514 } 21515 21516 else { // treat it as a selection 21517 21518 21519 21520 return isSelectionSpanAllowed(eventSpan); 21521 21522 } 21523 21524 } 21525 21526 21527 21528 21529 21530 // Determines the given span (unzoned start/end with other misc data) can be selected. 21531 21532 function isSelectionSpanAllowed(span) { 21533 21534 return isSpanAllowed(span, options.selectConstraint, options.selectOverlap); 21535 21536 } 21537 21538 21539 21540 21541 21542 // Returns true if the given span (caused by an event drop/resize or a selection) is allowed to exist 21543 21544 // according to the constraint/overlap settings. 21545 21546 // `event` is not required if checking a selection. 21547 21548 function isSpanAllowed(span, constraint, overlap, event) { 21549 21550 var constraintEvents; 21551 21552 var anyContainment; 21553 21554 var peerEvents; 21555 21556 var i, peerEvent; 21557 21558 var peerOverlap; 21559 21560 21561 21562 // the range must be fully contained by at least one of produced constraint events 21563 21564 if (constraint != null) { 21565 21566 21567 21568 // not treated as an event! intermediate data structure 21569 21570 // TODO: use ranges in the future 21571 21572 constraintEvents = constraintToEvents(constraint); 21573 21574 21575 21576 anyContainment = false;
21577 21578 for (i = 0; i < constraintEvents.length; i++) { 21579 21580 if (eventContainsRange(constraintEvents[i], span)) { 21581 21582 anyContainment = true; 21583 21584 break; 21585 21586 } 21587 21588 } 21589 21590 21591 21592 if (!anyContainment) { 21593 21594 return false; 21595 21596 } 21597 21598 } 21599 21600 21601 21602 peerEvents = t.getPeerEvents(span, event); 21603 21604 21605 21606 for (i = 0; i < peerEvents.length; i++) { 21607 21608 peerEvent = peerEvents[i]; 21609 21610 21611 21612 // there needs to be an actual intersection before disallowing anything 21613 21614 if (eventIntersectsRange(peerEvent, span)) { 21615 21616 21617 21618 // evaluate overlap for the given range and short-circuit if necessary 21619 21620 if (overlap === false) { 21621 21622 return false; 21623 21624 } 21625 21626 // if the event's overlap is a test function, pass the peer event in question as the first param 21627 21628 else if (typeof overlap === 'function' && !overlap(peerEvent, event)) { 21629 21630 return false; 21631 21632 } 21633 21634 21635 21636 // if we are computing if the given range is allowable for an event, consider the other event's 21637 21638 // EventObject-specific or Source-specific `overlap` property 21639 21640 if (event) { 21641 21642 peerOverlap = firstDefined( 21643 21644 peerEvent.overlap, 21645 21646 (peerEvent.source || {}).overlap 21647 21648 // we already considered the global `eventOverlap` 21649 21650 ); 21651 21652 if (peerOverlap === false) { 21653 21654 return false; 21655 21656 } 21657 21658 // if the peer event's overlap is a test function, pass the subject event as the first param 21659 21660 if (typeof peerOverlap === 'function' && !peerOverlap(event, peerEvent)) { 21661 21662 return false; 21663 21664 } 21665 21666 } 21667 21668 } 21669 21670 } 21671 21672 21673 21674 return true; 21675 21676 } 21677 21678 21679 21680 21681 21682 // Given an event input from the API, produces an array of event objects. Possible event inputs: 21683 21684 // 'businessHours' 21685 21686 // An event ID (number or string) 21687 21688 // An object with specific start/end dates or a recurring event (like what businessHours accepts) 21689 21690 function constraintToEvents(constraintInput) { 21691 21692 21693 21694 if (constraintInput === 'businessHours') { 21695 21696 return getBusinessHoursEvents(); 21697 21698 } 21699 21700 21701 21702 if (typeof constraintInput === 'object') { 21703 21704 return expandEvent(buildEventFromInput(constraintInput)); 21705 21706 } 21707 21708 21709 21710 return clientEvents(constraintInput); // probably an ID 21711 21712 } 21713 21714 21715 21716 21717 21718 // Does the event's date range fully contain the given range? 21719 21720 // start/end already assumed to have stripped zones :( 21721 21722 function eventContainsRange(event, range) { 21723 21724 var eventStart = event.start.clone().stripZone(); 21725 21726 var eventEnd = t.getEventEnd(event).stripZone(); 21727 21728 21729 21730 return range.start >= eventStart && range.end <= eventEnd; 21731 21732 } 21733 21734 21735 21736 21737 21738 // Does the event's date range intersect with the given range? 21739 21740 // start/end already assumed to have stripped zones :( 21741 21742 function eventIntersectsRange(event, range) { 21743 21744 var eventStart = event.start.clone().stripZone(); 21745 21746 var eventEnd = t.getEventEnd(event).stripZone(); 21747 21748 21749 21750 return range.start < eventEnd && range.end > eventStart; 21751 21752 } 21753 21754 21755 21756 21757 21758 t.getEventCache = function() { 21759 21760 return cache; 21761 21762 }; 21763 21764 21765 21766 } 21767 21768 21769 21770 21771 21772// Returns a list of events that the given event should be compared against when being considered for a move to 21773 21774// the specified span. Attached to the Calendar's prototype because EventManager is a mixin for a Calendar. 21775 21776 Calendar.prototype.getPeerEvents = function(span, event) { 21777 21778 var cache = this.getEventCache(); 21779 21780 var peerEvents = []; 21781 21782 var i, otherEvent; 21783 21784 21785 21786 for (i = 0; i < cache.length; i++) { 21787 21788 otherEvent = cache[i]; 21789 21790 if ( 21791 21792 !event || 21793 21794 event._id !== otherEvent._id // don't compare the event to itself or other related [repeating] events 21795 21796 ) { 21797 21798 peerEvents.push(otherEvent); 21799 21800 } 21801 21802 } 21803 21804 21805 21806 return peerEvents; 21807 21808 }; 21809 21810 21811 21812 21813 21814// updates the "backup" properties, which are preserved in order to compute diffs later on. 21815 21816 function backupEventDates(event) { 21817 21818 event._allDay = event.allDay; 21819 21820 event._start = event.start.clone(); 21821 21822 event._end = event.end ? event.end.clone() : null; 21823 21824 } 21825 21826 21827 21828 ;; 21829 21830 21831 21832 /* An abstract class for the "basic" views, as well as month view. Renders one or more rows of day cells. 21833 21834 ----------------------------------------------------------------------------------------------------------------------*/ 21835 21836// It is a manager for a DayGrid subcomponent, which does most of the heavy lifting. 21837 21838// It is responsible for managing width/height. 21839 21840 21841 21842 var BasicView = FC.BasicView = View.extend({ 21843 21844 21845 21846 dayGridClass: DayGrid, // class the dayGrid will be instantiated from (overridable by subclasses) 21847 21848 dayGrid: null, // the main subcomponent that does most of the heavy lifting 21849 21850 21851 21852 dayNumbersVisible: false, // display day numbers on each day cell? 21853 21854 weekNumbersVisible: false, // display week numbers along the side? 21855 21856 21857 21858 weekNumberWidth: null, // width of all the week-number cells running down the side 21859 21860 21861 21862 headContainerEl: null, // div that hold's the dayGrid's rendered date header 21863 21864 headRowEl: null, // the fake row element of the day-of-week header 21865 21866 21867 21868 21869 21870 initialize: function() { 21871 21872 this.dayGrid = this.instantiateDayGrid(); 21873 21874 }, 21875 21876 21877 21878 21879 21880 // Generates the DayGrid object this view needs. Draws from this.dayGridClass 21881 21882 instantiateDayGrid: function() { 21883 21884 // generate a subclass on the fly with BasicView-specific behavior 21885 21886 // TODO: cache this subclass 21887 21888 var subclass = this.dayGridClass.extend(basicDayGridMethods); 21889 21890 21891 21892 return new subclass(this); 21893 21894 }, 21895 21896 21897 21898 21899 21900 // Sets the display range and computes all necessary dates 21901 21902 setRange: function(range) { 21903 21904 View.prototype.setRange.call(this, range); // call the super-method 21905 21906 21907 21908 this.dayGrid.breakOnWeeks = /year|month|week/.test(this.intervalUnit); // do before setRange 21909 21910 this.dayGrid.setRange(range); 21911 21912 }, 21913 21914 21915 21916 21917 21918 // Compute the value to feed into setRange. Overrides superclass. 21919 21920 computeRange: function(date) { 21921 21922 var range = View.prototype.computeRange.call(this, date); // get value from the super-method 21923 21924 21925 21926 // year and month views should be aligned with weeks. this is already done for week 21927 21928 if (/year|month/.test(range.intervalUnit)) { 21929 21930 range.start.startOf('week'); 21931 21932 range.start = this.skipHiddenDays(range.start); 21933 21934 21935 21936 // make end-of-week if not already 21937 21938 if (range.end.weekday()) { 21939 21940 range.end.add(1, 'week').startOf('week'); 21941 21942 range.end = this.skipHiddenDays(range.end, -1, true); // exclusively move backwards 21943 21944 } 21945 21946 } 21947 21948 21949 21950 return range; 21951 21952 }, 21953 21954 21955 21956 21957 21958 // Renders the view into `this.el`, which should already be assigned 21959 21960 renderDates: function() { 21961 21962 21963 21964 this.dayNumbersVisible = this.dayGrid.rowCnt > 1; // TODO: make grid responsible 21965 21966 this.weekNumbersVisible = this.opt('weekNumbers'); 21967 21968 this.dayGrid.numbersVisible = this.dayNumbersVisible || this.weekNumbersVisible; 21969 21970 21971 21972 this.el.addClass('fc-basic-view').html(this.renderSkeletonHtml()); 21973 21974 this.renderHead(); 21975 21976 21977 21978 this.scrollerEl = this.el.find('.fc-day-grid-container'); 21979 21980 21981 21982 this.dayGrid.setElement(this.el.find('.fc-day-grid')); 21983 21984 this.dayGrid.renderDates(this.hasRigidRows()); 21985 21986 }, 21987 21988 21989 21990 21991 21992 // render the day-of-week headers 21993 21994 renderHead: function() { 21995 21996 this.headContainerEl = 21997 21998 this.el.find('.fc-head-container') 21999 22000 .html(this.dayGrid.renderHeadHtml()); 22001 22002 this.headRowEl = this.headContainerEl.find('.fc-row'); 22003 22004 }, 22005 22006 22007 22008 22009 22010 // Unrenders the content of the view. Since we haven't separated skeleton rendering from date rendering, 22011 22012 // always completely kill the dayGrid's rendering. 22013 22014 unrenderDates: function() { 22015 22016 this.dayGrid.unrenderDates(); 22017 22018 this.dayGrid.removeElement(); 22019 22020 }, 22021 22022 22023 22024 22025 22026 renderBusinessHours: function() { 22027 22028 this.dayGrid.renderBusinessHours(); 22029 22030 }, 22031 22032 22033 22034 22035 22036 // Builds the HTML skeleton for the view. 22037 22038 // The day-grid component will render inside of a container defined by this HTML. 22039 22040 renderSkeletonHtml: function() { 22041 22042 return '' + 22043 22044 '<table>' + 22045 22046 '<thead class="fc-head">' + 22047 22048 '<tr>' + 22049 22050 '<td class="fc-head-container ' + this.widgetHeaderClass + '"></td>' + 22051 22052 '</tr>' + 22053 22054 '</thead>' + 22055 22056 '<tbody class="fc-body">' + 22057 22058 '<tr>' + 22059 22060 '<td class="' + this.widgetContentClass + '">' + 22061 22062 '<div class="fc-day-grid-container">' + 22063 22064 '<div class="fc-day-grid"/>' + 22065 22066 '</div>' + 22067 22068 '</td>' + 22069 22070 '</tr>' + 22071 22072 '</tbody>' + 22073 22074 '</table>'; 22075 22076 }, 22077 22078 22079 22080 22081 22082 // Generates an HTML attribute string for setting the width of the week number column, if it is known 22083 22084 weekNumberStyleAttr: function() { 22085 22086 if (this.weekNumberWidth !== null) { 22087 22088 return 'style="width:' + this.weekNumberWidth + 'px"'; 22089 22090 } 22091 22092 return ''; 22093 22094 }, 22095 22096 22097 22098 22099 22100 // Determines whether each row should have a constant height 22101 22102 hasRigidRows: function() { 22103 22104 var eventLimit = this.opt('eventLimit'); 22105 22106 return eventLimit && typeof eventLimit !== 'number'; 22107 22108 }, 22109 22110 22111 22112 22113 22114 /* Dimensions 22115 22116 ------------------------------------------------------------------------------------------------------------------*/ 22117 22118 22119 22120 22121 22122 // Refreshes the horizontal dimensions of the view 22123 22124 updateWidth: function() { 22125 22126 if (this.weekNumbersVisible) { 22127 22128 // Make sure all week number cells running down the side have the same width. 22129 22130 // Record the width for cells created later. 22131 22132 this.weekNumberWidth = matchCellWidths( 22133 22134 this.el.find('.fc-week-number') 22135 22136 ); 22137 22138 } 22139 22140 }, 22141 22142 22143 22144 22145 22146 // Adjusts the vertical dimensions of the view to the specified values 22147 22148 setHeight: function(totalHeight, isAuto) { 22149 22150 var eventLimit = this.opt('eventLimit'); 22151 22152 var scrollerHeight; 22153 22154 22155 22156 // reset all heights to be natural 22157 22158 unsetScroller(this.scrollerEl); 22159 22160 uncompensateScroll(this.headRowEl); 22161 22162 22163 22164 this.dayGrid.removeSegPopover(); // kill the "more" popover if displayed 22165 22166 22167 22168 // is the event limit a constant level number? 22169 22170 if (eventLimit && typeof eventLimit === 'number') { 22171 22172 this.dayGrid.limitRows(eventLimit); // limit the levels first so the height can redistribute after 22173 22174 } 22175 22176 22177 22178 scrollerHeight = this.computeScrollerHeight(totalHeight); 22179 22180 this.setGridHeight(scrollerHeight, isAuto); 22181 22182 22183 22184 // is the event limit dynamically calculated? 22185 22186 if (eventLimit && typeof eventLimit !== 'number') { 22187 22188 this.dayGrid.limitRows(eventLimit); // limit the levels after the grid's row heights have been set 22189 22190 } 22191 22192 22193 22194 if (!isAuto && setPotentialScroller(this.scrollerEl, scrollerHeight)) { // using scrollbars? 22195 22196 22197 22198 compensateScroll(this.headRowEl, getScrollbarWidths(this.scrollerEl)); 22199 22200 22201 22202 // doing the scrollbar compensation might have created text overflow which created more height. redo 22203 22204 scrollerHeight = this.computeScrollerHeight(totalHeight); 22205 22206 this.scrollerEl.height(scrollerHeight); 22207 22208 } 22209 22210 }, 22211 22212 22213 22214 22215 22216 // Sets the height of just the DayGrid component in this view 22217 22218 setGridHeight: function(height, isAuto) { 22219 22220 if (isAuto) { 22221 22222 undistributeHeight(this.dayGrid.rowEls); // let the rows be their natural height with no expanding 22223 22224 } 22225 22226 else { 22227 22228 distributeHeight(this.dayGrid.rowEls, height, true); // true = compensate for height-hogging rows 22229 22230 } 22231 22232 }, 22233 22234 22235 22236 22237 22238 /* Hit Areas 22239 22240 ------------------------------------------------------------------------------------------------------------------*/ 22241 22242 // forward all hit-related method calls to dayGrid 22243 22244 22245 22246 22247 22248 prepareHits: function() { 22249 22250 this.dayGrid.prepareHits(); 22251 22252 }, 22253 22254 22255 22256 22257 22258 releaseHits: function() { 22259 22260 this.dayGrid.releaseHits(); 22261 22262 }, 22263 22264 22265 22266 22267 22268 queryHit: function(left, top) { 22269 22270 return this.dayGrid.queryHit(left, top); 22271 22272 }, 22273 22274 22275 22276 22277 22278 getHitSpan: function(hit) { 22279 22280 return this.dayGrid.getHitSpan(hit); 22281 22282 }, 22283 22284 22285 22286 22287 22288 getHitEl: function(hit) { 22289 22290 return this.dayGrid.getHitEl(hit); 22291 22292 }, 22293 22294 22295 22296 22297 22298 /* Events 22299 22300 ------------------------------------------------------------------------------------------------------------------*/ 22301 22302 22303 22304 22305 22306 // Renders the given events onto the view and populates the segments array 22307 22308 renderEvents: function(events) { 22309 22310 this.dayGrid.renderEvents(events); 22311 22312 22313 22314 this.updateHeight(); // must compensate for events that overflow the row 22315 22316 }, 22317 22318 22319 22320 22321 22322 // Retrieves all segment objects that are rendered in the view 22323 22324 getEventSegs: function() { 22325 22326 return this.dayGrid.getEventSegs(); 22327 22328 }, 22329 22330 22331 22332 22333 22334 // Unrenders all event elements and clears internal segment data 22335 22336 unrenderEvents: function() { 22337 22338 this.dayGrid.unrenderEvents(); 22339 22340 22341 22342 // we DON'T need to call updateHeight() because: 22343 22344 // A) a renderEvents() call always happens after this, which will eventually call updateHeight() 22345 22346 // B) in IE8, this causes a flash whenever events are rerendered 22347 22348 }, 22349 22350 22351 22352 22353 22354 /* Dragging (for both events and external elements) 22355 22356 ------------------------------------------------------------------------------------------------------------------*/ 22357 22358 22359 22360 22361 22362 // A returned value of `true` signals that a mock "helper" event has been rendered. 22363 22364 renderDrag: function(dropLocation, seg) { 22365 22366 return this.dayGrid.renderDrag(dropLocation, seg); 22367 22368 }, 22369 22370 22371 22372 22373 22374 unrenderDrag: function() { 22375 22376 this.dayGrid.unrenderDrag(); 22377 22378 }, 22379 22380 22381 22382 22383
22384 /* Selection 22385 22386 ------------------------------------------------------------------------------------------------------------------*/ 22387 22388 22389 22390 22391 22392 // Renders a visual indication of a selection 22393 22394 renderSelection: function(span) { 22395 22396 this.dayGrid.renderSelection(span); 22397 22398 }, 22399 22400 22401 22402 22403 22404 // Unrenders a visual indications of a selection 22405 22406 unrenderSelection: function() { 22407 22408 this.dayGrid.unrenderSelection(); 22409 22410 } 22411 22412 22413 22414 }); 22415 22416 22417 22418 22419 22420// Methods that will customize the rendering behavior of the BasicView's dayGrid 22421 22422 var basicDayGridMethods = { 22423 22424 22425 22426 22427 22428 // Generates the HTML that will go before the day-of week header cells 22429 22430 renderHeadIntroHtml: function() { 22431 22432 var view = this.view; 22433 22434 22435 22436 if (view.weekNumbersVisible) { 22437 22438 return '' + 22439 22440 '<th class="fc-week-number ' + view.widgetHeaderClass + '" ' + view.weekNumberStyleAttr() + '>' + 22441 22442 '<span>' + // needed for matchCellWidths 22443 22444 htmlEscape(view.opt('weekNumberTitle')) + 22445 22446 '</span>' + 22447 22448 '</th>'; 22449 22450 } 22451 22452 22453 22454 return ''; 22455 22456 }, 22457 22458 22459 22460 22461 22462 // Generates the HTML that will go before content-skeleton cells that display the day/week numbers 22463 22464 renderNumberIntroHtml: function(row) { 22465 22466 var view = this.view; 22467 22468 22469 22470 if (view.weekNumbersVisible) { 22471 22472 return '' + 22473 22474 '<td class="fc-week-number" ' + view.weekNumberStyleAttr() + '>' + 22475 22476 '<span>' + // needed for matchCellWidths 22477 22478 this.getCellDate(row, 0).format('w') + 22479 22480 '</span>' + 22481 22482 '</td>'; 22483 22484 } 22485 22486 22487 22488 return ''; 22489 22490 }, 22491 22492 22493 22494 22495 22496 // Generates the HTML that goes before the day bg cells for each day-row 22497 22498 renderBgIntroHtml: function() { 22499 22500 var view = this.view; 22501 22502 22503 22504 if (view.weekNumbersVisible) { 22505 22506 return '<td class="fc-week-number ' + view.widgetContentClass + '" ' + 22507 22508 view.weekNumberStyleAttr() + '></td>'; 22509 22510 } 22511 22512 22513 22514 return ''; 22515 22516 }, 22517 22518 22519 22520 22521 22522 // Generates the HTML that goes before every other type of row generated by DayGrid. 22523 22524 // Affects helper-skeleton and highlight-skeleton rows. 22525 22526 renderIntroHtml: function() { 22527 22528 var view = this.view; 22529 22530 22531 22532 if (view.weekNumbersVisible) { 22533 22534 return '<td class="fc-week-number" ' + view.weekNumberStyleAttr() + '></td>'; 22535 22536 } 22537 22538 22539 22540 return ''; 22541 22542 } 22543 22544 22545 22546 }; 22547 22548 22549 22550 ;; 22551 22552 22553 22554 /* A month view with day cells running in rows (one-per-week) and columns 22555 22556 ----------------------------------------------------------------------------------------------------------------------*/ 22557 22558 22559 22560 var MonthView = FC.MonthView = BasicView.extend({ 22561 22562 22563 22564 // Produces information about what range to display 22565 22566 computeRange: function(date) { 22567 22568 var range = BasicView.prototype.computeRange.call(this, date); // get value from super-method 22569 22570 var rowCnt; 22571 22572 22573 22574 // ensure 6 weeks 22575 22576 if (this.isFixedWeeks()) { 22577 22578 rowCnt = Math.ceil(range.end.diff(range.start, 'weeks', true)); // could be partial weeks due to hiddenDays 22579 22580 range.end.add(6 - rowCnt, 'weeks'); 22581 22582 } 22583 22584 22585 22586 return range; 22587 22588 }, 22589 22590 22591 22592 22593 22594 // Overrides the default BasicView behavior to have special multi-week auto-height logic 22595 22596 setGridHeight: function(height, isAuto) { 22597 22598 22599 22600 isAuto = isAuto || this.opt('weekMode') === 'variable'; // LEGACY: weekMode is deprecated 22601 22602 22603 22604 // if auto, make the height of each row the height that it would be if there were 6 weeks 22605 22606 if (isAuto) { 22607 22608 height *= this.rowCnt / 6; 22609 22610 } 22611 22612 22613 22614 distributeHeight(this.dayGrid.rowEls, height, !isAuto); // if auto, don't compensate for height-hogging rows 22615 22616 }, 22617 22618 22619 22620 22621 22622 isFixedWeeks: function() { 22623 22624 var weekMode = this.opt('weekMode'); // LEGACY: weekMode is deprecated 22625 22626 if (weekMode) { 22627 22628 return weekMode === 'fixed'; // if any other type of weekMode, assume NOT fixed 22629 22630 } 22631 22632 22633 22634 return this.opt('fixedWeekCount'); 22635 22636 } 22637 22638 22639 22640 }); 22641 22642 22643 22644 ;; 22645 22646 22647 22648 fcViews.basic = { 22649 22650 'class': BasicView 22651 22652 }; 22653 22654 22655 22656 fcViews.basicDay = { 22657 22658 type: 'basic', 22659 22660 duration: { days: 1 } 22661 22662 }; 22663 22664 22665 22666 fcViews.basicWeek = { 22667 22668 type: 'basic', 22669 22670 duration: { weeks: 1 } 22671 22672 }; 22673 22674 22675 22676 fcViews.month = { 22677 22678 'class': MonthView, 22679 22680 duration: { months: 1 }, // important for prev/next 22681 22682 defaults: { 22683 22684 fixedWeekCount: true 22685 22686 } 22687 22688 }; 22689 22690 ;; 22691 22692 22693 22694 /* An abstract class for all agenda-related views. Displays one more columns with time slots running vertically. 22695 22696 ----------------------------------------------------------------------------------------------------------------------*/ 22697 22698// Is a manager for the TimeGrid subcomponent and possibly the DayGrid subcomponent (if allDaySlot is on). 22699 22700// Responsible for managing width/height. 22701 22702 22703 22704 var AgendaView = FC.AgendaView = View.extend({ 22705 22706 22707 22708 timeGridClass: TimeGrid, // class used to instantiate the timeGrid. subclasses can override 22709 22710 timeGrid: null, // the main time-grid subcomponent of this view 22711 22712 22713 22714 dayGridClass: DayGrid, // class used to instantiate the dayGrid. subclasses can override 22715 22716 dayGrid: null, // the "all-day" subcomponent. if all-day is turned off, this will be null 22717 22718 22719 22720 axisWidth: null, // the width of the time axis running down the side 22721 22722 22723 22724 headContainerEl: null, // div that hold's the timeGrid's rendered date header 22725 22726 noScrollRowEls: null, // set of fake row elements that must compensate when scrollerEl has scrollbars 22727 22728 22729 22730 // when the time-grid isn't tall enough to occupy the given he
22730ight, we render an <hr> underneath 22731 22732 bottomRuleEl: null, 22733 22734 bottomRuleHeight: null, 22735 22736 22737 22738 22739 22740 initialize: function() { 22741 22742 this.timeGrid = this.instantiateTimeGrid(); 22743 22744 22745 22746 if (this.opt('allDaySlot')) { // should we display the "all-day" area? 22747 22748 this.dayGrid = this.instantiateDayGrid(); // the all-day subcomponent of this view 22749 22750 } 22751 22752 }, 22753 22754 22755 22756 22757 22758 // Instantiates the TimeGrid object this view needs. Draws from this.timeGridClass 22759 22760 instantiateTimeGrid: function() { 22761 22762 var subclass = this.timeGridClass.extend(agendaTimeGridMethods); 22763 22764 22765 22766 return new subclass(this); 22767 22768 }, 22769 22770 22771 22772 22773 22774 // Instantiates the DayGrid object this view might need. Draws from this.dayGridClass 22775 22776 instantiateDayGrid: function() { 22777 22778 var subclass = this.dayGridClass.extend(agendaDayGridMethods); 22779 22780 22781 22782 return new subclass(this); 22783 22784 }, 22785 22786 22787 22788 22789 22790 /* Rendering 22791 22792 ------------------------------------------------------------------------------------------------------------------*/ 22793 22794 22795 22796 22797 22798 // Sets the display range and computes all necessary dates 22799 22800 setRange: function(range) { 22801 22802 View.prototype.setRange.call(this, range); // call the super-method 22803 22804 22805 22806 this.timeGrid.setRange(range); 22807 22808 if (this.dayGrid) { 22809 22810 this.dayGrid.setRange(range); 22811 22812 } 22813 22814 }, 22815 22816 22817 22818 22819 22820 // Renders the view into `this.el`, which has already been assigned 22821 22822 renderDates: function() { 22823 22824 22825 22826 this.el.addClass('fc-agenda-view').html(this.renderSkeletonHtml()); 22827 22828 this.renderHead(); 22829 22830 22831 22832 // the element that wraps the time-grid that will probably scroll 22833 22834 this.scrollerEl = this.el.find('.fc-time-grid-container'); 22835 22836 22837 22838 this.timeGrid.setElement(this.el.find('.fc-time-grid')); 22839 22840 this.timeGrid.renderDates(); 22841 22842 22843 22844 // the <hr> that sometimes displays under the time-grid 22845 22846 this.bottomRuleEl = $('<hr class="fc-divider ' + this.widgetHeaderClass + '"/>') 22847 22848 .appendTo(this.timeGrid.el); // inject it into the time-grid 22849 22850 22851 22852 if (this.dayGrid) { 22853 22854 this.dayGrid.setElement(this.el.find('.fc-day-grid')); 22855 22856 this.dayGrid.renderDates(); 22857 22858 22859 22860 // have the day-grid extend it's coordinate area over the <hr> dividing the two grids 22861 22862 this.dayGrid.bottomCoordPadding = this.dayGrid.el.next('hr').outerHeight(); 22863 22864 } 22865 22866 22867 22868 this.noScrollRowEls = this.el.find('.fc-row:not(.fc-scroller *)'); // fake rows not within the scroller 22869 22870 }, 22871 22872 22873 22874 22875 22876 // render the day-of-week headers 22877 22878 renderHead: function() { 22879 22880 this.headContainerEl = 22881 22882 this.el.find('.fc-head-container') 22883 22884 .html(this.timeGrid.renderHeadHtml()); 22885 22886 }, 22887 22888 22889 22890 22891 22892 // Unrenders the content of the view. Since we haven't separated skeleton rendering from date rendering, 22893 22894 // always completely kill each grid's rendering. 22895 22896 unrenderDates: function() { 22897 22898 this.timeGrid.unrenderDates(); 22899 22900 this.timeGrid.removeElement(); 22901 22902 22903 22904 if (this.dayGrid) { 22905 22906 this.dayGrid.unrenderDates(); 22907 22908 this.dayGrid.removeElement(); 22909 22910 } 22911 22912 }, 22913 22914 22915 22916 22917 22918 renderBusinessHours: function() { 22919 22920 this.timeGrid.renderBusinessHours(); 22921 22922 22923 22924 if (this.dayGrid) { 22925 22926 this.dayGrid.renderBusinessHours(); 22927 22928 } 22929 22930 }, 22931 22932 22933 22934 22935 22936 // Builds the HTML skeleton for the view. 22937 22938 // The day-grid and time-grid components will render inside containers defined by this HTML. 22939 22940 renderSkeletonHtml: function() { 22941 22942 return '' + 22943 22944 '<table>' + 22945 22946 '<thead class="fc-head">' + 22947 22948 '<tr>' + 22949 22950 '<td class="fc-head-container ' + this.widgetHeaderClass + '"></td>' + 22951 22952 '</tr>' + 22953 22954 '</thead>' + 22955 22956 '<tbody class="fc-body">' + 22957 22958 '<tr>' + 22959 22960 '<td class="' + this.widgetContentClass + '">' + 22961 22962 (this.dayGrid ? 22963 22964 '<div class="fc-day-grid"/>' + 22965 22966 '<hr class="fc-divider ' + this.widgetHeaderClass + '"/>' : 22967 22968 '' 22969 22970 ) + 22971 22972 '<div class="fc-time-grid-container">' + 22973 22974 '<div class="fc-time-grid"/>' + 22975 22976 '</div>' + 22977 22978 '</td>' + 22979 22980 '</tr>' + 22981 22982 '</tbody>' + 22983 22984 '</table>'; 22985 22986 }, 22987 22988 22989 22990 22991 22992 // Generates an HTML attribute string for setting the width of the axis, if it is known 22993 22994 axisStyleAttr: function() { 22995 22996 if (this.axisWidth !== null) { 22997 22998 return 'style="width:' + this.axisWidth + 'px"'; 22999 23000 } 23001 23002 return ''; 23003 23004 }, 23005 23006 23007 23008 23009 23010 /* Dimensions 23011 23012 ------------------------------------------------------------------------------------------------------------------*/ 23013 23014 23015 23016 23017 23018 updateSize: function(isResize) { 23019 23020 this.timeGrid.updateSize(isResize); 23021 23022 23023 23024 View.prototype.updateSize.call(this, isResize); // call the super-method 23025 23026 }, 23027 23028 23029 23030 23031 23032 // Refreshes the horizontal dimensions of the view 23033 23034 updateWidth: function() { 23035 23036 // make all axis cells line up, and record the width so newly created axis cells will have it 23037 23038 this.axisWidth = matchCellWidths(this.el.find('.fc-axis')); 23039 23040 }, 23041 23042 23043 23044 23045 23046 // Adjusts the vertical dimensions of the view to the specified values 23047 23048 setHeight: function(totalHeight, isAuto) { 23049 23050 var eventLimit; 23051 23052 var scrollerHeight; 23053 23054 23055 23056 if (this.bottomRuleHeight === null) { 23057 23058 // calculate the height of the rule the very first time 23059 23060 this.bottomRuleHeight = this.bottomRuleEl.outerHeight(); 23061 23062 } 23063 23064 this.bottomRuleEl.hide(); // .show() will be called later if this <hr> is necessary 23065 23066 23067 23068 // reset all dimensions back to the original state 23069 23070 this.scrollerEl.css('overflow', ''); 23071 23072 unsetScroller(this.scrollerEl); 23073 23074 uncompensateScroll(this.noScrollRowEls); 23075 23076 23077 23078 // limit number of events in the all-day area 23079 23080 if (this.dayGrid) { 23081 23082 this.dayGrid.removeSegPopover(); // kill the "more" popover if displayed 23083 23084 23085 23086 eventLimit = this.opt('eventLimit'); 23087 23088 if (eventLimit && typeof eventLimit !== 'number') { 23089 23090 eventLimit = AGENDA_ALL_DAY_EVENT_LIMIT; // make sure "auto" goes to a real number 23091 23092 } 23093 23094 if (eventLimit) { 23095 23096 this.dayGrid.limitRows(eventLimit); 23097 23098 } 23099 23100 } 23101 23102 23103 23104 if (!isAuto) { // should we force dimensions of the scroll container, or let the contents be natural height? 23105 23106 23107 23108 scrollerHeight = this.computeScrollerHeight(totalHeight); 23109 23110 if (setPotentialScroller(this.scrollerEl, scrollerHeight)) { // using scrollbars? 23111 23112 23113 23114 // make the all-day and header rows lines up 23115 23116 compensateScroll(this.noScrollRowEls, getScrollbarWidths(this.scrollerEl)); 23117 23118 23119 23120 // the scrollbar compensation might have changed text flow, which might affect height, so recalculate 23121 23122 // and reapply the desired height to the scroller. 23123 23124 scrollerHeight = this.computeScrollerHeight(totalHeight); 23125 23126 this.scrollerEl.height(scrollerHeight); 23127 23128 } 23129 23130 else { // no scrollbars 23131 23132 // still, force a height and display the bottom rule (marks the end of day) 23133 23134 this.scrollerEl.height(scrollerHeight).css('overflow', 'hidden'); // in case <hr> goes outside 23135 23136 this.bottomRuleEl.show(); 23137 23138 } 23139 23140 } 23141 23142 }, 23143 23144 23145 23146 23147 23148 // Computes the initial pre-configured scroll state prior to allowing the user to change it 23149 23150 computeInitialScroll: function() { 23151 23152 var scrollTime = moment.duration(this.opt('scrollTime')); 23153 23154 var top = this.timeGrid.computeTimeTop(scrollTime); 23155 23156 23157 23158 // zoom can give weird floating-point values. rather scroll a little bit further 23159 23160 top = Math.ceil(top); 23161 23162 23163 23164 if (top) { 23165 23166 top++; // to overcome top border that slots beyond the first have. looks better 23167 23168 } 23169 23170 23171 23172 return top; 23173 23174 }, 23175 23176 23177 23178 23179 23180 /* Hit Areas 23181 23182 ------------------------------------------------------------------------------------------------------------------*/ 23183 23184 // forward all hit-related method calls to the grids (dayGrid might not be defined) 23185 23186 23187 23188 23189 23190 prepareHits: function() { 23191 23192 this.timeGrid.prepareHits(); 23193 23194 if (this.dayGrid) { 23195 23196 this.dayGrid.prepareHits(); 23197 23198 } 23199 23200 }, 23201 23202 23203 23204 23205 23206 releaseHits: function() { 23207 23208 this.timeGrid.releaseHits(); 23209 23210 if (this.dayGrid) { 23211 23212 this.dayGrid.releaseHits(); 23213 23214 } 23215 23216 }, 23217 23218 23219 23220 23221 23222 queryHit: function(left, top) { 23223 23224 var hit = this.timeGrid.queryHit(left, top); 23225 23226 23227 23228 if (!hit && this.dayGrid) { 23229 23230 hit = this.dayGrid.queryHit(left, top); 23231 23232 } 23233 23234 23235 23236 return hit; 23237 23238 }, 23239 23240 23241 23242 23243 23244 getHitSpan: function(hit) { 23245
23246 // TODO: hit.component is set as a hack to identify where the hit came from 23247 23248 return hit.component.getHitSpan(hit); 23249 23250 }, 23251 23252 23253 23254 23255 23256 getHitEl: function(hit) { 23257 23258 // TODO: hit.component is set as a hack to identify where the hit came from 23259 23260 return hit.component.getHitEl(hit); 23261 23262 }, 23263 23264 23265 23266 23267 23268 /* Events 23269 23270 ------------------------------------------------------------------------------------------------------------------*/ 23271 23272 23273 23274 23275 23276 // Renders events onto the view and populates the View's segment array 23277 23278 renderEvents: function(events) { 23279 23280 var dayEvents = []; 23281 23282 var timedEvents = []; 23283 23284 var daySegs = []; 23285 23286 var timedSegs; 23287 23288 var i; 23289 23290 23291 23292 // separate the events into all-day and timed 23293 23294 for (i = 0; i < events.length; i++) { 23295 23296 if (events[i].allDay) { 23297 23298 dayEvents.push(events[i]); 23299 23300 } 23301 23302 else { 23303 23304 timedEvents.push(events[i]); 23305 23306 } 23307 23308 } 23309 23310 23311 23312 // render the events in the subcomponents 23313 23314 timedSegs = this.timeGrid.renderEvents(timedEvents); 23315 23316 if (this.dayGrid) { 23317 23318 daySegs = this.dayGrid.renderEvents(dayEvents); 23319 23320 } 23321 23322 23323 23324 // the all-day area is flexible and might have a lot of events, so shift the height 23325 23326 this.updateHeight(); 23327 23328 }, 23329 23330 23331 23332 23333 23334 // Retrieves all segment objects that are rendered in the view 23335 23336 getEventSegs: function() { 23337 23338 return this.timeGrid.getEventSegs().concat( 23339 23340 this.dayGrid ? this.dayGrid.getEventSegs() : [] 23341 23342 ); 23343 23344 }, 23345 23346 23347 23348 23349 23350 // Unrenders all event elements and clears internal segment data 23351 23352 unrenderEvents: function() { 23353 23354 23355 23356 // unrender the events in the subcomponents 23357 23358 this.timeGrid.unrenderEvents(); 23359 23360 if (this.dayGrid) { 23361 23362 this.dayGrid.unrenderEvents(); 23363 23364 } 23365 23366 23367 23368 // we DON'T need to call updateHeight() because: 23369 23370 // A) a renderEvents() call always happens after this, which will eventually call updateHeight() 23371 23372 // B) in IE8, this causes a flash whenever events are rerendered 23373 23374 }, 23375 23376 23377 23378 23379 23380 /* Dragging (for events and external elements) 23381 23382 ------------------------------------------------------------------------------------------------------------------*/ 23383 23384 23385 23386 23387 23388 // A returned value of `true` signals that a mock "helper" event has been rendered. 23389 23390 renderDrag: function(dropLocation, seg) { 23391 23392 if (dropLocation.start.hasTime()) { 23393 23394 return this.timeGrid.renderDrag(dropLocation, seg); 23395 23396 } 23397 23398 else if (this.dayGrid) { 23399 23400 return this.dayGrid.renderDrag(dropLocation, seg); 23401 23402 } 23403 23404 }, 23405 23406 23407 23408 23409 23410 unrenderDrag: function() { 23411 23412 this.timeGrid.unrenderDrag(); 23413 23414 if (this.dayGrid) { 23415 23416 this.dayGrid.unrenderDrag(); 23417 23418 } 23419 23420 }, 23421 23422 23423 23424 23425 23426 /* Selection 23427 23428 ------------------------------------------------------------------------------------------------------------------*/ 23429 23430 23431 23432 23433 23434 // Renders a visual indication of a selection 23435 23436 renderSelection: function(span) { 23437 23438 if (span.start.hasTime() || span.end.hasTime()) { 23439 23440 this.timeGrid.renderSelection(span); 23441 23442 } 23443 23444 else if (this.dayGrid) { 23445 23446 this.dayGrid.renderSelection(span); 23447 23448 } 23449 23450 }, 23451 23452 23453 23454 23455 23456 // Unrenders a visual indications of a selection 23457 23458 unrenderSelection: function() { 23459 23460 this.timeGrid.unrenderSelection(); 23461 23462 if (this.dayGrid) { 23463 23464 this.dayGrid.unrenderSelection(); 23465 23466 } 23467 23468 } 23469 23470 23471 23472 }); 23473 23474 23475 23476 23477 23478// Methods that will customize the rendering behavior of the AgendaView's timeGrid 23479 23480 var agendaTimeGridMethods = { 23481 23482 23483 23484 23485 23486 // Generates the HTML that will go before the day-of week header cells 23487 23488 renderHeadIntroHtml: function() { 23489 23490 var view = this.view; 23491 23492 var weekText; 23493 23494 23495 23496 if (view.opt('weekNumbers')) { 23497 23498 weekText = this.start.format(view.opt('smallWeekFormat')); 23499 23500 23501 23502 return '' + 23503 23504 '<th class="fc-axis fc-week-number ' + view.widgetHeaderClass + '" ' + view.axisStyleAttr() + '>' + 23505 23506 '<span>' + // needed for matchCellWidths 23507 23508 htmlEscape(weekText) + 23509 23510 '</span>' + 23511 23512 '</th>'; 23513 23514 } 23515 23516 else { 23517 23518 return '<th class="fc-axis ' + view.widgetHeaderClass + '" ' + view.axisStyleAttr() + '></th>'; 23519 23520 } 23521 23522 }, 23523 23524 23525 23526 23527 23528 // Generates the HTML that goes before the bg of the TimeGrid slot area. Long vertical column. 23529 23530 renderBgIntroHtml: function() { 23531 23532 var view = this.view; 23533 23534 23535 23536 return '<td class="fc-axis ' + view.widgetContentClass + '" ' + view.axisStyleAttr() + '></td>'; 23537 23538 }, 23539 23540 23541 23542 23543 23544 // Generates the HTML that goes before all other types of cells. 23545 23546 // Affects content-skeleton, helper-skeleton, highlight-skeleton for both the time-grid and day-grid. 23547 23548 renderIntroHtml: function() { 23549 23550 var view = this.view; 23551 23552 23553 23554 return '<td class="fc-axis" ' + view.axisStyleAttr() + '></td>'; 23555 23556 } 23557 23558 23559 23560 }; 23561 23562 23563 23564 23565 23566// Methods that will customize the rendering behavior of the AgendaView's dayGrid 23567 23568 var agendaDayGridMethods = { 23569 23570 23571 23572 23573 23574 // Generates the HTML that goes before the all-day cells 23575 23576 renderBgIntroHtml: function() { 23577 23578 var view = this.view; 23579 23580 23581 23582 return '' + 23583 23584 '<td class="fc-axis ' + view.widgetContentClass + '" ' + view.axisStyleAttr() + '>' + 23585 23586 '<span>' + // needed for matchCellWidths 23587 23588 (view.opt('allDayHtml') || htmlEscape(view.opt('allDayText'))) + 23589 23590 '</span>' + 23591 23592 '</td>'; 23593 23594 }, 23595 23596 23597 23598 23599 23600 // Generates the HTML that goes before all other types of cells. 23601 23602 // Affects content-skeleton, helper-skeleton, highlight-skeleton for both the time-grid and day-grid. 23603 23604 renderIntroHtml: function() { 23605 23606 var view = this.view; 23607 23608 23609 23610 return '<td class="fc-axis" ' + view.axisStyleAttr() + '></td>'; 23611 23612 } 23613 23614 23615 23616 }; 23617 23618 23619 23620 ;; 23621 23622 23623 23624 var AGENDA_ALL_DAY_EVENT_LIMIT = 5; 23625 23626 23627 23628// potential nice values for the slot-duration and interval-duration 23629 23630// from largest to smallest 23631 23632 var AGENDA_STOCK_SUB_DURATIONS = [ 23633 23634 { hours: 1 }, 23635 23636 { minutes: 30 }, 23637 23638 { minutes: 15 }, 23639 23640 { seconds: 30 }, 23641 23642 { seconds: 15 } 23643 23644 ]; 23645 23646 23647 23648 fcViews.agenda = { 23649 23650 'class': AgendaView, 23651 23652 defaults: { 23653 23654 allDaySlot: true, 23655 23656 allDayText: 'all-day', 23657 23658 slotDuration: '00:30:00', 23659 23660 minTime: '00:00:00', 23661 23662 maxTime: '24:00:00', 23663 23664 slotEventOverlap: true // a bad name. confused with overlap/constraint system 23665 23666 } 23667 23668 }; 23669 23670 23671 23672 fcViews.agendaDay = { 23673 23674 type: 'agenda', 23675 23676 duration: { days: 1 } 23677 23678 }; 23679 23680 23681 23682 fcViews.agendaWeek = { 23683 23684 type: 'agenda', 23685 23686 duration: { weeks: 1 } 23687 23688 }; 23689 23690 ;; 23691 23692 23693 23694 return FC; // export for Node/CommonJS 23695 23696}); 23697 23698 23699!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):"object"==typeof exports?module.exports=a(require("jquery"),require("moment")):a(jQuery,moment)}(function(a,b){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"zh-cn",{months:"1æ_2æ_3æ_4æ_5æ_6æ_7æ_8æ_9æ_10æ_11æ_12æ".split("_"),monthsShort:"1æ_2æ_3æ_4æ_5æ_6æ_7æ_8æ_9æ_10æ_11æ_12æ".split("_"),weekdays:"æææ¥_ææä¸_ææäº_ææä¸_ææå_ææäº_ææå ".split("_"),weekdaysShort:"æ¥_ä¸_äº_ä¸_å_äº_å ".split("_"),weekdaysMin:"æ¥_ä¸_äº_ä¸_å_äº_å ".split("_"),longDateFormat:{LT:"Ahç¹mmå",LTS:"Ahç¹måsç§",L:"YYYY-MM-DD",LL:"YYYYå¹´MMMDæ¥",LLL:"YYYYå¹´MMMDæ¥Ahç¹mmå",LLLL:"YYYYå¹´MMMDæ¥ddddAhç¹mmå",l:"YYYY-MM-DD",ll:"YYYYå¹´MMMDæ¥",lll:"YYYYå¹´MMMDæ¥Ahç¹mmå",llll:"YYYYå¹´MMMDæ¥ddddAhç¹mmå"},meridiemParse:/忍|æ©ä¸|ä¸å|ä¸å|ä¸å|æä¸/,meridiemHour:function(a,b){return 12===a&&(a=0),"忍"===b||"æ©ä¸"===b||"ä¸å"===b?a:"ä¸å"===b||"æä¸"===b?a+12:a>=11?a:a+12},meridiem:function(a,b,c){var d=100*a+b;return 600>
23699d?"忍":900>d?"æ©ä¸":1130>d?"ä¸å":1230>d?"ä¸å":1800>d?"ä¸å":"æä¸"},calendar:{sameDay:function(){return 0===this.minutes()?"[ä»å¤©]Ah[ç¹æ´]":"[ä»å¤©]LT"},nextDay:function(){return 0===this.minutes()?"[æå¤©]Ah[ç¹æ´]":"[æå¤©]LT"},lastDay:function(){return 0===this.minutes()?"[æ¨å¤©]Ah[ç¹æ´]":"[æ¨å¤©]LT"},nextWeek:function(){var a,c;return a=b().startOf("week"),c=this.unix()-a.unix()>=604800?"[ä¸]":"[æ¬]",0===this.minutes()?c+"dddAhç¹æ´":c+"dddAhç¹mm"},lastWeek:function(){var a,c;return a=b().startOf("week"),c=this.unix()<a.unix()?"[ä¸]":"[æ¬]",0===this.minutes()?c+"dddAhç¹æ´":c+"dddAhç¹mm"},sameElse:"LL"},ordinalParse:/\d{1,2}(æ¥|æ|å¨)/,ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"æ¥";case"M":return a+"æ";case"w":case"W":return a+"å¨";default:return a}},relativeTime:{future:"%så ",past:"%så",s:"å ç§",m:"1 åé",mm:"%d åé",h:"1 å°æ¶",hh:"%d å°æ¶",d:"1 天",dd:"%d 天",M:"1 个æ",MM:"%d 个æ",y:"1 å¹´",yy:"%d å¹´"},week:{dow:1,doy:4}});return a}(),a.fullCalendar.datepickerLang("zh-cn","zh-CN",{closeText:"å ³é",prevText:"<䏿",nextText:"䏿>",currentText:"ä»å¤©",monthNames:["1æ","2æ","3æ","4æ","5æ","6æ","7æ","8æ","9æ","10æ","11æ","12æ"],monthNamesShort:["1æ","2æ","3æ","4æ","5æ","6æ","7æ","8æ","9æ","10æ","11æ","12æ"],dayNames:["æææ¥","ææä¸","ææäº","ææä¸","ææå","ææäº","ææå "],dayNamesShort:["æ¥","ä¸","äº","ä¸","å","äº","å "],dayNamesMin:["æ¥","ä¸","äº","ä¸","å","äº","å "],weekHeader:"å¨",dateFormat:"yy-mm-dd",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"å¹´"}),a.fullCalendar.lang("zh-cn",{buttonText:{month:"æ",week:"å¨",day:"æ¥",list:"æ¥ç¨"},allDayText:"å ¨å¤©",eventLimitText:function(a){return"å¦å¤ "+a+" 个"}})}); 23700!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):"object"==typeof exports?module.exports=a(require("jquery"),require("moment")):a(jQuery,moment)}(function(a,b){!function(){"use strict";var a=(b.defineLocale||b.lang).call(b,"zh-tw",{months:"1æ_2æ_3æ_4æ_5æ_6æ_7æ_8æ_9æ_10æ_11æ_12æ".split("_"),monthsShort:"1æ_2æ_3æ_4æ_5æ_6æ_7æ_8æ_9æ_10æ_11æ_12æ".split("_"),weekdays:"æææ¥_ææä¸_ææäº_ææä¸_ææå_ææäº_ææå ".split("_"),weekdaysShort:"æ¥_ä¸_äº_ä¸_å_äº_å ".split("_"),weekdaysMin:"æ¥_ä¸_äº_ä¸_å_äº_å ".split("_"),longDateFormat:{LT:"Ahé»mmå",LTS:"Ahé»måsç§",L:"YYYYå¹´MMMDæ¥",LL:"YYYYå¹´MMMDæ¥",LLL:"YYYYå¹´MMMDæ¥Ahé»mmå",LLLL:"YYYYå¹´MMMDæ¥ddddAhé»mmå",l:"YYYYå¹´MMMDæ¥",ll:"YYYYå¹´MMMDæ¥",lll:"YYYYå¹´MMMDæ¥Ahé»mmå",llll:"YYYYå¹´MMMDæ¥ddddAhé»mmå"},meridiemParse:/æ©ä¸|ä¸å|ä¸å|ä¸å|æä¸/,meridiemHour:function(a,b){return 12===a&&(a=0),"æ©ä¸"===b||"ä¸å"===b?a:"ä¸å"===b?a>=11?a:a+12:"ä¸å"===b||"æä¸"===b?a+12:void 0},meridiem:function(a,b,c){var d=100*a+b;return 900>d?"æ©ä¸":1130>d?"ä¸å":1230>d?"ä¸å":1800>d?"ä¸å":"æä¸"},calendar:{sameDay:"[ä»å¤©]LT",nextDay:"[æå¤©]LT",nextWeek:"[ä¸]ddddLT",lastDay:"[æ¨å¤©]LT",lastWeek:"[ä¸]ddddLT",sameElse:"L"},ordinalParse:/\d{1,2}(æ¥|æ|é±)/,ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"æ¥";case"M":return a+"æ";case"w":case"W":return a+"é±";default:return a}},relativeTime:{future:"%så §",past:"%så",s:"å¹¾ç§",m:"ä¸åé",mm:"%dåé",h:"ä¸å°æ",hh:"%då°æ",d:"ä¸å¤©",dd:"%d天",M:"ä¸åæ",MM:"%dåæ",y:"ä¸å¹´",yy:"%då¹´"}});return a}(),a.fullCalendar.datepickerLang("zh-tw","zh-TW",{closeText:"éé",prevText:"<䏿",nextText:"䏿>",currentText:"ä»å¤©",monthNames:["1æ","2æ","3æ","4æ","5æ","6æ","7æ","8æ","9æ","10æ","11æ","12æ"],monthNamesShort:["1æ","2æ","3æ","4æ","5æ","6æ","7æ","8æ","9æ","10æ","11æ","12æ"],dayNames:["æææ¥","ææä¸","ææäº","ææä¸","ææå","ææäº","ææå "],dayNamesShort:["æ¥","ä¸","äº","ä¸","å","äº","å "],dayNamesMin:["æ¥","ä¸","äº","ä¸","å","äº","å "],weekHeader:"å¨",dateFormat:"yy/mm/dd",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"å¹´"}),a.fullCalendar.lang("zh-tw",{buttonText:{month:"æ",week:"é±",day:"天",list:"å¾ è¾¦äºé "},allDayText:"å ¨å¤©",eventLimitText:"æ´å¤"})}); 23701!function(a){function b(){return new Date(Date.UTC.apply(Date,arguments))}var c=function(b,c){var f=this;this.element=a(b),this.autoShow=c.autoShow||!0,this.appendTo=c.appendTo||"body",this.closeButton=c.closeButton,this.language=c.language||this.element.data("date-language")||"en",this.language=this.language in d?this.language:this.language.split("-")[0],this.language=this.language in d?this.language:"en",this.isRTL=d[this.language].rtl||!1,this.format=e.parseFormat(c.format||this.element.data("date-format")||d[this.language].format||"mm/dd/yyyy"),this.isInline=!1,this.isInput=this.element.is("input"),this.component=this.element.is(".date")?this.element.find(".prefix, .postfix"):!1,this.hasInput=this.component&&this.element.find("input").length,this.disableDblClickSelection=c.disableDblClickSelection,this.onRender=c.onRender||function(){},this.component&&0===this.component.length&&(this.component=!1),this.linkField=c.linkField||this.element.data("link-field")||!1,this.linkFormat=e.parseFormat(c.linkFormat||this.element.data("link-format")||"yyyy-mm-dd hh:ii:ss"),this.minuteStep=c.minuteStep||this.element.data("minute-step")||5,this.pickerPosition=c.pickerPosition||this.element.data("picker-position")||"bottom-right",this.initialDate=c.initialDate||null,this._attachEvents(),this.minView=0,"minView"in c?this.minView=c.minView:"minView"in this.element.data()&&(this.minView=this.element.data("min-view")),this.minView=e.convertViewMode(this.minView),this.maxView=e.modes.length-1,"maxView"in c?this.maxView=c.maxView:"maxView"in this.element.data()&&(this.maxView=this.element.data("max-view")),this.maxView=e.convertViewMode(this.maxView),this.startViewMode="month","startView"in c?this.startViewMode=c.startView:"startView"in this.element.data()&&(this.startViewMode=this.element.data("start-view")),this.startViewMode=e.convertViewMode(this.startViewMode),this.viewMode=this.startViewMode,"minView"in c||"maxView"in c||this.element.data("min-view")&&!this.element.data("max-view")||(this.pickTime=!1,"pickTime"in c&&(this.pickTime=c.pickTime),1==this.pickTime?(this.minView=0,this.maxView=4):(this.minView=2,this.maxView=4)),this.forceParse=!0,"forceParse"in c?this.forceParse=c.forceParse:"dateForceParse"in this.element.data()&&(this.forceParse=this.element.data("date-force-parse")),this.picker=a(e.template).appendTo(this.isInline?this.element:this.appendTo).on({click:a.proxy(this.click,this),mousedown:a.proxy(this.mousedown,this)}),this.closeButton?this.picker.find("a.datepicker-close").show():this.picker.find("a.datepicker-close").hide(),this.isInline?this.picker.addClass("datepicker-inline"):this.picker.addClass("datepicker-dropdown dropdown-menu"),this.isRTL&&(this.picker.addClass("datepicker-rtl"),this.picker.find(".prev i, .next i").toggleClass("fa-chevron-left fa-chevron-right")),a(document).on("mousedown",function(b){0===a(b.target).closest(".datepicker.datepicker-inline, .datepicker.datepicker-dropdown").length&&f.hide()}),this.autoclose=!0,"autoclose"in c?this.autoclose=c.autoclose:"dateAutoclose"in this.element.data()&&(this.autoclose=this.element.data("date-autoclose")),this.keyboardNavigation=!0,"keyboardNavigation"in c?this.keyboardNavigation=c.keyboardNavigation:"dateKeyboardNavigation"in this.element.data()&&(this.keyboardNavigation=this.element.data("date-keyboard-navigation")),this.todayBtn=c.todayBtn||this.element.data("date-today-btn")||!1,this.todayHighlight=c.todayHighlight||this.element.data("date-today-highlight")||!1,this.calendarWeeks=!1,"calendarWeeks"in c?this.calendarWeeks=c.calendarWeeks:"dateCalendarWeeks"in this.element.data()&&(this.calendarWeeks=this.element.data("date-calendar-weeks")),this.calendarWeeks&&this.picker.find("tfoot th.today").attr("colspan",function(a,b){return parseInt(b)+1}),this.weekStart=(c.weekStart||this.element.data("date-weekstart")||d[this.language].weekStart||0)%7,this.weekEnd=(this.weekStart+6)%7,this.startDate=-(1/0),this.endDate=1/0,this.daysOfWeekDisabled=[],this.setStartDate(c.startDate||this.element.data("date-startdate")),this.setEndDate(c.endDate||this.element.data("date-enddate")),this.setDaysOfWeekDisabled(c.daysOfWeekDisabled||this.element.data("date-days-of-week-disabled")),this.fillDow(),this.fillMonths(),this.update(),this.showMode(),this.isInline&&this.show()};c.prototype={constructor:c,_events:[],_attachEvents:function(){this._detachEvents(),this.isInput?this._events=[[this.element,{focus:this.autoShow?a.proxy(this.show,this):function(){},keyup:a.proxy(this.update,this),keydown:a.proxy(this.keydown,this)}]]:this.component&&this.hasInput?this._events=[[this.element.find("input"),{focus:this.autoShow?a.proxy(this.show,this):function(){},keyup:a.proxy(this.update,this),keydown:a.proxy(this.keydown,this)}],[this.component,{click:a.proxy(this.show,this)}]]:this.element.is("div")?this.isInline=!0:this._events=[[this.element,{click:a.proxy(this.show,this)}]],this.disableDblClickSelection&&(this._events[this._events.length]=[this.element,{dblclick:function(b){b.preventDefault(),b.stopPropagation(),a(this).blur()}}]);for(var b,c,d=0;d<this._events.length;d++)b=this._events[d][0],c=this._events[d][1],b.on(c)},_detachEvents:function(){for(var a,b,c=0;c<this._events.length;c++)a=this._events[c][0],b=this._events[c][1],a.off(b);this._events=[]},show:function(b){this.picker.show(),this.height=this.component?this.component.outerHeight():this.element.outerHeight(),this.update(),this.place(),a(window).on("resize",a.proxy(this.place,this)),b&&(b.stopPropagation(),b.preventDefault()),this.element.trigger({type:"show",date:this.date})},hide:function(b){this.isInline||this.picker.is(":visible")&&(this.picker.hide(),a(window).off("resize",this.place),this.viewMode=this.startViewMode,this.showMode(),this.isInput||a(document).off("mousedown",this.hide),this.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val())&&this.setValue(),this.element.trigger({type:"hide",date:this.date}))},remove:function(){this._detachEvents(),this.picker.remove(),delete this.element.data().datepicker},getDate:function(){var a=this.getUTCDate();return new Date(a.getTime()+6e4*a.getTimezoneOffset())},getUTCDate:function(){return this.date},setDate:function(a){this.setUTCDate(new Date(a.getTime()-6e4*a.getTimezoneOffset()))},setUTCDate:function(a){this.date=a,this.setValue()},setValue:function(){var a=this.getFormattedDate();this.isInput?this.element.val(a):(this.component&&this.element.find("input").val(a),this.element.data("date",a))},getFormattedDate:function(a){return void 0===a&&(a=this.format),e.formatDate(this.date,a,this.language)},setStartDate:function(a){this.startDate=a||-(1/0),this.startDate!==-(1/0)&&(this.startDate=e.parseDate(this.startDate,this.format,this.language)),this.update(),this.updateNavArrows()},setEndDate:function(a){this.endDate=a||1/0,this.endDate!==1/0&&(this.endDate=e.parseDate(this.endDate,this.format,this.language)),this.update(),this.updateNavArrows()},setDaysOfWeekDisabled:function(b){this.daysOfWeekDisabled=b||[],a.isArray(this.daysOfWeekDisabled)||(this.daysOfWeekDisabled=this.daysOfWeekDisabled.split(/,\s*/)),this.daysOfWeekDisabled=a.map(this.daysOfWeekDisabled,function(a){return parseInt(a,10)}),this.update(),this.updateNavArrows()},place:function(){if(!this.isInline){var b=parseInt(this.element.parents().filter(function(){return"auto"!=a(this).css("z-index")}).first().css("z-index"))+10,c=this.component?this.component:this.element,d=c.offset(),e=c.outerHeight()+parseInt(c.css("margin-top")),f=c.outerWidth()+parseInt(c.css("margin-left")),g=d.top+e,h=d.left;g+this.picker.outerHeight()>=a(window).scrollTop()+a(window).height()&&(g=d.top-this.picker.outerHeight()),d.left+this.picker.width()>=a(window).width()&&(h=d.left+f-this.picker.width()),this.picker.css({top:g,left:h,zIndex:b})}},update:function(){var a,b=!1;arguments&&arguments.length&&("string"==typeof arguments[0]||arguments[0]instanceof Date)?(a=arguments[0],b=!0):a=null!=this.initialDate?this.initialDate:this.isInput?this.element.val():this.element.data("date")||this.element.find("input").val(),this.date=e.parseDate(a,this.format,this.language),(b||null!=this.initialDate)&&this.setValue(),this.date<this.startDate?this.viewDate=new Date(this.startDate.valueOf()):this.date>this.endDate?this.viewDate=new Date(this.endDate.valueOf()):this.viewDate=new Date(this.date.valueOf()),this.fill()},fillDow:function(){var a=this.weekStart,b="<tr>";if(this.calendarWeeks){var c='<th class="cw"> </th>';b+=c,this.picker.find(".datepicker-days thead tr:first-child").prepend(c)}for(;a<this.weekStart+7;)b+='<th class="dow">'+d[this.language].daysMin[a++%7]+"</th>";b+="</tr>",this.picker.find(".datepicker-days thead").append(b)},fillMonths:function(){for(var a="",b=0;12>b;)a+='<span class="month">'+d[this.language].monthsShort[b++]+"</span>";this.picker.find(".datepicker-months td").html(a)},fill:function(){if(null!=this.date&&null!=this.viewDate){var c=new Date(this.viewDate.valueOf()),f=c.getUTCFullYear(),g=c.getUTCMonth(),h=c.getUTCDate(),i=c.getUTCHours(),j=c.getUTCMinutes(),k=this.startDate!==-(1/0)?this.startDate.getUTCFullYear():-(1/0),l=this.startDate!==-(1/0)?this.startDate.getUTCMonth():-(1/0),m=this.endDate!==1/0?this.endDate.getUTCFullYear():1/0,n=this.endDate!==1/0?this.endDate.getUTCMonth():1/0,o=this.date&&this.date.valueOf(),p=new Date;d[this.language].titleFormat||d.en.titleFormat;this.picker.find(".datepicker-days thead th:eq(1)").text(d[this.language].months[g]+" "+f),this.picker.find(".datepicker-hours thead th:eq(1)").text(h+" "+d[this.language].months[g]+" "+f),this.picker.find(".datepicker-minutes thead th:eq(1)").text(h+" "+d[this.language].months[g]+" "+f),this.picker.find("tfoot th.today").text(d[this.language].today).toggle(this.todayBtn!==!1),this.updateNavArrows(),this.fillMonths();var q=b(f,g-1,28,0,0,0,0),r=e.getDaysInMonth(q.getUTCFullYear(),q.getUTCMonth());q.setUTCDate(r),q.setUTCDate(r-(q.getUTCDay()-this.weekStart+7)%7);var s=new Date(q.valueOf());s.setUTCDate(s.getUTCDate()+42),s=s.valueOf();for(var t,u=[];q.valueOf()<s;){if(q.getUTCDay()==this.weekStart&&(u.push("<tr>"),this.calendarWeeks)){var v=new Date(q.getUTCFullYear(),q.getUTCMonth(),q.getUTCDate()-q.getDay()+10-(this.weekStart&&this.weekStart%7<5&&7)),w=new Date(v.getFullYear(),0,4),x=~~((v-w)/864e5/7+1.5);u.push('<td class="cw">'+x+"</td>")}t=" "+this.onRender(q)+" ",q.getUTCFullYear()<f||q.getUTCFullYear()==f&&q.getUTCMonth()<g?t+=" old":(q.getUTCFullYear()>f||q.getUTCFullYear()==f&&q.getUTCMonth()>g)&&(t+=" new"),this.todayHighlight&&q.getUTCFullYear()==p.getFullYear()&&q.getUTCMonth()==p.getMonth()&&q.getUTCDate()==p.getDate()&&(t+=" today"),o&&q.valueOf()==o&&(t+=" active"),(q.valueOf()<this.startDate||q.valueOf()>this.endDate||-1!==a.inArray(q.getUTCDay(),this.daysOfWeekDisabled))&&(t+=" disabled"),u.push('<td class="day'+t+'">'+q.getUTCDate()+"</td>"),q.getUTCDay()==this.weekEnd&&u.push("</tr>"),q.setUTCDate(q.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").empty().append(u.join("")),u=[];for(var y=0;24>y;y++){var z=b(f,g,h,y);t="",z.valueOf()+36e5<this.startDate||z.valueOf()>this.endDate?t+=" disabled":i==y&&(t+=" active"),u.push('<span class="hour'+t+'">'+y+":00</span>")}this.picker.find(".datepicker-hours td").html(u.join("")),u=[];for(var y=0;60>y;y+=this.minuteStep){var z=b(f,g,h,i,y);t="",z.valueOf()<this.startDate||z.valueOf()>this.endDate?t+=" disabled":Math.floor(j/this.minuteStep)==Math.floor(y/this.minuteStep)&&(t+=" active"),u.push('<span class="minute'+t+'">'+i+":"+(10>y?"0"+y:y)+"</span>")}this.picker.find(".datepicker-minutes td").html(u.join(""));var A=this.date&&this.date.getUTCFullYear(),B=this.picker.find(".datepicker-months").find("th:eq(1)").text(f).end().find("span").removeClass("active");A&&A==f&&B.eq(this.date.getUTCMonth()).addClass("active"),(k>f||f>m)&&B.addClass("disabled"),f==k&&B.slice(0,l).addClass("disabled"),f==m&&B.slice(n+1).addClass("disabled"),u="",f=10*parseInt(f/10,10);
23701var C=this.picker.find(".datepicker-years").find("th:eq(1)").text(f+"-"+(f+9)).end().find("td");f-=1;for(var y=-1;11>y;y++)u+='<span class="year'+(-1==y||10==y?" old":"")+(A==f?" active":"")+(k>f||f>m?" disabled":"")+'">'+f+"</span>",f+=1;C.html(u)}},updateNavArrows:function(){var a=new Date(this.viewDate),b=a.getUTCFullYear(),c=a.getUTCMonth(),d=a.getUTCDate(),e=a.getUTCHours();switch(this.viewMode){case 0:this.startDate!==-(1/0)&&b<=this.startDate.getUTCFullYear()&&c<=this.startDate.getUTCMonth()&&d<=this.startDate.getUTCDate()&&e<=this.startDate.getUTCHours()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==1/0&&b>=this.endDate.getUTCFullYear()&&c>=this.endDate.getUTCMonth()&&d>=this.endDate.getUTCDate()&&e>=this.endDate.getUTCHours()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 1:this.startDate!==-(1/0)&&b<=this.startDate.getUTCFullYear()&&c<=this.startDate.getUTCMonth()&&d<=this.startDate.getUTCDate()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==1/0&&b>=this.endDate.getUTCFullYear()&&c>=this.endDate.getUTCMonth()&&d>=this.endDate.getUTCDate()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 2:this.startDate!==-(1/0)&&b<=this.startDate.getUTCFullYear()&&c<=this.startDate.getUTCMonth()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==1/0&&b>=this.endDate.getUTCFullYear()&&c>=this.endDate.getUTCMonth()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 3:case 4:this.startDate!==-(1/0)&&b<=this.startDate.getUTCFullYear()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==1/0&&b>=this.endDate.getUTCFullYear()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"})}},click:function(c){c.stopPropagation(),c.preventDefault(),(a(c.target).hasClass("datepicker-close")||a(c.target).parent().hasClass("datepicker-close"))&&this.hide();var d=a(c.target).closest("span, td, th");if(1==d.length){if(d.is(".disabled"))return void this.element.trigger({type:"outOfRange",date:this.viewDate,startDate:this.startDate,endDate:this.endDate});switch(d[0].nodeName.toLowerCase()){case"th":switch(d[0].className){case"date-switch":this.showMode(1);break;case"prev":case"next":var f=e.modes[this.viewMode].navStep*("prev"==d[0].className?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveHour(this.viewDate,f);break;case 1:this.viewDate=this.moveDate(this.viewDate,f);break;case 2:this.viewDate=this.moveMonth(this.viewDate,f);break;case 3:case 4:this.viewDate=this.moveYear(this.viewDate,f)}this.fill();break;case"today":var g=new Date;g=b(g.getFullYear(),g.getMonth(),g.getDate(),g.getHours(),g.getMinutes(),g.getSeconds()),this.viewMode=this.startViewMode,this.showMode(0),this._setDate(g)}break;case"span":if(!d.is(".disabled")){if(d.is(".month"))if(3===this.minView){var h=d.parent().find("span").index(d)||0,i=this.viewDate.getUTCFullYear(),j=1,k=this.viewDate.getUTCHours(),l=this.viewDate.getUTCMinutes(),m=this.viewDate.getUTCSeconds();this._setDate(b(i,h,j,k,l,m,0))}else{this.viewDate.setUTCDate(1);var h=d.parent().find("span").index(d);this.viewDate.setUTCMonth(h),this.element.trigger({type:"changeMonth",date:this.viewDate})}else if(d.is(".year"))if(4===this.minView){var i=parseInt(d.text(),10)||0,h=0,j=1,k=this.viewDate.getUTCHours(),l=this.viewDate.getUTCMinutes(),m=this.viewDate.getUTCSeconds();this._setDate(b(i,h,j,k,l,m,0))}else{this.viewDate.setUTCDate(1);var i=parseInt(d.text(),10)||0;this.viewDate.setUTCFullYear(i),this.element.trigger({type:"changeYear",date:this.viewDate})}else if(d.is(".hour")){var k=parseInt(d.text(),10)||0,i=this.viewDate.getUTCFullYear(),h=this.viewDate.getUTCMonth(),j=this.viewDate.getUTCDate(),l=this.viewDate.getUTCMinutes(),m=this.viewDate.getUTCSeconds();this._setDate(b(i,h,j,k,l,m,0))}else if(d.is(".minute")){var l=parseInt(d.text().substr(d.text().indexOf(":")+1),10)||0,i=this.viewDate.getUTCFullYear(),h=this.viewDate.getUTCMonth(),j=this.viewDate.getUTCDate(),k=this.viewDate.getUTCHours(),m=this.viewDate.getUTCSeconds();this._setDate(b(i,h,j,k,l,m,0))}if(0!=this.viewMode){var n=this.viewMode;this.showMode(-1),this.fill(),n==this.viewMode&&this.autoclose&&this.hide()}else this.fill(),this.autoclose&&this.hide()}break;case"td":if(d.is(".day")&&!d.is(".disabled")){var j=parseInt(d.text(),10)||1,i=this.viewDate.getUTCFullYear(),h=this.viewDate.getUTCMonth(),k=this.viewDate.getUTCHours(),l=this.viewDate.getUTCMinutes(),m=this.viewDate.getUTCSeconds();d.is(".old")?0===h?(h=11,i-=1):h-=1:d.is(".new")&&(11==h?(h=0,i+=1):h+=1),this._setDate(b(i,h,j,k,l,m,0))}var n=this.viewMode;this.showMode(-1),this.fill(),n==this.viewMode&&this.autoclose&&this.hide()}}},_setDate:function(a,b){b&&"date"!=b||(this.date=a),b&&"view"!=b||(this.viewDate=a),this.fill(),this.setValue(),this.element.trigger({type:"changeDate",date:this.date});var c;this.isInput?c=this.element:this.component&&(c=this.element.find("input")),c&&(c.change(),this.autoclose&&(!b||"date"==b))},moveHour:function(a,b){if(!b)return a;var c=new Date(a.valueOf());return b=b>0?1:-1,c.setUTCHours(c.getUTCHours()+b),c},moveDate:function(a,b){if(!b)return a;var c=new Date(a.valueOf());return b=b>0?1:-1,c.setUTCDate(c.getUTCDate()+b),c},moveMonth:function(a,b){if(!b)return a;var c,d,e=new Date(a.valueOf()),f=e.getUTCDate(),g=e.getUTCMonth(),h=Math.abs(b);
vendor: 5,256 bytes, line 23701
23701if(b=b>0?1:-1,1==h)d=-1==b?function(){return e.getUTCMonth()==g}:function(){return e.getUTCMonth()!=c},c=g+b,e.setUTCMonth(c),(0>c||c>11)&&(c=(c+12)%12);else{for(var i=0;h>i;i++)e=this.moveMonth(e,b);c=e.getUTCMonth(),e.setUTCDate(f),d=function(){return c!=e.getUTCMonth()}}for(;d();)e.setUTCDate(--f),e.setUTCMonth(c);return e},moveYear:function(a,b){return this.moveMonth(a,12*b)},dateWithinRange:function(a){return a>=this.startDate&&a<=this.endDate},keydown:function(a){if(this.picker.is(":not(:visible)"))return void(27==a.keyCode&&this.show());var b,c,d,e=!1;switch(a.keyCode){case 27:this.hide(),a.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation)break;b=37==a.keyCode?-1:1,a.ctrlKey?(c=this.moveYear(this.date,b),d=this.moveYear(this.viewDate,b)):a.shiftKey?(c=this.moveMonth(this.date,b),d=this.moveMonth(this.viewDate,b)):(c=new Date(this.date.valueOf()),c.setUTCDate(this.date.getUTCDate()+b),d=new Date(this.viewDate.valueOf()),d.setUTCDate(this.viewDate.getUTCDate()+b)),this.dateWithinRange(c)&&(this.date=c,this.viewDate=d,this.setValue(),this.update(),a.preventDefault(),e=!0);break;case 38:case 40:if(!this.keyboardNavigation)break;b=38==a.keyCode?-1:1,a.ctrlKey?(c=this.moveYear(this.date,b),d=this.moveYear(this.viewDate,b)):a.shiftKey?(c=this.moveMonth(this.date,b),d=this.moveMonth(this.viewDate,b)):(c=new Date(this.date.valueOf()),c.setUTCDate(this.date.getUTCDate()+7*b),d=new Date(this.viewDate.valueOf()),d.setUTCDate(this.viewDate.getUTCDate()+7*b)),this.dateWithinRange(c)&&(this.date=c,this.viewDate=d,this.setValue(),this.update(),a.preventDefault(),e=!0);break;case 13:this.hide(),a.preventDefault();break;case 9:this.hide()}if(e){this.element.trigger({type:"changeDate",date:this.date});var f;this.isInput?f=this.element:this.component&&(f=this.element.find("input")),f&&f.change()}},showMode:function(a){if(a){var b=Math.max(0,Math.min(e.modes.length-1,this.viewMode+a));b>=this.minView&&b<=this.maxView&&(this.viewMode=b)}this.picker.find(">div").hide().filter(".datepicker-"+e.modes[this.viewMode].clsName).css("display","block"),this.updateNavArrows()},reset:function(a){this._setDate(null,"date")}},a.fn.fdatepicker=function(b){var d=Array.apply(null,arguments);return d.shift(),this.each(function(){var e=a(this),f=e.data("datepicker"),g="object"==typeof b&&b;f||e.data("datepicker",f=new c(this,a.extend({},a.fn.fdatepicker.defaults,g))),"string"==typeof b&&"function"==typeof f[b]&&f[b].apply(f,d)})},a.fn.fdatepicker.defaults={onRender:function(a){return""}},a.fn.fdatepicker.Constructor=c;var d=a.fn.fdatepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",titleFormat:"MM yyyy"}},e={modes:[{clsName:"minutes",navFnc:"Hours",navStep:1},{clsName:"hours",navFnc:"Date",navStep:1},{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(a){return a%4===0&&a%100!==0||a%400===0},getDaysInMonth:function(a,b){return[31,e.isLeapYear(a)?29:28,31,30,31,30,31,31,30,31,30,31][b]},validParts:/hh?|ii?|ss?|dd?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,parseFormat:function(a){var b=a.replace(this.validParts,"\x00").split("\x00"),c=a.match(this.validParts);if(!b||!b.length||!c||0===c.length)throw new Error("Invalid date format.");return{separators:b,parts:c}},parseDate:function(c,e,f){if(c instanceof Date)return new Date(c.valueOf()-6e4*c.getTimezoneOffset());if(/^\d{4}\-\d{1,2}\-\d{1,2}$/.test(c)&&(e=this.parseFormat("yyyy-mm-dd")),/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}$/.test(c)&&(e=this.parseFormat("yyyy-mm-dd hh:ii")),/^\d{4}\-\d{1,2}\-\d{1,2}[T ]\d{1,2}\:\d{1,2}\:\d{1,2}[Z]{0,1}$/.test(c)&&(e=this.parseFormat("yyyy-mm-dd hh:ii:ss")),/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(c)){var g,h,i=/([-+]\d+)([dmwy])/,j=c.match(/([-+]\d+)([dmwy])/g);c=new Date;for(var k=0;k<j.length;k++)switch(g=i.exec(j[k]),h=parseInt(g[1]),g[2]){case"d":c.setUTCDate(c.getUTCDate()+h);break;case"m":c=Datetimepicker.prototype.moveMonth.call(Datetimepicker.prototype,c,h);break;case"w":c.setUTCDate(c.getUTCDate()+7*h);break;case"y":c=Datetimepicker.prototype.moveYear.call(Datetimepicker.prototype,c,h)}return b(c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate(),c.getUTCHours(),c.getUTCMinutes(),c.getUTCSeconds())}var l,m,g,j=c&&c.match(this.nonpunctuation)||[],c=new Date,n={},o=["hh","h","ii","i","ss","s","yyyy","yy","M","MM","m","mm","d","dd"],p={hh:function(a,b){return a.setUTCHours(b)},h:function(a,b){return a.setUTCHours(b)},ii:function(a,b){return a.setUTCMinutes(b)},i:function(a,b){return a.setUTCMinutes(b)},ss:function(a,b){return a.setUTCSeconds(b)},s:function(a,b){return a.setUTCSeconds(b)},yyyy:function(a,b){return a.setUTCFullYear(b)},yy:function(a,b){return a.setUTCFullYear(2e3+b)},m:function(a,b){for(b-=1;0>b;)b+=12;for(b%=12,a.setUTCMonth(b);a.getUTCMonth()!=b;
23701)a.setUTCDate(a.getUTCDate()-1);return a},d:function(a,b){return a.setUTCDate(b)}};if(p.M=p.MM=p.mm=p.m,p.dd=p.d,c=b(c.getFullYear(),c.getMonth(),c.getDate(),0,0,0),j.length==e.parts.length){for(var k=0,q=e.parts.length;q>k;k++){if(l=parseInt(j[k],10),g=e.parts[k],isNaN(l))switch(g){case"MM":m=a(d[f].months).filter(function(){var a=this.slice(0,j[k].length),b=j[k].slice(0,a.length);return a==b}),l=a.inArray(m[0],d[f].months)+1;break;case"M":m=a(d[f].monthsShort).filter(function(){var a=this.slice(0,j[k].length),b=j[k].slice(0,a.length);return a==b}),l=a.inArray(m[0],d[f].monthsShort)+1}n[g]=l}for(var r,k=0;k<o.length;k++)r=o[k],r in n&&!isNaN(n[r])&&p[r](c,n[r])}return c},formatDate:function(b,c,e){if(null==b)return"";var f={h:b.getUTCHours(),i:b.getUTCMinutes(),s:b.getUTCSeconds(),d:b.getUTCDate(),m:b.getUTCMonth()+1,M:d[e].monthsShort[b.getUTCMonth()],MM:d[e].months[b.getUTCMonth()],yy:b.getUTCFullYear().toString().substring(2),yyyy:b.getUTCFullYear()};f.hh=(f.h<10?"0":"")+f.h,f.ii=(f.i<10?"0":"")+f.i,f.ss=(f.s<10?"0":"")+f.s,f.dd=(f.d<10?"0":"")+f.d,f.mm=(f.m<10?"0":"")+f.m;for(var b=[],g=a.extend([],c.separators),h=0,i=c.parts.length;i>h;h++)g.length&&b.push(g.shift()),b.push(f[c.parts[h]]);return b.join("")},convertViewMode:function(a){switch(a){case 4:case"decade":a=4;break;case 3:case"year":a=3;break;case 2:case"month":a=2;break;case 1:case"day":a=1;break;case 0:case"hour":a=0}return a},headTemplate:'<thead><tr><th class="prev"><i class="fa fa-chevron-left fi-arrow-left"/></th><th colspan="5" class="date-switch"></th><th class="next"><i class="fa fa-chevron-right fi-arrow-right"/></th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>'};e.template='<div class="datepicker"><div class="datepicker-minutes"><table class=" table-condensed">'+e.headTemplate+e.contTemplate+e.footTemplate+'</table></div><div class="datepicker-hours"><table class=" table-condensed">'+e.headTemplate+e.contTemplate+e.footTemplate+'</table></div><div class="datepicker-days"><table class=" table-condensed">'+e.headTemplate+"<tbody></tbody>"+e.footTemplate+'</table></div><div class="datepicker-months"><table class="table-condensed">'+e.headTemplate+e.contTemplate+e.footTemplate+'</table></div><div class="datepicker-years"><table class="table-condensed">'+e.headTemplate+e.contTemplate+e.footTemplate+'</table></div><a class="button datepicker-close tiny alert right" style="width:auto;"><i class="fa fa-remove fa-times fi-x"></i></a></div>',a.fn.fdatepicker.DPGlobal=e}(window.jQuery); 23702/** 23703 23704 * Simplified Chinese translation for foundation-datepicker 23705 23706 * Yuan Cheung <[email protected]> 23707 23708 */ 23709 23710;(function($){ 23711 23712 $.fn.fdatepicker.dates['zh-CN'] = { 23713 23714 days: ["æææ¥", "ææä¸", "ææäº", "ææä¸", "ææå", "ææäº", "ææå "], 23715 23716 daysShort: ["卿¥", "å¨ä¸", "å¨äº", "å¨ä¸", "å¨å", "å¨äº", "å¨å "], 23717 23718 daysMin: ["æ¥", "ä¸", "äº", "ä¸", "å", "äº", "å "], 23719 23720 months: ["䏿", "äºæ", "䏿", "åæ", "äºæ", "å æ", "䏿", "å «æ", "乿", "åæ", "å䏿", "åäºæ"], 23721 23722 monthsShort: ["ä¸", "äº", "ä¸", "å", "äº", "å ", "ä¸", "å «", "ä¹", "å", "åä¸", "åäº"], 23723 23724 today: 'ä»å¤©' 23725 23726 }; 23727 23728}(jQuery)); 23729 23730 23731/** 23732 23733 * Traditional Chinese translation for fondation-datepicker 23734 23735 * Rung-Sheng Jang <[email protected]> 23736 23737 */ 23738 23739;(function($){ 23740 23741 $.fn.fdatepicker.dates['zh-TW'] = { 23742 23743 days: ["æææ¥", "ææä¸", "ææäº", "ææä¸", "ææå", "ææäº", "ææå "], 23744 23745 daysShort: ["鱿¥", "é±ä¸", "é±äº", "é±ä¸", "é±å", "é±äº", "é±å "], 23746 23747 daysMin: ["æ¥", "ä¸", "äº", "ä¸", "å", "äº", "å "], 23748 23749 months: ["䏿", "äºæ", "䏿", "åæ", "äºæ", "å æ", "䏿", "å «æ", "乿", "åæ", "å䏿", "åäºæ"], 23750 23751 monthsShort: ["ä¸", "äº", "ä¸", "å", "äº", "å ", "ä¸", "å «", "ä¹", "å", "åä¸", "åäº"], 23752 23753 today: 'ä»å¤©' 23754 23755 }; 23756 23757}(jQuery)); 23758 23759 23760/* 23761 23762 * Foundation Responsive Library 23763 23764 * http://foundation.zurb.com 23765 23766 * Copyright 2015, ZURB 23767 23768 * Free to use under the MIT license. 23769 23770 * http://www.opensource.org/licenses/mit-license.php 23771 23772*/ 23773
23774!function(t,e,i,s){"use strict";function n(t){return("string"==typeof t||t instanceof String)&&(t=t.replace(/^['\\/"]+|(;\s?})+|['\\/"]+$/g,"")),t}function a(t){this.selector=t,this.query=""}var o=function(e){var i=t("head");i.prepend(t.map(e,function(t){return 0===i.has("."+t).length?'<meta class="'+t+'" />':void 0}))};o(["foundation-mq-small","foundation-mq-small-only","foundation-mq-medium","foundation-mq-medium-only","foundation-mq-large","foundation-mq-large-only","foundation-mq-xlarge","foundation-mq-xlarge-only","foundation-mq-xxlarge","foundation-data-attribute-namespace"]),t(function(){"undefined"!=typeof FastClick&&"undefined"!=typeof i.body&&FastClick.attach(i.body)});var r=function(e,s){if("string"==typeof e){if(s){var n;if(s.jquery){if(n=s[0],!n)return s}else n=s;return t(n.querySelectorAll(e))}return t(i.querySelectorAll(e))}return t(e,s)},l=function(t){var e=[];return t||e.push("data"),this.namespace.length>0&&e.push(this.namespace),e.push(this.name),e.join("-")},d=function(t){for(var e=t.split("-"),i=e.length,s=[];i--;)0!==i?s.push(e[i]):this.namespace.length>0?s.push(this.namespace,e[i]):s.push(e[i]);return s.reverse().join("-")},c=function(e,i){var s=this,n=function(){var n=r(this),a=!n.data(s.attr_name(!0)+"-init");n.data(s.attr_name(!0)+"-init",t.extend({},s.settings,i||e,s.data_options(n))),a&&s.events(this)};return r(this.scope).is("["+this.attr_name()+"]")?n.call(this.scope):r("["+this.attr_name()+"]",this.scope).each(n),"string"==typeof e?this[e].call(this,i):void 0},h=function(t,e){function i(){e(t[0])}function s(){if(this.one("load",i),/MSIE (\d+\.\d+);/.test(navigator.userAgent)){var t=this.attr("src"),e=t.match(/\?/)?"&":"?";e+="random="+(new Date).getTime(),this.attr("src",t+e)}}return t.attr("src")?void(t[0].complete||4===t[0].readyState?i():s.call(t)):void i()};/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas, David Knight. Dual MIT/BSD license */ 23775 23776e.matchMedia||(e.matchMedia=function(){var t=e.styleMedia||e.media;if(!t){var s=i.createElement("style"),n=i.getElementsByTagName("script")[0],a=null;s.type="text/css",s.id="matchmediajs-test",n.parentNode.insertBefore(s,n),a="getComputedStyle"in e&&e.getComputedStyle(s,null)||s.currentStyle,t={matchMedium:function(t){var e="@media "+t+"{ #matchmediajs-test { width: 1px; } }";return s.styleSheet?s.styleSheet.cssText=e:s.textContent=e,"1px"===a.width}}}return function(e){return{matches:t.matchMedium(e||"all"),media:e||"all"}}}()),/* 23777 23778 * jquery.requestAnimationFrame 23779 23780 * https://github.com/gnarf37/jquery-requestAnimationFrame 23781 23782 * Requires jQuery 1.8+ 23783 23784 * 23785 23786 * Copyright (c) 2012 Corey Frang 23787 23788 * Licensed under the MIT license. 23789 23790 */ 23791 23792function(t){function i(){s&&(o(i),l&&t.fx.tick())}for(var s,n=0,a=["webkit","moz"],o=e.requestAnimationFrame,r=e.cancelAnimationFrame,l="undefined"!=typeof t.fx;n<a.length&&!o;n++)o=e[a[n]+"RequestAnimationFrame"],r=r||e[a[n]+"CancelAnimationFrame"]||e[a[n]+"CancelRequestAnimationFrame"];o?(e.requestAnimationFrame=o,e.cancelAnimationFrame=r,l&&(t.fx.timer=function(e){e()&&t.timers.push(e)&&!s&&(s=!0,i())},t.fx.stop=function(){s=!1})):(e.requestAnimationFrame=function(t){var i=(new Date).getTime(),s=Math.max(0,16-(i-n)),a=e.setTimeout(function(){t(i+s)},s);return n=i+s,a},e.cancelAnimationFrame=function(t){clearTimeout(t)})}(t),a.prototype.toString=function(){return this.query||(this.query=r(this.selector).css("font-family").replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g,""))},e.Foundation={name:"Foundation",version:"5.5.3",media_queries:{small:new a(".foundation-mq-small"),"small-only":new a(".foundation-mq-small-only"),medium:new a(".foundation-mq-medium"),"medium-only":new a(".foundation-mq-medium-only"),large:new a(".foundation-mq-large"),"large-only":new a(".foundation-mq-large-only"),xlarge:new a(".foundation-mq-xlarge"),"xlarge-only":new a(".foundation-mq-xlarge-only"),xxlarge:new a(".foundation-mq-xxlarge")},stylesheet:t("<style></style>").appendTo("head")[0].sheet,global:{namespace:s},init:function(t,i,s,n,a){var o=[t,s,n,a],l=[];
vendor: 77,614 bytes, lines 23792-23796
23792if(this.rtl=/rtl/i.test(r("html").attr("dir")),this.scope=t||this.scope,this.set_namespace(),i&&"string"==typeof i&&!/reflow/i.test(i))this.libs.hasOwnProperty(i)&&l.push(this.init_lib(i,o));else for(var d in this.libs)l.push(this.init_lib(d,i));return r(e).load(function(){r(e).trigger("resize.fndtn.clearing").trigger("resize.fndtn.dropdown").trigger("resize.fndtn.equalizer").trigger("resize.fndtn.interchange").trigger("resize.fndtn.joyride").trigger("resize.fndtn.magellan").trigger("resize.fndtn.topbar").trigger("resize.fndtn.slider")}),t},init_lib:function(e,i){return this.libs.hasOwnProperty(e)?(this.patch(this.libs[e]),i&&i.hasOwnProperty(e)?("undefined"!=typeof this.libs[e].settings?t.extend(!0,this.libs[e].settings,i[e]):"undefined"!=typeof this.libs[e].defaults&&t.extend(!0,this.libs[e].defaults,i[e]),this.libs[e].init.apply(this.libs[e],[this.scope,i[e]])):(i=i instanceof Array?i:new Array(i),this.libs[e].init.apply(this.libs[e],i))):function(){}},patch:function(t){t.scope=this.scope,t.namespace=this.global.namespace,t.rtl=this.rtl,t.data_options=this.utils.data_options,t.attr_name=l,t.add_namespace=d,t.bindings=c,t.S=this.utils.S},inherit:function(t,e){for(var i=e.split(" "),s=i.length;s--;)this.utils.hasOwnProperty(i[s])&&(t[i[s]]=this.utils[i[s]])},set_namespace:function(){var e=this.global.namespace===s?t(".foundation-data-attribute-namespace").css("font-family"):this.global.namespace;this.global.namespace=e===s||/false/i.test(e)?"":e},libs:{},utils:{S:r,throttle:function(t,e){var i=null;return function(){var s=this,n=arguments;null==i&&(i=setTimeout(function(){t.apply(s,n),i=null},e))}},debounce:function(t,e,i){var s,n;return function(){var a=this,o=arguments,r=function(){s=null,i||(n=t.apply(a,o))},l=i&&!s;return clearTimeout(s),s=setTimeout(r,e),l&&(n=t.apply(a,o)),n}},data_options:function(e,i){function s(t){return!isNaN(t-0)&&null!==t&&""!==t&&t!==!1&&t!==!0}function n(e){return"string"==typeof e?t.trim(e):e}i=i||"options";var a,o,r,l={},d=function(t){var e=Foundation.global.namespace;return t.data(e.length>0?e+"-"+i:i)},c=d(e);if("object"==typeof c)return c;for(r=(c||":").split(";"),a=r.length;a--;)o=r[a].split(":"),o=[o[0],o.slice(1).join(":")],/true/i.test(o[1])&&(o[1]=!0),/false/i.test(o[1])&&(o[1]=!1),s(o[1])&&(o[1]=-1===o[1].indexOf(".")?parseInt(o[1],10):parseFloat(o[1])),2===o.length&&o[0].length>0&&(l[n(o[0])]=n(o[1]));return l},register_media:function(e,i){Foundation.media_queries[e]===s&&(t("head").append('<meta class="'+i+'"/>'),Foundation.media_queries[e]=n(t("."+i).css("font-family")))},add_custom_rule:function(t,e){if(e===s&&Foundation.stylesheet)Foundation.stylesheet.insertRule(t,Foundation.stylesheet.cssRules.length);else{var i=Foundation.media_queries[e];i!==s&&Foundation.stylesheet.insertRule("@media "+Foundation.media_queries[e]+"{ "+t+" }",Foundation.stylesheet.cssRules.length)}},image_loaded:function(t,e){function i(t){for(var e=t.length,i=e-1;i>=0;i--)if(t.attr("height")===s)return!1;return!0}var n=this,a=t.length;(0===a||i(t))&&e(t),t.each(function(){h(n.S(this),function(){a-=1,0===a&&e(t)})})},random_str:function(){return this.fidx||(this.fidx=0),this.prefix=this.prefix||[this.name||"F",(+new Date).toString(36)].join("-"),this.prefix+(this.fidx++).toString(36)},match:function(t){return e.matchMedia(t).matches},is_small_up:function(){return this.match(Foundation.media_queries.small)},is_medium_up:function(){return this.match(Foundation.media_queries.medium)},is_large_up:function(){return this.match(Foundation.media_queries.large)},is_xlarge_up:function(){return this.match(Foundation.media_queries.xlarge)},is_xxlarge_up:function(){return this.match(Foundation.media_queries.xxlarge)},is_small_only:function(){return!(this.is_medium_up()||this.is_large_up()||this.is_xlarge_up()||this.is_xxlarge_up())},is_medium_only:function(){return this.is_medium_up()&&!this.is_large_up()&&!this.is_xlarge_up()&&!this.is_xxlarge_up()},is_large_only:function(){return this.is_medium_up()&&this.is_large_up()&&!this.is_xlarge_up()&&!this.is_xxlarge_up()},is_xlarge_only:function(){return this.is_medium_up()&&this.is_large_up()&&this.is_xlarge_up()&&!this.is_xxlarge_up()},is_xxlarge_only:function(){return this.is_medium_up()&&this.is_large_up()&&this.is_xlarge_up()&&this.is_xxlarge_up()}}},t.fn.foundation=function(){var t=Array.prototype.slice.call(arguments,0);return this.each(function(){return Foundation.init.apply(Foundation,[this].concat(t)),this})}}(jQuery,window,window.document),function(t,e){"use strict";Foundation.libs.slider={name:"slider",version:"5.5.3",settings:{start:0,end:100,step:1,precision:2,initial:null,display_selector:"",vertical:!1,trigger_input_change:!1,on_change:function(){}},cache:{},init:function(t,e,i){Foundation.inherit(this,"throttle"),this.bindings(e,i),this.reflow()},events:function(){var i=this;t(this.scope).off(".slider").on("mousedown.fndtn.slider touchstart.fndtn.slider pointerdown.fndtn.slider","["+i.attr_name()+"]:not(.disabled, [disabled]) .range-slider-handle",function(e){i.cache.active||(e.preventDefault(),i.set_active_slider(t(e.target)))}).on("mousemove.fndtn.slider touchmove.fndtn.slider pointermove.fndtn.slider",function(s){if(i.cache.active)if(s.preventDefault(),t.data(i.cache.active[0],"settings").vertical){var n=0;s.pageY||(n=e.scrollY),i.calculate_position(i.cache.active,i.get_cursor_position(s,"y")+n)}else i.calculate_position(i.cache.active,i.get_cursor_position(s,"x"))}).on("mouseup.fndtn.slider touchend.fndtn.slider pointerup.fndtn.slider",function(s){if(!i.cache.active){var n="slider"===t(s.target).attr("role")?t(s.target):t(s.target).closest(".range-slider").find("[role='slider']");if(n.length&&!n.parent().hasClass("disabled")&&!n.parent().attr("disabled"))if(i.set_active_slider(n),t.data(i.cache.active[0],"settings").vertical){var a=0;s.pageY||(a=e.scrollY),i.calculate_position(i.cache.active,i.get_cursor_position(s,"y")+a)}else i.calculate_position(i.cache.active,i.get_cursor_position(s,"x"))}i.remove_active_slider()}).on("change.fndtn.slider",function(){i.settings.on_change()}),i.S(e).on("resize.fndtn.slider",i.throttle(function(){i.reflow()},300)),this.S("["+this.attr_name()+"]").each(function(){var e=t(this),s=e.children(".range-slider-handle")[0],n=i.initialize_settings(s);""!=n.display_selector&&t(n.display_selector).each(function(){t(this).attr("value")&&t(this).off("change").on("change",function(){e.foundation("slider","set_value",t(this).val())})})})},get_cursor_position:function(t,e){var i,s="page"+e.toUpperCase(),n="client"+e.toUpperCase();return"undefined"!=typeof t[s]?i=t[s]:"undefined"!=typeof t.originalEvent[n]?i=t.originalEvent[n]:t.originalEvent.touches&&t.originalEvent.touches[0]&&"undefined"!=typeof t.originalEvent.touches[0][n]?i=t.originalEvent.touches[0][n]:t.currentPoint&&"undefined"!=typeof t.currentPoint[e]&&(i=t.currentPoint[e]),i},set_active_slider:function(t){this.cache.active=t},remove_active_slider:function(){this.cache.active=null},calculate_position:function(e,i){var s=this,n=t.data(e[0],"settings"),a=(t.data(e[0],"handle_l"),t.data(e[0],"handle_o"),t.data(e[0],"bar_l")),o=t.data(e[0],"bar_o");requestAnimationFrame(function(){var t;t=Foundation.rtl&&!n.vertical?s.limit_to((o+a-i)/a,0,1):s.limit_to((i-o)/a,0,1),t=n.vertical?1-t:t;var r=s.normalized_value(t,n.start,n.end,n.step,n.precision);s.set_ui(e,r)})},set_ui:function(e,i){var s=t.data(e[0],"settings"),n=t.data(e[0],"handle_l"),a=t.data(e[0],"bar_l"),o=this.normalized_percentage(i,s.start,s.end),r=o*(a-n)-1,l=100*o,d=e.parent(),c=e.parent().children("input[type=hidden]");Foundation.rtl&&!s.vertical&&(r=-r),r=s.vertical?-r+a-n+1:r,this.set_translate(e,r,s.vertical),s.vertical?e.siblings(".range-slider-active-segment").css("height",l+"%"):e.siblings(".range-slider-active-segment").css("width",l+"%"),d.attr(this.attr_name(),i).trigger("change.fndtn.slider"),c.val(i),s.trigger_input_change&&c.trigger("change.fndtn.slider"),e[0].hasAttribute("aria-valuemin")||e.attr({"aria-valuemin":s.start,"aria-valuemax":s.end}),e.attr("aria-valuenow",i),""!=s.display_selector&&t(s.display_selector).each(function(){this.hasAttribute("value")?t(this).val(i):t(this).text(i)})},normalized_percentage:function(t,e,i){return Math.min(1,(t-e)/(i-e))},normalized_value:function(t,e,i,s,n){var a=i-e,o=t*a,r=(o-o%s)/s,l=o%s,d=l>=.5*s?s:0;return(r*s+d+e).toFixed(n)},set_translate:function(e,i,s){s?t(e).css("-webkit-transform","translateY("+i+"px)").css("-moz-transform","translateY("+i+"px)").css("-ms-transform","translateY("+i+"px)").css("-o-transform","translateY("+i+"px)").css("transform","translateY("+i+"px)"):t(e).css("-webkit-transform","translateX("+i+"px)").css("-moz-transform","translateX("+i+"px)").css("-ms-transform","translateX("+i+"px)").css("-o-transform","translateX("+i+"px)").css("transform","translateX("+i+"px)")},limit_to:function(t,e,i){return Math.min(Math.max(t,e),i)},initialize_settings:function(e){var i,s=t.extend({},this.settings,this.data_options(t(e).parent()));return null===s.precision&&(i=(""+s.step).match(/\.([\d]*)/),s.precision=i&&i[1]?i[1].length:0),s.vertical?(t.data(e,"bar_o",t(e).parent().offset().top),t.data(e,"bar_l",t(e).parent().outerHeight()),t.data(e,"handle_o",t(e).offset().top),t.data(e,"handle_l",t(e).outerHeight())):(t.data(e,"bar_o",t(e).parent().offset().left),t.data(e,"bar_l",t(e).parent().outerWidth()),t.data(e,"handle_o",t(e).offset().left),t.data(e,"handle_l",t(e).outerWidth())),t.data(e,"bar",t(e).parent()),t.data(e,"settings",s)},set_initial_position:function(e){var i=t.data(e.children(".range-slider-handle")[0],"settings"),s="number"!=typeof i.initial||isNaN(i.initial)?Math.floor(.5*(i.end-i.start)/i.step)*i.step+i.start:i.initial,n=e.children(".range-slider-handle");this.set_ui(n,s)},set_value:function(e){var i=this;t("["+i.attr_name()+"]",this.scope).each(function(){t(this).attr(i.attr_name(),e)}),t(this.scope).attr(i.attr_name())&&t(this.scope).attr(i.attr_name(),e),i.reflow()},reflow:function(){var e=this;e.S("["+this.attr_name()+"]").each(function(){var i=t(this).children(".range-slider-handle")[0],s=t(this).attr(e.attr_name());e.initialize_settings(i),s?e.set_ui(t(i),parseFloat(s)):e.set_initial_position(t(this))})}}}(jQuery,window,window.document),function(t,e,i,s){"use strict";Foundation.libs.joyride={name:"joyride",version:"5.5.3",defaults:{expose:!1,modal:!0,keyboard:!0,tip_location:"bottom",nub_position:"auto",scroll_speed:1500,scroll_animation:"linear",timer:0,start_timer_on_click:!0,start_offset:0,next_button:!0,prev_button:!0,tip_animation:"fade",pause_after:[],exposed:[],tip_animation_fade_speed:300,cookie_monster:!1,cookie_name:"joyride",cookie_domain:!1,cookie_expires:365,tip_container:"body",abort_on_close:!0,tip_location_patterns:{top:["bottom"],bottom:[],left:["right","top","bottom"],right:["left","top","bottom"]},post_ride_callback:function(){},post_step_callback:function(){},pre_step_callback:function(){},pre_ride_callback:function(){},post_expose_callback:function(){},template:{link:'<a href="#close" class="joyride-close-tip">×</a>',timer:'<div class="joyride-timer-indicator-wrap"><span class="joyride-timer-indicator"></span></div>',tip:'<div class="joyride-tip-guide"><span class="joyride-nub"></span></div>',wrapper:'<div class="joyride-content-wrapper"></div>',button:'<a href="#" class="small button joyride-next-tip"></a>',prev_button:'<a href="#" class="small button joyride-prev-tip"></a>',modal:'<div class="joyride-modal-bg"></div>',expose:'<div class="joyride-expose-wrapper"></div>',expose_cover:'<div class="joyride-expose-cover"></div>'},expose_add_class:""},init:function(e,i,s){Foundation.inherit(this,"throttle random_str"),this.settings=this.settings||t.extend({},this.defaults,s||i),this.bindings(i,s)},go_next:function(){this.settings.$li.next().length<1?this.end():this.settings.timer>0?(clearTimeout(this.settings.automate),this.hide(),this.show(),this.startTimer()):(this.hide(),this.show())},go_prev:function(){this.settings.$li.prev().length<1||(this.settings.timer>0?(clearTimeout(this.settings.automate),this.hide(),this.show(null,!0),this.startTimer()):(this.hide(),this.show(null,!0)))},events:function(){var i=this;t(this.scope).off(".joyride").on("click.fndtn.joyride",".joyride-next-tip, .joyride-modal-bg",function(t){t.preventDefault(),this.go_next()}.bind(this)).on("click.fndtn.joyride",".joyride-prev-tip",function(t){t.preventDefault(),this.go_prev()}.bind(this)).on("click.fndtn.joyride",".joyride-close-tip",function(t){t.preventDefault(),this.end(this.settings.abort_on_close)}.bind(this)).on("keyup.fndtn.joyride",function(t){if(this.settings.keyboard&&this.settings.riding)switch(t.which){case 39:t.preventDefault(),this.go_next();break;case 37:t.preventDefault(),this.go_prev();break;case 27:t.preventDefault(),this.end(this.settings.abort_on_close)}}.bind(this)),t(e).off(".joyride").on("resize.fndtn.joyride",i.throttle(function(){if(t("["+i.attr_name()+"]").length>0&&i.settings.$next_tip&&i.settings.riding){if(i.settings.exposed.length>0){var e=t(i.settings.exposed);e.each(function(){var e=t(this);i.un_expose(e),i.expose(e)})}i.is_phone()?i.pos_phone():i.pos_default(!1)}},100))},start:function(){var e=this,i=t("["+this.attr_name()+"]",this.scope),s=["timer","scrollSpeed","startOffset","tipAnimationFadeSpeed","cookieExpires"],n=s.length;!i.length>0||(this.settings.init||this.events(),this.settings=i.data(this.attr_name(!0)+"-init"),this.settings.$content_el=i,this.settings.$body=t(this.settings.tip_container),this.settings.body_offset=t(this.settings.tip_container).position(),this.settings.$tip_content=this.settings.$content_el.find("> li"),this.settings.paused=!1,this.settings.attempts=0,this.settings.riding=!0,"function"!=typeof t.cookie&&(this.settings.cookie_monster=!1),(!this.settings.cookie_monster||this.settings.cookie_monster&&!t.cookie(this.settings.cookie_name))&&(this.settings.$tip_content.each(function(i){var a=t(this);this.settings=t.extend({},e.defaults,e.data_options(a));for(var o=n;o--;)e.settings[s[o]]=parseInt(e.settings[s[o]],10);e.create({$li:a,index:i})}),!this.settings.start_timer_on_click&&this.settings.timer>0?(this.show("init"),this.startTimer()):this.show("init")))},resume:function(){this.set_li(),this.show()},tip_template:function(e){var i,s;return e.tip_class=e.tip_class||"",i=t(this.settings.template.tip).addClass(e.tip_class),s=t.trim(t(e.li).html())+this.prev_button_text(e.prev_button_text,e.index)+this.button_text(e.button_text)+this.settings.template.link+this.timer_instance(e.index),i.append(t(this.settings.template.wrapper)),i.first().attr(this.add_namespace("data-index"),e.index),t(".joyride-content-wrapper",i).append(s),i[0]},timer_instance:function(e){var i;return i=0===e&&this.settings.start_timer_on_click&&this.settings.timer>0||0===this.settings.timer?"":t(this.settings.template.timer)[0].outerHTML},button_text:function(e){return this.settings.tip_settings.next_button?(e=t.trim(e)||"Next",e=t(this.settings.template.button).append(e)[0].outerHTML):e="",e},prev_button_text:function(e,i){return this.settings.tip_settings.prev_button?(e=t.trim(e)||"Previous",e=0==i?t(this.settings.template.prev_button).append(e).addClass("disabled")[0].outerHTML:t(this.settings.template.prev_button).append(e)[0].outerHTML):e="",e},create:function(e){this.settings.tip_settings=t.extend({},this.settings,this.data_options(e.$li));var i=e.$li.attr(this.add_namespace("data-button"))||e.$li.attr(this.add_namespace("data-text")),s=e.$li.attr(this.add_namespace("data-button-prev"))||e.$li.attr(this.add_namespace("data-prev-text")),n=e.$li.attr("class"),a=t(this.tip_template({tip_class:n,index:e.index,button_text:i,prev_button_text:s,li:e.$li}));t(this.settings.tip_container).append(a)},show:function(e,i){var n=null;if(this.settings.$li===s||-1===t.inArray(this.settings.$li.index(),this.settings.pause_after))if(this.settings.paused?this.settings.paused=!1:this.set_li(e,i),this.settings.attempts=0,this.settings.$li.length&&this.settings.$target.length>0){if(e&&(this.settings.pre_ride_callback(this.settings.$li.index(),this.settings.$next_tip),this.settings.modal&&this.show_modal()),this.settings.pre_step_callback(this.settings.$li.index(),this.settings.$next_tip),this.settings.modal&&this.settings.expose&&this.expose(),this.settings.tip_settings=t.extend({},this.settings,this.data_options(this.settings.$li)),this.settings.timer=parseInt(this.settings.timer,10),this.settings.tip_settings.tip_location_pattern=this.settings.tip_location_patterns[this.settings.tip_settings.tip_location],!/body/i.test(this.settings.$target.selector)&&!this.settings.expose){var a=t(".joyride-modal-bg");/pop/i.test(this.settings.tipAnimation)?a.hide():a.fadeOut(this.settings.tipAnimationFadeSpeed),this.scroll_to()}this.is_phone()?this.pos_phone(!0):this.pos_default(!0),n=this.settings.$next_tip.find(".joyride-timer-indicator"),/pop/i.test(this.settings.tip_animation)?(n.width(0),this.settings.timer>0?(this.settings.$next_tip.show(),setTimeout(function(){n.animate({width:n.parent().width()},this.settings.timer,"linear")}.bind(this),this.settings.tip_animation_fade_speed)):this.settings.$next_tip.show()):/fade/i.test(this.settings.tip_animation)&&(n.width(0),this.settings.timer>0?(this.settings.$next_tip.fadeIn(this.settings.tip_animation_fade_speed).show(),setTimeout(function(){n.animate({width:n.parent().width()},this.settings.timer,"linear")}.bind(this),this.settings.tip_animation_fade_speed)):this.settings.$next_tip.fadeIn(this.settings.tip_animation_fade_speed)),this.settings.$current_tip=this.settings.$next_tip}else this.settings.$li&&this.settings.$target.length<1?this.show(e,i):this.end();else this.settings.paused=!0},is_phone:function(){return matchMedia(Foundation.media_queries.small).matches&&!matchMedia(Foundation.media_queries.medium).matches},hide:function(){this.settings.modal&&this.settings.expose&&this.un_expose(),this.settings.modal||t(".joyride-modal-bg").hide(),this.settings.$current_tip.css("visibility","hidden"),setTimeout(t.proxy(function(){this.hide(),this.css("visibility","visible")},this.settings.$current_tip),0),this.settings.post_step_callback(this.settings.$li.index(),this.settings.$current_tip)},set_li:function(t,e){t?(this.settings.$li=this.settings.$tip_content.eq(this.settings.start_offset),this.set_next_tip(),this.settings.$current_tip=this.settings.$next_tip):(this.settings.$li=e?this.settings.$li.prev():this.settings.$li.next(),this.set_next_tip()),this.set_target()},set_next_tip:function(){this.settings.$next_tip=t(".joyride-tip-guide").eq(this.settings.$li.index()),this.settings.$next_tip.data("closed","")},set_target:function(){var e=this.settings.$li.attr(this.add_namespace("data-class")),s=this.settings.$li.attr(this.add_namespace("data-id")),n=function(){return s?t(i.getElementById(s)):e?t("."+e).first():t("body")};this.settings.$target=n()},scroll_to:function(){var i,s;i=t(e).height()/2,s=Math.ceil(this.settings.$target.offset().top-i+this.settings.$next_tip.outerHeight()),0!=s&&t("html, body").stop().animate({scrollTop:s},this.settings.scroll_speed,"swing")},paused:function(){return-1===t.inArray(this.settings.$li.index()+1,this.settings.pause_after)},restart:function(){this.hide(),this.settings.$li=s,this.show("init")},pos_default:function(t){var e=this.settings.$next_tip.find(".joyride-nub"),i=Math.ceil(e.outerWidth()/2),s=Math.ceil(e.outerHeight()/2),n=t||!1;if(n&&(this.settings.$next_tip.css("visibility","hidden"),this.settings.$next_tip.show()),/body/i.test(this.settings.$target.selector))this.settings.$li.length&&this.pos_modal(e);else{var a=this.settings.tip_settings.tipAdjustmentY?parseInt(this.settings.tip_settings.tipAdjustmentY):0,o=this.settings.tip_settings.tipAdjustmentX?parseInt(this.settings.tip_settings.tipAdjustmentX):0;this.bottom()?(this.settings.$next_tip.css(this.rtl?{top:this.settings.$target.offset().top+s+this.settings.$target.outerHeight()+a,left:this.settings.$target.offset().left+this.settings.$target.outerWidth()-this.settings.$next_tip.outerWidth()+o}:{top:this.settings.$target.offset().top+s+this.settings.$target.outerHeight()+a,left:this.settings.$target.offset().left+o}),this.nub_position(e,this.settings.tip_settings.nub_position,"top")):this.top()?(this.settings.$next_tip.css(this.rtl?{top:this.settings.$target.offset().top-this.settings.$next_tip.outerHeight()-s+a,left:this.settings.$target.offset().left+this.settings.$target.outerWidth()-this.settings.$next_tip.outerWidth()}:{top:this.settings.$target.offset().top-this.settings.$next_tip.outerHeight()-s+a,left:this.settings.$target.offset().left+o}),this.nub_position(e,this.settings.tip_settings.nub_position,"bottom")):this.right()?(this.settings.$next_tip.css({top:this.settings.$target.offset().top+a,left:this.settings.$target.outerWidth()+this.settings.$target.offset().left+i+o}),this.nub_position(e,this.settings.tip_settings.nub_position,"left")):this.left()&&(this.settings.$next_tip.css({top:this.settings.$target.offset().top+a,left:this.settings.$target.offset().left-this.settings.$next_tip.outerWidth()-i+o}),this.nub_position(e,this.settings.tip_settings.nub_position,"right")),!this.visible(this.corners(this.settings.$next_tip))&&this.settings.attempts<this.settings.tip_settings.tip_location_pattern.length&&(e.removeClass("bottom").removeClass("top").removeClass("right").removeClass("left"),this.settings.tip_settings.tip_location=this.settings.tip_settings.tip_location_pattern[this.settings.attempts],this.settings.attempts++,this.pos_default())}n&&(this.settings.$next_tip.hide(),this.settings.$next_tip.css("visibility","visible"))},pos_phone:function(e){var i=this.settings.$next_tip.outerHeight(),s=(this.settings.$next_tip.offset(),this.settings.$target.outerHeight()),n=t(".joyride-nub",this.settings.$next_tip),a=Math.ceil(n.outerHeight()/2),o=e||!1;n.removeClass("bottom").removeClass("top").removeClass("right").removeClass("left"),o&&(this.settings.$next_tip.css("visibility","hidden"),this.settings.$next_tip.show()),/body/i.test(this.settings.$target.selector)?this.settings.$li.length&&this.pos_modal(n):this.top()?(this.settings.$next_tip.offset({top:this.settings.$target.offset().top-i-a}),n.addClass("bottom")):(this.settings.$next_tip.offset({top:this.settings.$target.offset().top+s+a}),n.addClass("top")),o&&(this.settings.$next_tip.hide(),this.settings.$next_tip.css("visibility","visible"))},pos_modal:function(t){this.center(),t.hide(),this.show_modal()},show_modal:function(){if(!this.settings.$next_tip.data("closed")){var e=t(".joyride-modal-bg");if(e.length<1){var e=t(this.settings.template.modal);e.appendTo("body")}/pop/i.test(this.settings.tip_animation)?e.show():e.fadeIn(this.settings.tip_animation_fade_speed)}},expose:function(){var i,s,n,a,o,r="expose-"+this.random_str(6);if(arguments.length>0&&arguments[0]instanceof t)n=arguments[0];else{if(!this.settings.$target||/body/i.test(this.settings.$target.selector))return!1;n=this.settings.$target}return n.length<1?(e.console&&console.error("element not valid",n),!1):(i=t(this.settings.template.expose),this.settings.$body.append(i),i.css({top:n.offset().top,left:n.offset().left,width:n.outerWidth(!0),height:n.outerHeight(!0)}),s=t(this.settings.template.expose_cover),a={zIndex:n.css("z-index"),position:n.css("position")},o=null==n.attr("class")?"":n.attr("class"),n.css("z-index",parseInt(i.css("z-index"))+1),"static"==a.position&&n.css("position","relative"),n.data("expose-css",a),n.data("orig-class",o),n.attr("class",o+" "+this.settings.expose_add_class),s.css({top:n.offset().top,left:n.offset().left,width:n.outerWidth(!0),height:n.outerHeight(!0)}),this.settings.modal&&this.show_modal(),this.settings.$body.append(s),i.addClass(r),s.addClass(r),n.data("expose",r),this.settings.post_expose_callback(this.settings.$li.index(),this.settings.$next_tip,n),void this.add_exposed(n))},un_expose:function(){var i,s,n,a,o,r=!1;if(arguments.length>0&&arguments[0]instanceof t)s=arguments[0];else{if(!this.settings.$target||/body/i.test(this.settings.$target.selector))return!1;s=this.settings.$target}return s.length<1?(e.console&&console.error("element not valid",s),!1):(i=s.data("expose"),n=t("."+i),arguments.length>1&&(r=arguments[1]),r===!0?t(".joyride-expose-wrapper,.joyride-expose-cover").remove():n.remove(),a=s.data("expose-css"),"auto"==a.zIndex?s.css("z-index",""):s.css("z-index",a.zIndex),a.position!=s.css("position")&&("static"==a.position?s.css("position",""):s.css("position",a.position)),o=s.data("orig-class"),s.attr("class",o),s.removeData("orig-classes"),s.removeData("expose"),s.removeData("expose-z-index"),void this.remove_exposed(s))},add_exposed:function(e){this.settings.exposed=this.settings.exposed||[],e instanceof t||"object"==typeof e?this.settings.exposed.push(e[0]):"string"==typeof e&&this.settings.exposed.push(e)},remove_exposed:function(e){var i,s;for(e instanceof t?i=e[0]:"string"==typeof e&&(i=e),this.settings.exposed=this.settings.exposed||[],s=this.settings.exposed.length;s--;)if(this.settings.exposed[s]==i)return void this.settings.exposed.splice(s,1)},center:function(){var i=t(e);return this.settings.$next_tip.css({top:(i.height()-this.settings.$next_tip.outerHeight())/2+i.scrollTop(),left:(i.width()-this.settings.$next_tip.outerWidth())/2+i.scrollLeft()}),!0},bottom:function(){return/bottom/i.test(this.settings.tip_settings.tip_location)},top:function(){return/top/i.test(this.settings.tip_settings.tip_location)},right:function(){return/right/i.test(this.settings.tip_settings.tip_location)},left:function(){return/left/i.test(this.settings.tip_settings.tip_location)},corners:function(i){if(0===i.length)return[!1,!1,!1,!1];var s=t(e),n=s.height()/2,a=Math.ceil(this.settings.$target.offset().top-n+this.settings.$next_tip.outerHeight()),o=s.width()+s.scrollLeft(),r=s.height()+a,l=s.height()+s.scrollTop(),d=s.scrollTop();return d>a&&(d=0>a?0:a),r>l&&(l=r),[i.offset().top<d,o<i.offset().left+i.outerWidth(),l<i.offset().top+i.outerHeight(),s.scrollLeft()>i.offset().left]},visible:function(t){for(var e=t.length;e--;)if(t[e])return!1;return!0},nub_position:function(t,e,i){t.addClass("auto"===e?i:e)},startTimer:function(){this.settings.$li.length?this.settings.automate=setTimeout(function(){this.hide(),this.show(),this.startTimer()}.bind(this),this.settings.timer):clearTimeout(this.settings.automate)},end:function(e){this.settings.cookie_monster&&t.cookie(this.settings.cookie_name,"ridden",{expires:this.settings.cookie_expires,domain:this.settings.cookie_domain}),this.settings.timer>0&&clearTimeout(this.settings.automate),this.settings.modal&&this.settings.expose&&this.un_expose(),t(this.scope).off("keyup.joyride"),this.settings.$next_tip.data("closed",!0),this.settings.riding=!1,t(".joyride-modal-bg").hide(),this.settings.$current_tip.hide(),("undefined"==typeof e||e===!1)&&(this.settings.post_step_callback(this.settings.$li.index(),this.settings.$current_tip),this.settings.post_ride_callback(this.settings.$li.index(),this.settings.$current_tip)),t(".joyride-tip-guide").remove()},off:function(){t(this.scope).off(".joyride"),t(e).off(".joyride"),t(".joyride-close-tip, .joyride-next-tip, .joyride-modal-bg").off(".joyride"),t(".joyride-tip-guide, .joyride-modal-bg").remove(),clearTimeout(this.settings.automate)},reflow:function(){}}}(jQuery,window,window.document),function(t,e){"use strict";Foundation.libs.equalizer={name:"equalizer",version:"5.5.3",settings:{use_tallest:!0,before_height_change:t.noop,after_height_change:t.noop,equalize_on_stack:!1,act_on_hidden_el:!1},init:function(t,e,i){Foundation.inherit(this,"image_loaded"),this.bindings(e,i),this.reflow()},events:function(){this.S(e).off(".equalizer").on("resize.fndtn.equalizer",function(){this.reflow()}.bind(this))},equalize:function(e){var i,s,n=!1,a=e.data("equalizer"),o=e.data(this.attr_name(!0)+"-init")||this.settings;if(i=e.find(o.act_on_hidden_el?a?"["+this.attr_name()+'-watch="'+a+'"]':"["+this.attr_name()+"-watch]":a?"["+this.attr_name()+'-watch="'+a+'"]:visible':"["+this.attr_name()+"-watch]:visible"),0!==i.length&&(o.before_height_change(),e.trigger("before-height-change.fndth.equalizer"),i.height("inherit"),o.equalize_on_stack!==!1||(s=i.first().offset().top,i.each(function(){return t(this).offset().top!==s?(n=!0,!1):void 0}),!n))){var r=i.map(function(){return t(this).outerHeight(!1)}).get();if(o.use_tallest){var l=Math.max.apply(null,r);i.css("height",l)}else{var d=Math.min.apply(null,r);i.css("height",d)}o.after_height_change(),e.trigger("after-height-change.fndtn.equalizer")}},reflow:function(){var e=this;this.S("["+this.attr_name()+"]",this.scope).each(function(){var i=t(this),s=i.data("equalizer-mq"),n=!0;s&&(s="is_"+s.replace(/-/g,"_"),Foundation.utils.hasOwnProperty(s)&&(n=!1)),e.image_loaded(e.S("img",this),function(){if(n||Foundation.utils[s]())e.equalize(i);else{var t=i.find("["+e.attr_name()+"-watch]:visible");t.css("height","auto")}})})}}}(jQuery,window,window.document),function(t,e,i){"use strict";Foundation.libs.dropdown={name:"dropdown",version:"5.5.3",settings:{active_class:"open",disabled_class:"disabled",mega_class:"mega",align:"bottom",is_hover:!1,hover_timeout:150,opened:function(){},closed:function(){}},init:function(e,i,s){Foundation.inherit(this,"throttle"),t.extend(!0,this.settings,i,s),this.bindings(i,s)},events:function(){var s=this,n=s.S;n(this.scope).off(".dropdown").on("click.fndtn.dropdown","["+this.attr_name()+"]",function(e){var i=n(this).data(s.attr_name(!0)+"-init")||s.settings;(!i.is_hover||Modernizr.touch)&&(e.preventDefault(),n(this).parent("[data-reveal-id]").length&&e.stopPropagation(),s.toggle(t(this)))}).on("mouseenter.fndtn.dropdown","["+this.attr_name()+"], ["+this.attr_name()+"-content]",function(t){var e,i,a=n(this);clearTimeout(s.timeout),a.data(s.data_attr())?(e=n("#"+a.data(s.data_attr())),i=a):(e=a,i=n("["+s.attr_name()+'="'+e.attr("id")+'"]'));var o=i.data(s.attr_name(!0)+"-init")||s.settings;n(t.currentTarget).data(s.data_attr())&&o.is_hover&&s.closeall.call(s),o.is_hover&&s.open.apply(s,[e,i])}).on("mouseleave.fndtn.dropdown","["+this.attr_name()+"], ["+this.attr_name()+"-content]",function(){var t,e=n(this);if(e.data(s.data_attr()))t=e.data(s.data_attr(!0)+"-init")||s.settings;else var i=n("["+s.attr_name()+'="'+n(this).attr("id")+'"]'),t=i.data(s.attr_name(!0)+"-init")||s.settings;s.timeout=setTimeout(function(){e.data(s.data_attr())?t.is_hover&&s.close.call(s,n("#"+e.data(s.data_attr()))):t.is_hover&&s.close.call(s,e)}.bind(this),t.hover_timeout)}).on("click.fndtn.dropdown",function(e){var a=n(e.target).closest("["+s.attr_name()+"-content]"),o=a.find("a");return o.length>0&&"false"!==a.attr("aria-autoclose")&&s.close.call(s,n("["+s.attr_name()+"-content]")),e.target!==i&&!t.contains(i.documentElement,e.target)||n(e.target).closest("["+s.attr_name()+"]").length>0?void 0:!n(e.target).data("revealId")&&a.length>0&&(n(e.target).is("["+s.attr_name()+"-content]")||t.contains(a.first()[0],e.target))?void e.stopPropagation():void s.close.call(s,n("["+s.attr_name()+"-content]"))}).on("opened.fndtn.dropdown","["+s.attr_name()+"-content]",function(){s.settings.opened.call(this)}).on("closed.fndtn.dropdown","["+s.attr_name()+"-content]",function(){s.settings.closed.call(this)}),n(e).off(".dropdown").on("resize.fndtn.dropdown",s.throttle(function(){s.resize.call(s)},50)),this.resize()},close:function(e){var i=this;e.each(function(s){var n=t("["+i.attr_name()+"="+e[s].id+"]")||t("aria-controls="+e[s].id+"]"); 23793 23794n.attr("aria-expanded","false"),i.S(this).hasClass(i.settings.active_class)&&(i.S(this).css(Foundation.rtl?"right":"left","-99999px").attr("aria-hidden","true").removeClass(i.settings.active_class).prev("["+i.attr_name()+"]").removeClass(i.settings.active_class).removeData("target"),i.S(this).trigger("closed.fndtn.dropdown",[e]))}),e.removeClass("f-open-"+this.attr_name(!0))},closeall:function(){var e=this;t.each(e.S(".f-open-"+this.attr_name(!0)),function(){e.close.call(e,e.S(this))})},open:function(t,e){this.css(t.addClass(this.settings.active_class),e),t.prev("["+this.attr_name()+"]").addClass(this.settings.active_class),t.data("target",e.get(0)).trigger("opened.fndtn.dropdown",[t,e]),t.attr("aria-hidden","false"),e.attr("aria-expanded","true"),t.focus(),t.addClass("f-open-"+this.attr_name(!0))},data_attr:function(){return this.namespace.length>0?this.namespace+"-"+this.name:this.name},toggle:function(t){if(!t.hasClass(this.settings.disabled_class)){var e=this.S("#"+t.data(this.data_attr()));0!==e.length&&(this.close.call(this,this.S("["+this.attr_name()+"-content]").not(e)),e.hasClass(this.settings.active_class)?(this.close.call(this,e),e.data("target")!==t.get(0)&&this.open.call(this,e,t)):this.open.call(this,e,t))}},resize:function(){var e=this.S("["+this.attr_name()+"-content].open"),i=t(e.data("target"));e.length&&i.length&&this.css(e,i)},css:function(t,e){var i=Math.max((e.width()-t.width())/2,8),s=e.data(this.attr_name(!0)+"-init")||this.settings,n=t.parent().css("overflow-y")||t.parent().css("overflow");if(this.clear_idx(),this.small()){var a=this.dirs.bottom.call(t,e,s);t.attr("style","").removeClass("drop-left drop-right drop-top").css({position:"absolute",width:"95%","max-width":"none",top:a.top}),t.css(Foundation.rtl?"right":"left",i)}else if("visible"!==n){var o=e[0].offsetTop+e[0].offsetHeight;t.attr("style","").css({position:"absolute",top:o}),t.css(Foundation.rtl?"right":"left",i)}else this.style(t,e,s);return t},style:function(e,i,s){var n=t.extend({position:"absolute"},this.dirs[s.align].call(e,i,s));e.attr("style","").css(n)},dirs:{_base:function(t,s){var n=this.offsetParent(),a=n.offset(),o=t.offset();o.top-=a.top,o.left-=a.left,o.missRight=!1,o.missTop=!1,o.missLeft=!1,o.leftRightFlag=!1;var r,l=e.innerWidth;r=i.getElementsByClassName("row")[0]?i.getElementsByClassName("row")[0].clientWidth:l;var d=(l-r)/2,c=r;if(!this.hasClass("mega")&&!s.ignore_repositioning){var h=this.outerWidth(),u=t.offset().left;t.offset().top<=this.outerHeight()&&(o.missTop=!0,c=l-d,o.leftRightFlag=!0),u+h>u+d&&u-d>h&&(o.missRight=!0,o.missLeft=!1),0>=u-h&&(o.missLeft=!0,o.missRight=!1)}return o},top:function(t,e){var i=Foundation.libs.dropdown,s=i.dirs._base.call(this,t,e);return this.addClass("drop-top"),1==s.missTop&&(s.top=s.top+t.outerHeight()+this.outerHeight(),this.removeClass("drop-top")),1==s.missRight&&(s.left=s.left-this.outerWidth()+t.outerWidth()),(t.outerWidth()<this.outerWidth()||i.small()||this.hasClass(e.mega_menu))&&i.adjust_pip(this,t,e,s),Foundation.rtl?{left:s.left-this.outerWidth()+t.outerWidth(),top:s.top-this.outerHeight()}:{left:s.left,top:s.top-this.outerHeight()}},bottom:function(t,e){var i=Foundation.libs.dropdown,s=i.dirs._base.call(this,t,e);return 1==s.missRight&&(s.left=s.left-this.outerWidth()+t.outerWidth()),(t.outerWidth()<this.outerWidth()||i.small()||this.hasClass(e.mega_menu))&&i.adjust_pip(this,t,e,s),i.rtl?{left:s.left-this.outerWidth()+t.outerWidth(),top:s.top+t.outerHeight()}:{left:s.left,top:s.top+t.outerHeight()}},left:function(t,e){var i=Foundation.libs.dropdown.dirs._base.call(this,t,e);return this.addClass("drop-left"),1==i.missLeft&&(i.left=i.left+this.outerWidth(),i.top=i.top+t.outerHeight(),this.removeClass("drop-left")),{left:i.left-this.outerWidth(),top:i.top}},right:function(t,e){var i=Foundation.libs.dropdown.dirs._base.call(this,t,e);this.addClass("drop-right"),1==i.missRight?(i.left=i.left-this.outerWidth(),i.top=i.top+t.outerHeight(),this.removeClass("drop-right")):i.triggeredRight=!0;var s=Foundation.libs.dropdown;return(t.outerWidth()<this.outerWidth()||s.small()||this.hasClass(e.mega_menu))&&s.adjust_pip(this,t,e,i),{left:i.left+t.outerWidth(),top:i.top}}},adjust_pip:function(t,e,i,s){var n=Foundation.stylesheet,a=8;t.hasClass(i.mega_class)?a=s.left+e.outerWidth()/2-8:this.small()&&(a+=s.left-8),this.rule_idx=n.cssRules.length;var o=".f-dropdown.open:before",r=".f-dropdown.open:after",l="left: "+a+"px;",d="left: "+(a-1)+"px;";1==s.missRight&&(a=t.outerWidth()-23,o=".f-dropdown.open:before",r=".f-dropdown.open:after",l="left: "+a+"px;",d="left: "+(a-1)+"px;"),1==s.triggeredRight&&(o=".f-dropdown.open:before",r=".f-dropdown.open:after",l="left:-12px;",d="left:-14px;"),n.insertRule?(n.insertRule([o,"{",l,"}"].join(" "),this.rule_idx),n.insertRule([r,"{",d,"}"].join(" "),this.rule_idx+1)):(n.addRule(o,l,this.rule_idx),n.addRule(r,d,this.rule_idx+1))},clear_idx:function(){var t=Foundation.stylesheet;"undefined"!=typeof this.rule_idx&&(t.deleteRule(this.rule_idx),t.deleteRule(this.rule_idx),delete this.rule_idx)},small:function(){return matchMedia(Foundation.media_queries.small).matches&&!matchMedia(Foundation.media_queries.medium).matches},off:function(){this.S(this.scope).off(".fndtn.dropdown"),this.S("html, body").off(".fndtn.dropdown"),this.S(e).off(".fndtn.dropdown"),this.S("[data-dropdown-content]").off(".fndtn.dropdown")},reflow:function(){}}}(jQuery,window,window.document),function(t,e,i,s){"use strict";Foundation.libs.clearing={name:"clearing",version:"5.5.3",settings:{templates:{viewing:'<a href="#" class="clearing-close">×</a><div class="visible-img" style="display: none"><div class="clearing-touch-label"></div><img src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" alt="" /><p class="clearing-caption"></p><a href="#" class="clearing-main-prev"><span></span></a><a href="#" class="clearing-main-next"><span></span></a></div><img class="clearing-preload-next" style="display: none" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" alt="" /><img class="clearing-preload-prev" style="display: none" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" alt="" />'},close_selectors:".clearing-close, div.clearing-blackout",open_selectors:"",skip_selector:"",touch_label:"",init:!1,locked:!1},init:function(t,e,i){var s=this;Foundation.inherit(this,"throttle image_loaded"),this.bindings(e,i),s.S(this.scope).is("["+this.attr_name()+"]")?this.assemble(s.S("li",this.scope)):s.S("["+this.attr_name()+"]",this.scope).each(function(){s.assemble(s.S("li",this))})},events:function(s){var n=this,a=n.S,o=t(".scroll-container");o.length>0&&(this.scope=o),a(this.scope).off(".clearing").on("click.fndtn.clearing","ul["+this.attr_name()+"] li "+this.settings.open_selectors,function(t,e,i){var e=e||a(this),i=i||e,s=e.next("li"),o=e.closest("["+n.attr_name()+"]").data(n.attr_name(!0)+"-init"),r=a(t.target);t.preventDefault(),o||(n.init(),o=e.closest("["+n.attr_name()+"]").data(n.attr_name(!0)+"-init")),i.hasClass("visible")&&e[0]===i[0]&&s.length>0&&n.is_open(e)&&(i=s,r=a("img",i)),n.open(r,e,i),n.update_paddles(i)}).on("click.fndtn.clearing",".clearing-main-next",function(t){n.nav(t,"next")}).on("click.fndtn.clearing",".clearing-main-prev",function(t){n.nav(t,"prev")}).on("click.fndtn.clearing",this.settings.close_selectors,function(t){Foundation.libs.clearing.close(t,this)}),t(i).on("keydown.fndtn.clearing",function(t){n.keydown(t)}),a(e).off(".clearing").on("resize.fndtn.clearing",function(){n.resize()}),this.swipe_events(s)},swipe_events:function(){var t=this,e=t.S;e(this.scope).on("touchstart.fndtn.clearing",".visible-img",function(t){t.touches||(t=t.originalEvent);var i={start_page_x:t.touches[0].pageX,start_page_y:t.touches[0].pageY,start_time:(new Date).getTime(),delta_x:0,is_scrolling:s};e(this).data("swipe-transition",i),t.stopPropagation()}).on("touchmove.fndtn.clearing",".visible-img",function(i){if(i.touches||(i=i.originalEvent),!(i.touches.length>1||i.scale&&1!==i.scale)){var s=e(this).data("swipe-transition");if("undefined"==typeof s&&(s={}),s.delta_x=i.touches[0].pageX-s.start_page_x,Foundation.rtl&&(s.delta_x=-s.delta_x),"undefined"==typeof s.is_scrolling&&(s.is_scrolling=!!(s.is_scrolling||Math.abs(s.delta_x)<Math.abs(i.touches[0].pageY-s.start_page_y))),!s.is_scrolling&&!s.active){i.preventDefault();var n=s.delta_x<0?"next":"prev";s.active=!0,t.nav(i,n)}}}).on("touchend.fndtn.clearing",".visible-img",function(t){e(this).data("swipe-transition",{}),t.stopPropagation()})},assemble:function(e){var i=e.parent();if(!i.parent().hasClass("carousel")){i.after('<div id="foundationClearingHolder"></div>');var s=i.detach(),n="";if(null!=s[0]){n=s[0].outerHTML;var a=this.S("#foundationClearingHolder"),o=i.data(this.attr_name(!0)+"-init"),r={grid:'<div class="carousel">'+n+"</div>",viewing:o.templates.viewing},l='<div class="clearing-assembled"><div>'+r.viewing+r.grid+"</div></div>",d=this.settings.touch_label;Modernizr.touch&&(l=t(l).find(".clearing-touch-label").html(d).end()),a.after(l).remove()}}},open:function(e,s,n){function a(){setTimeout(function(){this.image_loaded(u,function(){1!==u.outerWidth()||p?o.call(this,u):a.call(this)}.bind(this))}.bind(this),100)}function o(e){var i=t(e);i.css("visibility","visible"),i.trigger("imageVisible"),l.css("overflow","hidden"),d.addClass("clearing-blackout"),c.addClass("clearing-container"),h.show(),this.fix_height(n).caption(r.S(".clearing-caption",h),r.S("img",n)).center_and_label(e,f).shift(s,n,function(){n.closest("li").siblings().removeClass("visible"),n.closest("li").addClass("visible")}),h.trigger("opened.fndtn.clearing")}var r=this,l=t(i.body),d=n.closest(".clearing-assembled"),c=r.S("div",d).first(),h=r.S(".visible-img",c),u=r.S("img",h).not(e),f=r.S(".clearing-touch-label",c),p=!1,g={};t("body").on("touchmove",function(t){t.preventDefault()}),u.error(function(){p=!0}),this.locked()||(h.trigger("open.fndtn.clearing"),g=this.load(e),g.interchange?u.attr("data-interchange",g.interchange).foundation("interchange","reflow"):u.attr("src",g.src).attr("data-interchange",""),u.css("visibility","hidden"),a.call(this))},close:function(e,s){e.preventDefault();var n,a,o=function(t){return/blackout/.test(t.selector)?t:t.closest(".clearing-blackout")}(t(s)),r=t(i.body);return s===e.target&&o&&(r.css("overflow",""),n=t("div",o).first(),a=t(".visible-img",n),a.trigger("close.fndtn.clearing"),this.settings.prev_index=0,t("ul["+this.attr_name()+"]",o).attr("style","").closest(".clearing-blackout").removeClass("clearing-blackout"),n.removeClass("clearing-container"),a.hide(),a.trigger("closed.fndtn.clearing")),t("body").off("touchmove"),!1},is_open:function(t){return t.parent().prop("style").length>0},keydown:function(e){var i=t(".clearing-blackout ul["+this.attr_name()+"]"),s=this.rtl?37:39,n=this.rtl?39:37,a=27;e.which===s&&this.go(i,"next"),e.which===n&&this.go(i,"prev"),e.which===a&&this.S("a.clearing-close").trigger("click.fndtn.clearing")},nav:function(e,i){var s=t("ul["+this.attr_name()+"]",".clearing-blackout");e.preventDefault(),this.go(s,i)},resize:function(){var e=t("img",".clearing-blackout .visible-img"),i=t(".clearing-touch-label",".clearing-blackout");e.length&&(this.center_and_label(e,i),e.trigger("resized.fndtn.clearing"))},fix_height:function(t){var e=t.parent().children(),i=this;return e.each(function(){var t=i.S(this),e=t.find("img");t.height()>e.outerHeight()&&t.addClass("fix-height")}).closest("ul").width(100*e.length+"%"),this},update_paddles:function(t){t=t.closest("li");var e=t.closest(".carousel").siblings(".visible-img");t.next().length>0?this.S(".clearing-main-next",e).removeClass("disabled"):this.S(".clearing-main-next",e).addClass("disabled"),t.prev().length>0?this.S(".clearing-main-prev",e).removeClass("disabled"):this.S(".clearing-main-prev",e).addClass("disabled")},center_and_label:function(t,e){return e.css(!this.rtl&&e.length>0?{marginLeft:-(e.outerWidth()/2),marginTop:-(t.outerHeight()/2)-e.outerHeight()-10}:{marginRight:-(e.outerWidth()/2),marginTop:-(t.outerHeight()/2)-e.outerHeight()-10,left:"auto",right:"50%"}),this},load:function(t){var e,i,s;return"A"===t[0].nodeName?(e=t.attr("href"),i=t.data("clearing-interchange")):(s=t.closest("a"),e=s.attr("href"),i=s.data("clearing-interchange")),this.preload(t),{src:e?e:t.attr("src"),interchange:e?i:t.data("clearing-interchange")}},preload:function(t){this.img(t.closest("li").next(),"next").img(t.closest("li").prev(),"prev")},img:function(e,i){if(e.length){var s,n,a,o=t(".clearing-preload-"+i),r=this.S("a",e);r.length?(s=r.attr("href"),n=r.data("clearing-interchange")):(a=this.S("img",e),s=a.attr("src"),n=a.data("clearing-interchange")),n?o.attr("data-interchange",n):(o.attr("src",s),o.attr("data-interchange",""))}return this},caption:function(t,e){var i=e.attr("data-caption");if(i){var s=t.get(0);s.innerHTML=i,t.show()}else t.text("").hide();return this},go:function(t,e){var i=this.S(".visible",t),s=i[e]();this.settings.skip_selector&&0!=s.find(this.settings.skip_selector).length&&(s=s[e]()),s.length&&this.S("img",s).trigger("click.fndtn.clearing",[i,s]).trigger("change.fndtn.clearing")},shift:function(t,e,i){var s,n=e.parent(),a=this.settings.prev_index||e.index(),o=this.direction(n,t,e),r=this.rtl?"right":"left",l=parseInt(n.css("left"),10),d=e.outerWidth(),c={};e.index()===a||/skip/.test(o)?/skip/.test(o)&&(s=e.index()-this.settings.up_count,this.lock(),s>0?(c[r]=-(s*d),n.animate(c,300,this.unlock())):(c[r]=0,n.animate(c,300,this.unlock()))):/left/.test(o)?(this.lock(),c[r]=l+d,n.animate(c,300,this.unlock())):/right/.test(o)&&(this.lock(),c[r]=l-d,n.animate(c,300,this.unlock())),i()},direction:function(t,e,i){var s,n=this.S("li",t),a=n.outerWidth()+n.outerWidth()/4,o=Math.floor(this.S(".clearing-container").outerWidth()/a)-1,r=n.index(i);return this.settings.up_count=o,s=this.adjacent(this.settings.prev_index,r)?r>o&&r>this.settings.prev_index?"right":r>o-1&&r<=this.settings.prev_index?"left":!1:"skip",this.settings.prev_index=r,s},adjacent:function(t,e){for(var i=e+1;i>=e-1;i--)if(i===t)return!0;return!1},lock:function(){this.settings.locked=!0},unlock:function(){this.settings.locked=!1},locked:function(){return this.settings.locked},off:function(){this.S(this.scope).off(".fndtn.clearing"),this.S(e).off(".fndtn.clearing")},reflow:function(){this.init()}}}(jQuery,window,window.document),function(t,e,i,s){"use strict";var n=function(){},a=function(n,a){if(n.hasClass(a.slides_container_class))return this;var d,c,h,u,f,p,g=this,_=n,m=0,v=!1;g.slides=function(){return _.children(a.slide_selector)},g.slides().first().addClass(a.active_slide_class),g.update_slide_number=function(e){a.slide_number&&(c.find("span:first").text(parseInt(e)+1),c.find("span:last").text(g.slides().length)),a.bullets&&(h.children().removeClass(a.bullets_active_class),t(h.children().get(e)).addClass(a.bullets_active_class))},g.update_active_link=function(e){var i=t('[data-orbit-link="'+g.slides().eq(e).attr("data-orbit-slide")+'"]');i.siblings().removeClass(a.bullets_active_class),i.addClass(a.bullets_active_class)},g.build_markup=function(){_.wrap('<div class="'+a.container_class+'"></div>'),d=_.parent(),_.addClass(a.slides_container_class),a.stack_on_small&&d.addClass(a.stack_on_small_class),a.navigation_arrows&&(d.append(t('<a href="#"><span></span></a>').addClass(a.prev_class)),d.append(t('<a href="#"><span></span></a>').addClass(a.next_class))),a.timer&&(u=t("<div>").addClass(a.timer_container_class),u.append("<span>"),u.append(t("<div>").addClass(a.timer_progress_class)),u.addClass(a.timer_paused_class),d.append(u)),a.slide_number&&(c=t("<div>").addClass(a.slide_number_class),c.append("<span></span> "+a.slide_number_text+" <span></span>"),d.append(c)),a.bullets&&(h=t("<ol>").addClass(a.bullets_container_class),d.append(h),h.wrap('<div class="orbit-bullets-container"></div>'),g.slides().each(function(e){var i=t("<li>").attr("data-orbit-slide",e).on("click",g.link_bullet);h.append(i)}))},g._goto=function(e,i){if(e===m)return!1;"object"==typeof p&&p.restart();var s=g.slides(),n="next";if(v=!0,m>e&&(n="prev"),e>=s.length){if(!a.circular)return!1;e=0}else if(0>e){if(!a.circular)return!1;e=s.length-1}var o=t(s.get(m)),r=t(s.get(e));o.css("zIndex",2),o.removeClass(a.active_slide_class),r.css("zIndex",4).addClass(a.active_slide_class),_.trigger("before-slide-change.fndtn.orbit"),a.before_slide_change(),g.update_active_link(e);var l=function(){var t=function(){m=e,v=!1,i===!0&&(p=g.create_timer(),p.start()),g.update_slide_number(m),_.trigger("after-slide-change.fndtn.orbit",[{slide_number:m,total_slides:s.length}]),a.after_slide_change(m,s.length)};_.outerHeight()!=r.outerHeight()&&a.variable_height?_.animate({height:r.outerHeight()},250,"linear",t):t()};if(1===s.length)return l(),!1;var d=function(){"next"===n&&f.next(o,r,l),"prev"===n&&f.prev(o,r,l)};r.outerHeight()>_.outerHeight()&&a.variable_height?_.animate({height:r.outerHeight()},250,"linear",d):d()},g.next=function(t){t.stopImmediatePropagation(),t.preventDefault(),g._goto(m+1)},g.prev=function(t){t.stopImmediatePropagation(),t.preventDefault(),g._goto(m-1)},g.link_custom=function(e){e.preventDefault();var i=t(this).attr("data-orbit-link");if("string"==typeof i&&""!=(i=t.trim(i))){var s=d.find("[data-orbit-slide="+i+"]");-1!=s.index()&&g._goto(s.index())}},g.link_bullet=function(){var e=t(this).attr("data-orbit-slide");if("string"==typeof e&&""!=(e=t.trim(e)))if(isNaN(parseInt(e))){var i=d.find("[data-orbit-slide="+e+"]");-1!=i.index()&&g._goto(i.index()+1)}else g._goto(parseInt(e))},g.timer_callback=function(){g._goto(m+1,!0)},g.compute_dimensions=function(){var e=t(g.slides().get(m)),i=e.outerHeight();a.variable_height||g.slides().each(function(){t(this).outerHeight()>i&&(i=t(this).outerHeight())}),_.height(i)},g.create_timer=function(){var t=new o(d.find("."+a.timer_container_class),a,g.timer_callback);return t},g.stop_timer=function(){"object"==typeof p&&p.stop()},g.toggle_timer=function(){var t=d.find("."+a.timer_container_class);t.hasClass(a.timer_paused_class)?("undefined"==typeof p&&(p=g.create_timer()),p.start()):"object"==typeof p&&p.stop()},g.init=function(){g.build_markup(),a.timer&&(p=g.create_timer(),Foundation.utils.image_loaded(this.slides().children("img"),p.start)),f=new l(a,_),"slide"===a.animation&&(f=new r(a,_)),d.on("click","."+a.next_class,g.next),d.on("click","."+a.prev_class,g.prev),a.next_on_click&&d.on("click","."+a.slides_container_class+" [data-orbit-slide]",g.link_bullet),d.on("click",g.toggle_timer),a.swipe&&d.on("touchstart.fndtn.orbit",function(t){t.touches||(t=t.originalEvent);var e={start_page_x:t.touches[0].pageX,start_page_y:t.touches[0].pageY,start_time:(new Date).getTime(),delta_x:0,is_scrolling:s};d.data("swipe-transition",e),t.stopPropagation()}).on("touchmove.fndtn.orbit",function(t){if(t.touches||(t=t.originalEvent),!(t.touches.length>1||t.scale&&1!==t.scale)){var e=d.data("swipe-transition");if("undefined"==typeof e&&(e={}),e.delta_x=t.touches[0].pageX-e.start_page_x,"undefined"==typeof e.is_scrolling&&(e.is_scrolling=!!(e.is_scrolling||Math.abs(e.delta_x)<Math.abs(t.touches[0].pageY-e.start_page_y))),!e.is_scrolling&&!e.active){t.preventDefault();var i=e.delta_x<0?m+1:m-1;e.active=!0,g._goto(i)}}}).on("touchend.fndtn.orbit",function(t){d.data("swipe-transition",{}),t.stopPropagation()}),d.on("mouseenter.fndtn.orbit",function(){a.timer&&a.pause_on_hover&&g.stop_timer()}).on("mouseleave.fndtn.orbit",function(){a.timer&&a.resume_on_mouseout&&p.start()}),t(i).on("click","[data-orbit-link]",g.link_custom),t(e).on("load resize",g.compute_dimensions),Foundation.utils.image_loaded(this.slides().children("img"),g.compute_dimensions),Foundation.utils.image_loaded(this.slides().children("img"),function(){d.prev("."+a.preloader_class).css("display","none"),g.update_slide_number(0),g.update_active_link(0),_.trigger("ready.fndtn.orbit")})},g.init()},o=function(t,e,i){var s,n,a=this,o=e.timer_speed,r=t.find("."+e.timer_progress_class),l=-1;this.update_progress=function(t){var e=r.clone();e.attr("style",""),e.css("width",t+"%"),r.replaceWith(e),r=e},this.restart=function(){clearTimeout(n),t.addClass(e.timer_paused_class),l=-1,a.update_progress(0)},this.start=function(){return t.hasClass(e.timer_paused_class)?(l=-1===l?o:l,t.removeClass(e.timer_paused_class),s=(new Date).getTime(),r.animate({width:"100%"},l,"linear"),n=setTimeout(function(){a.restart(),i()},l),void t.trigger("timer-started.fndtn.orbit")):!0},this.stop=function(){if(t.hasClass(e.timer_paused_class))return!0;clearTimeout(n),t.addClass(e.timer_paused_class);var i=(new Date).getTime();l-=i-s;var r=100-l/o*100;a.update_progress(r),t.trigger("timer-stopped.fndtn.orbit")}},r=function(e){var i=e.animation_speed,s=1===t("html[dir=rtl]").length,n=s?"marginRight":"marginLeft",a={};a[n]="0%",this.next=function(t,e,s){t.animate({marginLeft:"-100%"},i),e.animate(a,i,function(){t.css(n,"100%"),s()})},this.prev=function(t,e,s){t.animate({marginLeft:"100%"},i),e.css(n,"-100%"),e.animate(a,i,function(){t.css(n,"100%"),s()})}},l=function(e){{var i=e.animation_speed;1===t("html[dir=rtl]").length}this.next=function(t,e,s){e.css({margin:"0%",opacity:"0.01"}),e.animate({opacity:"1"},i,"linear",function(){t.css("margin","100%"),s()})},this.prev=function(t,e,s){e.css({margin:"0%",opacity:"0.01"}),e.animate({opacity:"1"},i,"linear",function(){t.css("margin","100%"),s()})}};Foundation.libs=Foundation.libs||{},Foundation.libs.orbit={name:"orbit",version:"5.5.3",settings:{animation:"slide",timer_speed:1e4,pause_on_hover:!0,resume_on_mouseout:!1,next_on_click:!0,animation_speed:500,stack_on_small:!1,navigation_arrows:!0,slide_number:!0,slide_number_text:"of",container_class:"orbit-container",stack_on_small_class:"orbit-stack-on-small",next_class:"orbit-next",prev_class:"orbit-prev",timer_container_class:"orbit-timer",timer_paused_class:"paused",timer_progress_class:"orbit-progress",slides_container_class:"orbit-slides-container",preloader_class:"preloader",slide_selector:"*",bullets_container_class:"orbit-bullets",bullets_active_class:"active",slide_number_class:"orbit-slide-number",caption_class:"orbit-caption",active_slide_class:"active",orbit_transition_class:"orbit-transitioning",bullets:!0,circular:!0,timer:!0,variable_height:!1,swipe:!0,before_slide_change:n,after_slide_change:n},init:function(t,e,i){this.bindings(e,i)},events:function(t){var e=new a(this.S(t),this.S(t).data("orbit-init"));this.S(t).data(this.name+"-instance",e)},reflow:function(){var t=this;if(t.S(t.scope).is("[data-orbit]")){var e=t.S(t.scope),i=e.data(t.name+"-instance");i.compute_dimensions()}else t.S("[data-orbit]",t.scope).each(function(e,i){var s=t.S(i),n=(t.data_options(s),s.data(t.name+"-instance"));n.compute_dimensions()})}}}(jQuery,window,window.document),function(t){"use strict";Foundation.libs.offcanvas={name:"offcanvas",version:"5.5.3",settings:{open_method:"move",close_on_click:!1},init:function(t,e,i){this.bindings(e,i)},events:function(){var e=this,i=e.S,s="",n="",a="",o="",r="";"move"===this.settings.open_method?(s="move-",n="right",a="left",o="top",r="bottom"):"overlap_single"===this.settings.open_method?(s="offcanvas-overlap-",n="right",a="left",o="top",r="bottom"):"overlap"===this.settings.open_method&&(s="offcanvas-overlap"),i(this.scope).off(".offcanvas").on("click.fndtn.offcanvas",".left-off-canvas-toggle",function(a){e.click_toggle_class(a,s+n),"overlap"!==e.settings.open_method&&i(".left-submenu").removeClass(s+n),t(".left-off-canvas-toggle").attr("aria-expanded","true")}).on("click.fndtn.offcanvas",".left-off-canvas-menu a",function(a){var o=e.get_settings(a),r=i(this).parent();!o.close_on_click||r.hasClass("has-submenu")||r.hasClass("back")?i(this).parent().hasClass("has-submenu")?(a.preventDefault(),i(this).siblings(".left-submenu").toggleClass(s+n)):r.hasClass("back")&&(a.preventDefault(),r.parent().removeClass(s+n)):(e.hide.call(e,s+n,e.get_wrapper(a)),r.parent().removeClass(s+n)),t(".left-off-canvas-toggle").attr("aria-expanded","true")}).on("click.fndtn.offcanvas",".right-off-canvas-toggle",function(n){e.click_toggle_class(n,s+a),"overlap"!==e.settings.open_method&&i(".right-submenu").removeClass(s+a),t(".right-off-canvas-toggle").attr("aria-expanded","true")}).on("click.fndtn.offcanvas",".right-off-canvas-menu a",function(n){var o=e.get_settings(n),r=i(this).parent();!o.close_on_click||r.hasClass("has-submenu")||r.hasClass("back")?i(this).parent().hasClass("has-submenu")?(n.preventDefault(),i(this).siblings(".right-submenu").toggleClass(s+a)):r.hasClass("back")&&(n.preventDefault(),r.parent().removeClass(s+a)):(e.hide.call(e,s+a,e.get_wrapper(n)),r.parent().removeClass(s+a)),t(".right-off-canvas-toggle").attr("aria-expanded","true")}).on("click.fndtn.offcanvas",".top-off-canvas-toggle",function(n){e.click_toggle_class(n,s+r),"overlap"!==e.settings.open_method&&i(".top-submenu").removeClass(s+r),t(".top-off-canvas-toggle").attr("aria-expanded","true")}).on("click.fndtn.offcanvas",".top-off-canvas-menu a",function(n){var a=e.get_settings(n),o=i(this).parent();!a.close_on_click||o.hasClass("has-submenu")||o.hasClass("back")?i(this).parent().hasClass("has-submenu")?(n.preventDefault(),i(this).siblings(".top-submenu").toggleClass(s+r)):o.hasClass("back")&&(n.preventDefault(),o.parent().removeClass(s+r)):(e.hide.call(e,s+r,e.get_wrapper(n)),o.parent().removeClass(s+r)),t(".top-off-canvas-toggle").attr("aria-expanded","true")}).on("click.fndtn.offcanvas",".bottom-off-canvas-toggle",function(n){e.click_toggle_class(n,s+o),"overlap"!==e.settings.open_method&&i(".bottom-submenu").removeClass(s+o),t(".bottom-off-canvas-toggle").attr("aria-expanded","true")}).on("click.fndtn.offcanvas",".bottom-off-canvas-menu a",function(n){var a=e.get_settings(n),r=i(this).parent();!a.close_on_click||r.hasClass("has-submenu")||r.hasClass("back")?i(this).parent().hasClass("has-submenu")?(n.preventDefault(),i(this).siblings(".bottom-submenu").toggleClass(s+o)):r.hasClass("back")&&(n.preventDefault(),r.parent().removeClass(s+o)):(e.hide.call(e,s+o,e.get_wrapper(n)),r.parent().removeClass(s+o)),t(".bottom-off-canvas-toggle").attr("aria-expanded","true")}).on("click.fndtn.offcanvas",".exit-off-canvas",function(o){e.click_remove_class(o,s+a),i(".right-submenu").removeClass(s+a),n&&(e.click_remove_class(o,s+n),i(".left-submenu").removeClass(s+a)),t(".right-off-canvas-toggle").attr("aria-expanded","true")}).on("click.fndtn.offcanvas",".exit-off-canvas",function(i){e.click_remove_class(i,s+a),t(".left-off-canvas-toggle").attr("aria-expanded","false"),n&&(e.click_remove_class(i,s+n),t(".right-off-canvas-toggle").attr("aria-expanded","false"))}).on("click.fndtn.offcanvas",".exit-off-canvas",function(n){e.click_remove_class(n,s+o),i(".bottom-submenu").removeClass(s+o),r&&(e.click_remove_class(n,s+r),i(".top-submenu").removeClass(s+o)),t(".bottom-off-canvas-toggle").attr("aria-expanded","true")}).on("click.fndtn.offcanvas",".exit-off-canvas",function(i){e.click_remove_class(i,s+o),t(".top-off-canvas-toggle").attr("aria-expanded","false"),r&&(e.click_remove_class(i,s+r),t(".bottom-off-canvas-toggle").attr("aria-expanded","false"))})},toggle:function(t,e){e=e||this.get_wrapper(),e.is("."+t)?this.hide(t,e):this.show(t,e)},show:function(t,e){e=e||this.get_wrapper(),e.trigger("open.fndtn.offcanvas"),e.addClass(t)},hide:function(t,e){e=e||this.get_wrapper(),e.trigger("close.fndtn.offcanvas"),e.removeClass(t)},click_toggle_class:function(t,e){t.preventDefault();var i=this.get_wrapper(t);this.toggle(e,i)},click_remove_class:function(t,e){t.preventDefault();var i=this.get_wrapper(t);this.hide(e,i)},get_settings:function(t){var e=this.S(t.target).closest("["+this.attr_name()+"]");return e.data(this.attr_name(!0)+"-init")||this.settings},get_wrapper:function(t){var e=this.S(t?t.target:this.scope).closest(".off-canvas-wrap");return 0===e.length&&(e=this.S(".off-canvas-wrap")),e},reflow:function(){}}}(jQuery,window,window.document),function(t){"use strict";Foundation.libs.alert={name:"alert",version:"5.5.3",settings:{callback:function(){}},init:function(t,e,i){this.bindings(e,i)},events:function(){var e=this,i=this.S;t(this.scope).off(".alert").on("click.fndtn.alert","["+this.attr_name()+"] .close",function(t){var s=i(this).closest("["+e.attr_name()+"]"),n=s.data(e.attr_name(!0)+"-init")||e.settings;t.preventDefault(),Modernizr.csstransitions?(s.addClass("alert-close"),s.on("transitionend webkitTransitionEnd oTransitionEnd",function(){i(this).trigger("close.fndtn.alert").remove(),n.callback()})):s.fadeOut(300,function(){i(this).trigger("close.fndtn.alert").remove(),n.callback()})})},reflow:function(){}}}(jQuery,window,window.document),function(t,e,i,s){"use strict";function n(t){var e=/fade/i.test(t),i=/pop/i.test(t);return{animate:e||i,pop:i,fade:e}}var a=[];Foundation.libs.reveal={name:"reveal",version:"5.5.3",locked:!1,settings:{animation:"fadeAndPop",animation_speed:250,close_on_background_click:!0,close_on_esc:!0,dismiss_modal_class:"close-reveal-modal",multiple_opened:!1,bg_class:"reveal-modal-bg",root_element:"body",open:function(){},opened:function(){},close:function(){},closed:function(){},on_ajax_error:t.noop,bg:t(".reveal-modal-bg"),css:{open:{opacity:0,visibility:"visible",display:"block"},close:{opacity:1,visibility:"hidden",display:"none"}}},init:function(e,i,s){t.extend(!0,this.settings,i,s),this.bindings(i,s)},events:function(){var t=this,e=t.S;return e(this.scope).off(".reveal").on("click.fndtn.reveal","["+this.add_namespace("data-reveal-id")+"]:not([disabled])",function(i){if(i.preventDefault(),!t.locked){var s=e(this),n=s.data(t.data_attr("reveal-ajax")),a=s.data(t.data_attr("reveal-replace-content"));if(t.locked=!0,"undefined"==typeof n)t.open.call(t,s);else{var o=n===!0?s.attr("href"):n;t.open.call(t,s,{url:o},{replaceContentSel:a})}}}),e(i).on("click.fndtn.reveal",this.close_targets(),function(i){if(i.preventDefault(),!t.locked){var s=e("["+t.attr_name()+"].open").data(t.attr_name(!0)+"-init")||t.settings,n=e(i.target)[0]===e("."+s.bg_class)[0];if(n){if(!s.close_on_background_click)return;i.stopPropagation()}t.locked=!0,t.close.call(t,n?e("["+t.attr_name()+"].open:not(.toback)"):e(this).closest("["+t.attr_name()+"]"))}}),e("["+t.attr_name()+"]",this.scope).length>0?e(this.scope).on("open.fndtn.reveal",this.settings.open).on("opened.fndtn.reveal",this.settings.opened).on("opened.fndtn.reveal",this.open_video).on("close.fndtn.reveal",this.settings.close).on("closed.fndtn.reveal",this.settings.closed).on("closed.fndtn.reveal",this.close_video):e(this.scope).on("open.fndtn.reveal","["+t.attr_name()+"]",this.settings.open).on("opened.fndtn.reveal","["+t.attr_name()+"]",this.settings.opened).on("opened.fndtn.reveal","["+t.attr_name()+"]",this.open_video).on("close.fndtn.reveal","["+t.attr_name()+"]",this.settings.close).on("closed.fndtn.reveal","["+t.attr_name()+"]",this.settings.closed).on("closed.fndtn.reveal","["+t.attr_name()+"]",this.close_video),!0},key_up_on:function(){var t=this;return t.S("body").off("keyup.fndtn.reveal").on("keyup.fndtn.reveal",function(e){var i=t.S("["+t.attr_name()+"].open"),s=i.data(t.attr_name(!0)+"-init")||t.settings;s&&27===e.which&&s.close_on_esc&&!t.locked&&t.close.call(t,i)}),!0},key_up_off:function(){return this.S("body").off("keyup.fndtn.reveal"),!0},open:function(i,n){var o,r=this;i?"undefined"!=typeof i.selector?o=r.S("#"+i.data(r.data_attr("reveal-id"))).first():(o=r.S(this.scope),n=i):o=r.S(this.scope);var l=o.data(r.attr_name(!0)+"-init");if(l=l||this.settings,o.hasClass("open")&&i!==s&&i.attr("data-reveal-id")==o.attr("id"))return r.close(o);if(!o.hasClass("open")){var d=r.S("["+r.attr_name()+"].open");"undefined"==typeof o.data("css-top")&&o.data("css-top",parseInt(o.css("top"),10)).data("offset",this.cache_offset(o)),o.attr("tabindex","0").attr("aria-hidden","false"),this.key_up_on(o),o.on("open.fndtn.reveal",function(t){"fndtn.reveal"!==t.namespace}),o.on("open.fndtn.reveal").trigger("open.fndtn.reveal"),d.length<1&&this.toggle_bg(o,!0),"string"==typeof n&&(n={url:n});var c=function(){d.length>0&&(l.multiple_opened?r.to_back(d):r.hide(d,l.css.close)),l.multiple_opened&&a.push(o),r.show(o,l.css.open)};if("undefined"!=typeof n&&n.url){var h="undefined"!=typeof n.success?n.success:null;t.extend(n,{success:function(e,i,s){if(t.isFunction(h)){var n=h(e,i,s);"string"==typeof n&&(e=n)}"undefined"!=typeof options&&"undefined"!=typeof options.replaceContentSel?o.find(options.replaceContentSel).html(e):o.html(e),r.S(o).foundation("section","reflow"),r.S(o).children().foundation(),c()}}),l.on_ajax_error!==t.noop&&t.extend(n,{error:l.on_ajax_error}),t.ajax(n)}else c()}r.S(e).trigger("resize")},close:function(e){var e=e&&e.length?e:this.S(this.scope),i=this.S("["+this.attr_name()+"].open"),s=e.data(this.attr_name(!0)+"-init")||this.settings,n=this; 23795 23796if(i.length>0)if(e.removeAttr("tabindex","0").attr("aria-hidden","true"),this.locked=!0,this.key_up_off(e),e.trigger("close.fndtn.reveal"),(s.multiple_opened&&1===i.length||!s.multiple_opened||e.length>1)&&(n.toggle_bg(e,!1),n.to_front(e)),s.multiple_opened){var o=e.is(":not(.toback)");n.hide(e,s.css.close,s),o?a.pop():a=t.grep(a,function(t){var i=t[0]===e[0];return i&&n.to_front(e),!i}),a.length>0&&n.to_front(a[a.length-1])}else n.hide(i,s.css.close,s)},close_targets:function(){var t="."+this.settings.dismiss_modal_class;return this.settings.close_on_background_click?t+", ."+this.settings.bg_class:t},toggle_bg:function(e,i){0===this.S("."+this.settings.bg_class).length&&(this.settings.bg=t("<div />",{"class":this.settings.bg_class}).appendTo("body").hide());var n=this.settings.bg.filter(":visible").length>0;i!=n&&((i==s?n:!i)?this.hide(this.settings.bg):this.show(this.settings.bg))},show:function(i,s){if(s){var a=i.data(this.attr_name(!0)+"-init")||this.settings,o=a.root_element,r=this;if(0===i.parent(o).length){var l=i.wrap('<div style="display: none;" />').parent();i.on("closed.fndtn.reveal.wrapped",function(){i.detach().appendTo(l),i.unwrap().unbind("closed.fndtn.reveal.wrapped")}),i.detach().appendTo(o)}var d=n(a.animation);if(d.animate||(this.locked=!1),d.pop){s.top=t(e).scrollTop()-i.data("offset")+"px";var c={top:t(e).scrollTop()+i.data("css-top")+"px",opacity:1};return setTimeout(function(){return i.css(s).animate(c,a.animation_speed,"linear",function(){r.locked=!1,i.trigger("opened.fndtn.reveal")}).addClass("open")},a.animation_speed/2)}if(s.top=t(e).scrollTop()+i.data("css-top")+"px",d.fade){var c={opacity:1};return setTimeout(function(){return i.css(s).animate(c,a.animation_speed,"linear",function(){r.locked=!1,i.trigger("opened.fndtn.reveal")}).addClass("open")},a.animation_speed/2)}return i.css(s).show().css({opacity:1}).addClass("open").trigger("opened.fndtn.reveal")}var a=this.settings;return n(a.animation).fade?i.fadeIn(a.animation_speed/2):(this.locked=!1,i.show())},to_back:function(t){t.addClass("toback")},to_front:function(t){t.removeClass("toback")},hide:function(i,s){if(s){var a=i.data(this.attr_name(!0)+"-init"),o=this;a=a||this.settings;var r=n(a.animation);if(r.animate||(this.locked=!1),r.pop){var l={top:-t(e).scrollTop()-i.data("offset")+"px",opacity:0};return setTimeout(function(){return i.animate(l,a.animation_speed,"linear",function(){o.locked=!1,i.css(s).trigger("closed.fndtn.reveal")}).removeClass("open")},a.animation_speed/2)}if(r.fade){var l={opacity:0};return setTimeout(function(){return i.animate(l,a.animation_speed,"linear",function(){o.locked=!1,i.css(s).trigger("closed.fndtn.reveal")}).removeClass("open")},a.animation_speed/2)}return i.hide().css(s).removeClass("open").trigger("closed.fndtn.reveal")}var a=this.settings;return n(a.animation).fade?i.fadeOut(a.animation_speed/2):i.hide()},close_video:function(e){var i=t(".flex-video",e.target),s=t("iframe",i);s.length>0&&(s.attr("data-src",s[0].src),s.attr("src",s.attr("src")),i.hide())},open_video:function(e){var i=t(".flex-video",e.target),n=i.find("iframe");if(n.length>0){var a=n.attr("data-src");if("string"==typeof a)n[0].src=n.attr("data-src");else{var o=n[0].src;n[0].src=s,n[0].src=o}i.show()}},data_attr:function(t){return this.namespace.length>0?this.namespace+"-"+t:t},cache_offset:function(t){var e=t.show().height()+parseInt(t.css("top"),10)+t.scrollY;return t.hide(),e},off:function(){t(this.scope).off(".fndtn.reveal")},reflow:function(){}}}(jQuery,window,window.document),function(t,e){"use strict";Foundation.libs.interchange={name:"interchange",version:"5.5.3",cache:{},images_loaded:!1,nodes_loaded:!1,settings:{load_attr:"interchange",named_queries:{"default":"only screen",small:Foundation.media_queries.small,"small-only":Foundation.media_queries["small-only"],medium:Foundation.media_queries.medium,"medium-only":Foundation.media_queries["medium-only"],large:Foundation.media_queries.large,"large-only":Foundation.media_queries["large-only"],xlarge:Foundation.media_queries.xlarge,"xlarge-only":Foundation.media_queries["xlarge-only"],xxlarge:Foundation.media_queries.xxlarge,landscape:"only screen and (orientation: landscape)",portrait:"only screen and (orientation: portrait)",retina:"only screen and (-webkit-min-device-pixel-ratio: 2),only screen and (min--moz-device-pixel-ratio: 2),only screen and (-o-min-device-pixel-ratio: 2/1),only screen and (min-device-pixel-ratio: 2),only screen and (min-resolution: 192dpi),only screen and (min-resolution: 2dppx)"},directives:{replace:function(e,i,s){if(null!==e&&/IMG/.test(e[0].nodeName)){var n=t.each(e,function(){this.src=i});if(new RegExp(i,"i").test(n))return;return e.attr("src",i),s(e[0].src)}var a=e.data(this.data_attr+"-last-path"),o=this;if(a!=i)return/\.(gif|jpg|jpeg|tiff|png)([?#].*)?/i.test(i)?(t(e).css("background-image","url("+i+")"),e.data("interchange-last-path",i),s(i)):t.get(i,function(t){e.html(t),e.data(o.data_attr+"-last-path",i),s()})}}},init:function(e,i,s){Foundation.inherit(this,"throttle random_str"),this.data_attr=this.set_data_attr(),t.extend(!0,this.settings,i,s),this.bindings(i,s),this.reflow()},get_media_hash:function(){var t="";for(var e in this.settings.named_queries)t+=matchMedia(this.settings.named_queries[e]).matches.toString();return t},events:function(){var i,s=this;return t(e).off(".interchange").on("resize.fndtn.interchange",s.throttle(function(){var t=s.get_media_hash();t!==i&&s.resize(),i=t},50)),this},resize:function(){var e=this.cache;if(!this.images_loaded||!this.nodes_loaded)return void setTimeout(t.proxy(this.resize,this),50);for(var i in e)if(e.hasOwnProperty(i)){var s=this.results(i,e[i]);s&&this.settings.directives[s.scenario[1]].call(this,s.el,s.scenario[0],function(t){if(arguments[0]instanceof Array)var e=arguments[0];else var e=Array.prototype.slice.call(arguments,0);return function(){t.el.trigger(t.scenario[1],e)}}(s))}},results:function(t,e){var i=e.length;if(i>0)for(var s=this.S("["+this.add_namespace("data-uuid")+'="'+t+'"]');i--;){var n,a=e[i][2];if(n=matchMedia(this.settings.named_queries.hasOwnProperty(a)?this.settings.named_queries[a]:a),n.matches)return{el:s,scenario:e[i]}}return!1},load:function(t,e){return("undefined"==typeof this["cached_"+t]||e)&&this["update_"+t](),this["cached_"+t]},update_images:function(){var t=this.S("img["+this.data_attr+"]"),e=t.length,i=e,s=0,n=this.data_attr;for(this.cache={},this.cached_images=[],this.images_loaded=0===e;i--;){if(s++,t[i]){var a=t[i].getAttribute(n)||"";a.length>0&&this.cached_images.push(t[i])}s===e&&(this.images_loaded=!0,this.enhance("images"))}return this},update_nodes:function(){var t=this.S("["+this.data_attr+"]").not("img"),e=t.length,i=e,s=0,n=this.data_attr;for(this.cached_nodes=[],this.nodes_loaded=0===e;i--;){s++;var a=t[i].getAttribute(n)||"";a.length>0&&this.cached_nodes.push(t[i]),s===e&&(this.nodes_loaded=!0,this.enhance("nodes"))}return this},enhance:function(i){for(var s=this["cached_"+i].length;s--;)this.object(t(this["cached_"+i][s]));return t(e).trigger("resize.fndtn.interchange")},convert_directive:function(t){var e=this.trim(t);return e.length>0?e:"replace"},parse_scenario:function(t){var e=t[0].match(/(.+),\s*(\w+)\s*$/),i=t[1].match(/(.*)\)/);if(e)var s=e[1],n=e[2];else var a=t[0].split(/,\s*$/),s=a[0],n="";return[this.trim(s),this.convert_directive(n),this.trim(i[1])]},object:function(t){var e=this.parse_data_attr(t),i=[],s=e.length;if(s>0)for(;s--;){var n=e[s].split(/,\s?\(/);if(n.length>1){var a=this.parse_scenario(n);i.push(a)}}return this.store(t,i)},store:function(t,e){var i=this.random_str(),s=t.data(this.add_namespace("uuid",!0));return this.cache[s]?this.cache[s]:(t.attr(this.add_namespace("data-uuid"),i),this.cache[i]=e)},trim:function(e){return"string"==typeof e?t.trim(e):e},set_data_attr:function(t){return t?this.namespace.length>0?this.namespace+"-"+this.settings.load_attr:this.settings.load_attr:this.namespace.length>0?"data-"+this.namespace+"-"+this.settings.load_attr:"data-"+this.settings.load_attr},parse_data_attr:function(t){for(var e=t.attr(this.attr_name()).split(/\[(.*?)\]/),i=e.length,s=[];i--;)e[i].replace(/[\W\d]+/,"").length>4&&s.push(e[i]);return s},reflow:function(){this.load("images",!0),this.load("nodes",!0)}}}(jQuery,window,window.document),function(t,e){"use strict";Foundation.libs["magellan-expedition"]={name:"magellan-expedition",version:"5.5.3",settings:{active_class:"active",threshold:0,destination_threshold:20,throttle_delay:30,fixed_top:0,offset_by_height:!0,duration:700,easing:"swing"},init:function(t,e,i){Foundation.inherit(this,"throttle"),this.bindings(e,i)},events:function(){var e=this,i=e.S,s=e.settings;e.set_expedition_position(),i(e.scope).off(".magellan").on("click.fndtn.magellan","["+e.add_namespace("data-magellan-arrival")+"] a[href*=#]",function(i){var s=this.hostname===location.hostname||!this.hostname,n=e.filterPathname(location.pathname)===e.filterPathname(this.pathname),a=this.hash.replace(/(:|\.|\/)/g,"\\$1"),o=this;if(s&&n&&a){i.preventDefault();var r=t(this).closest("["+e.attr_name()+"]"),l=r.data("magellan-expedition-init"),d=this.hash.split("#").join(""),c=t('a[name="'+d+'"]');0===c.length&&(c=t("#"+d));var h=c.offset().top-l.destination_threshold+1;l.offset_by_height&&(h-=r.outerHeight()),t("html, body").stop().animate({scrollTop:h},l.duration,l.easing,function(){history.pushState?history.pushState(null,null,o.pathname+o.search+"#"+d):location.hash=o.pathname+o.search+"#"+d})}}).on("scroll.fndtn.magellan",e.throttle(this.check_for_arrivals.bind(this),s.throttle_delay))},check_for_arrivals:function(){var t=this;t.update_arrivals(),t.update_expedition_positions()},set_expedition_position:function(){var e=this;t("["+this.attr_name()+"=fixed]",e.scope).each(function(){var i,s,n=t(this),a=n.data("magellan-expedition-init"),o=n.attr("styles");n.attr("style",""),i=n.offset().top+a.threshold,s=parseInt(n.data("magellan-fixed-top")),isNaN(s)||(e.settings.fixed_top=s),n.data(e.data_attr("magellan-top-offset"),i),n.attr("style",o)})},update_expedition_positions:function(){var i=this,s=t(e).scrollTop();t("["+this.attr_name()+"=fixed]",i.scope).each(function(){var e=t(this),n=e.data("magellan-expedition-init"),a=e.attr("style"),o=e.data("magellan-top-offset");if(s+i.settings.fixed_top>=o){var r=e.prev("["+i.add_namespace("data-magellan-expedition-clone")+"]");0===r.length&&(r=e.clone(),r.removeAttr(i.attr_name()),r.attr(i.add_namespace("data-magellan-expedition-clone"),""),e.before(r)),e.css({position:"fixed",top:n.fixed_top}).addClass("fixed")}else e.prev("["+i.add_namespace("data-magellan-expedition-clone")+"]").remove(),e.attr("style",a).css("position","").css("top","").removeClass("fixed")})},update_arrivals:function(){var i=this,s=t(e).scrollTop();t("["+this.attr_name()+"]",i.scope).each(function(){var e=t(this),n=e.data(i.attr_name(!0)+"-init"),a=i.offsets(e,s),o=e.find("["+i.add_namespace("data-magellan-arrival")+"]"),r=!1;a.each(function(t,s){if(s.viewport_offset>=s.top_offset){var a=e.find("["+i.add_namespace("data-magellan-arrival")+"]");return a.not(s.arrival).removeClass(n.active_class),s.arrival.addClass(n.active_class),r=!0,!0}}),r||o.removeClass(n.active_class)})},offsets:function(e,i){var s=this,n=e.data(s.attr_name(!0)+"-init"),a=i;return e.find("["+s.add_namespace("data-magellan-arrival")+"]").map(function(){var i=t(this).data(s.data_attr("magellan-arrival")),o=t("["+s.add_namespace("data-magellan-destination")+"="+i+"]");if(o.length>0){var r=o.offset().top-n.destination_threshold;return n.offset_by_height&&(r-=e.outerHeight()),r=Math.floor(r),{destination:o,arrival:t(this),top_offset:r,viewport_offset:a}}}).sort(function(t,e){return t.top_offset<e.top_offset?-1:t.top_offset>e.top_offset?1:0})},data_attr:function(t){return this.namespace.length>0?this.namespace+"-"+t:t},off:function(){this.S(this.scope).off(".magellan"),this.S(e).off(".magellan")},filterPathname:function(t){return t=t||"",t.replace(/^\//,"").replace(/(?:index|default).[a-zA-Z]{3,4}$/,"").replace(/\/$/,"")},reflow:function(){var e=this;t("["+e.add_namespace("data-magellan-expedition-clone")+"]",e.scope).remove()}}}(jQuery,window,window.document),function(t,e){"use strict";Foundation.libs.accordion={name:"accordion",version:"5.5.3",settings:{content_class:"content",active_class:"active",multi_expand:!1,toggleable:!0,callback:function(){}},init:function(t,e,i){this.bindings(e,i)},events:function(e){var i=this,s=this.S;i.create(this.S(e)),s(this.scope).off(".fndtn.accordion").on("click.fndtn.accordion","["+this.attr_name()+"] > dd > a, ["+this.attr_name()+"] > li > a",function(e){var n=s(this).closest("["+i.attr_name()+"]"),a=i.attr_name()+"="+n.attr(i.attr_name()),o=n.data(i.attr_name(!0)+"-init")||i.settings,r=s("#"+this.href.split("#")[1]),l=t("> dd, > li",n),d=l.children("."+o.content_class),c=d.filter("."+o.active_class);return e.preventDefault(),n.attr(i.attr_name())&&(d=d.add("["+a+"] dd > ."+o.content_class+", ["+a+"] li > ."+o.content_class),l=l.add("["+a+"] dd, ["+a+"] li")),o.toggleable&&r.is(c)?(r.parent("dd, li").toggleClass(o.active_class,!1),r.toggleClass(o.active_class,!1),s(this).attr("aria-expanded",function(t,e){return"true"===e?"false":"true"}),o.callback(r),r.triggerHandler("toggled",[n]),void n.triggerHandler("toggled",[r])):(o.multi_expand||(d.removeClass(o.active_class),l.removeClass(o.active_class),l.children("a").attr("aria-expanded","fal
23796se")),r.addClass(o.active_class).parent().addClass(o.active_class),o.callback(r),r.triggerHandler("toggled",[n]),n.triggerHandler("toggled",[r]),void s(this).attr("aria-expanded","true"))})},create:function(e){var i=this,s=e,n=t("> .accordion-navigation",s),a=s.data(i.attr_name(!0)+"-init")||i.settings;n.children("a").attr("aria-expanded","false"),n.has("."+a.content_class+"."+a.active_class).addClass(a.active_class).children("a").attr("aria-expanded","true"),a.multi_expand&&e.attr("aria-multiselectable","true")},toggle:function(t){var t="undefined"!=typeof t?t:{},i="undefined"!=typeof t.selector?t.selector:"",s="undefined"!=typeof t.toggle_state?t.toggle_state:"",n="undefined"!=typeof t.$accordion?t.$accordion:this.S(this.scope).closest("["+this.attr_name()+"]"),a=n.find("> dd"+i+", > li"+i);if(a.length<1)return e.console&&console.error("Selection not found.",i),!1;var o=this.S,r=this.settings.active_class;a.each(function(){var t=o(this),e=t.hasClass(r);(e&&"close"===s||!e&&"open"===s||""===s)&&t.find("> a").trigger("click.fndtn.accordion")})},open:function(t){var t="undefined"!=typeof t?t:{};t.toggle_state="open",this.toggle(t)},close:function(t){var t="undefined"!=typeof t?t:{};t.toggle_state="close",this.toggle(t)},off:function(){},reflow:function(){}}}(jQuery,window,window.document),function(t,e,i){"use strict";Foundation.libs.topbar={name:"topbar",version:"5.5.3",settings:{index:0,start_offset:0,sticky_class:"sticky",custom_back_text:!0,back_text:"Back",mobile_show_parent_link:!0,is_hover:!0,scrolltop:!0,sticky_on:"all",dropdown_autoclose:!0},init:function(e,i,s){Foundation.inherit(this,"add_custom_rule register_media throttle");var n=this;n.register_media("topbar","foundation-mq-topbar"),this.bindings(i,s),n.S("["+this.attr_name()+"]",this.scope).each(function(){{var e=t(this),i=e.data(n.attr_name(!0)+"-init");n.S("section, .top-bar-section",this)}e.data("index",0);var s=e.parent();s.hasClass("fixed")||n.is_sticky(e,s,i)?(n.settings.sticky_class=i.sticky_class,n.settings.sticky_topbar=e,e.data("height",s.outerHeight()),e.data("stickyoffset",s.offset().top)):e.data("height",e.outerHeight()),i.assembled||n.assemble(e),i.is_hover?n.S(".has-dropdown",e).addClass("not-click"):n.S(".has-dropdown",e).removeClass("not-click"),n.add_custom_rule(".f-topbar-fixed { padding-top: "+e.data("height")+"px }"),s.hasClass("fixed")&&n.S("body").addClass("f-topbar-fixed")})},is_sticky:function(t,e,i){var s=e.hasClass(i.sticky_class),n=matchMedia(Foundation.media_queries.small).matches,a=matchMedia(Foundation.media_queries.medium).matches,o=matchMedia(Foundation.media_queries.large).matches;return s&&"all"===i.sticky_on?!0:s&&this.small()&&-1!==i.sticky_on.indexOf("small")&&n&&!a&&!o?!0:s&&this.medium()&&-1!==i.sticky_on.indexOf("medium")&&n&&a&&!o?!0:s&&this.large()&&-1!==i.sticky_on.indexOf("large")&&n&&a&&o?!0:!1},toggle:function(i){var s,n=this;s=i?n.S(i).closest("["+this.attr_name()+"]"):n.S("["+this.attr_name()+"]");var a=s.data(this.attr_name(!0)+"-init"),o=n.S("section, .top-bar-section",s);n.breakpoint()&&(n.rtl?(o.css({right:"0%"}),t(">.name",o).css({right:"100%"})):(o.css({left:"0%"}),t(">.name",o).css({left:"100%"})),n.S("li.moved",o).removeClass("moved"),s.data("index",0),s.toggleClass("expanded").css("height","")),a.scrolltop?s.hasClass("expanded")?s.parent().hasClass("fixed")&&(a.scrolltop?(s.parent().removeClass("fixed"),s.addClass("fixed"),n.S("body").removeClass("f-topbar-fixed"),e.scrollTo(0,0)):s.parent().removeClass("expanded")):s.hasClass("fixed")&&(s.parent().addClass("fixed"),s.removeClass("fixed"),n.S("body").addClass("f-topbar-fixed")):(n.is_sticky(s,s.parent(),a)&&s.parent().addClass("fixed"),s.parent().hasClass("fixed")&&(s.hasClass("expanded")?(s.addClass("fixed"),s.parent().addClass("expanded"),n.S("body").addClass("f-topbar-fixed")):(s.removeClass("fixed"),s.parent().removeClass("expanded"),n.update_sticky_positioning())))},timer:null,events:function(){var i=this,s=this.S;s(this.scope).off(".topbar").on("click.fndtn.topbar","["+this.attr_name()+"] .toggle-topbar",function(t){t.preventDefault(),i.toggle(this)}).on("click.fndtn.topbar contextmenu.fndtn.topbar",'.top-bar .top-bar-section li a[href^="#"],['+this.attr_name()+'] .top-bar-section li a[href^="#"]',function(){var e=t(this).closest("li"),s=e.closest("["+i.attr_name()+"]"),n=s.data(i.attr_name(!0)+"-init");if(n.dropdown_autoclose&&n.is_hover){var a=t(this).closest(".hover");a.removeClass("hover")}!i.breakpoint()||e.hasClass("back")||e.hasClass("has-dropdown")||i.toggle()}).on("click.fndtn.topbar","["+this.attr_name()+"] li.has-dropdown",function(e){var n=s(this),a=s(e.target),o=n.closest("["+i.attr_name()+"]"),r=o.data(i.attr_name(!0)+"-init");return a.data("revealId")?void i.toggle():void(i.breakpoint()||(!r.is_hover||Modernizr.touch)&&(e.stopImmediatePropagation(),n.hasClass("hover")?(n.removeClass("hover").find("li").removeClass("hover"),n.parents("li.hover").removeClass("hover")):(n.addClass("hover"),t(n).siblings().removeClass("hover"),"A"===a[0].nodeName&&a.parent().hasClass("has-dropdown")&&e.preventDefault())))}).on("click.fndtn.topbar","["+this.attr_name()+"] .has-dropdown>a",function(t){if(i.breakpoint()){t.preventDefault();var e=s(this),n=e.closest("["+i.attr_name()+"]"),a=n.find("section, .to
23796p-bar-section"),o=(e.next(".dropdown").outerHeight(),e.closest("li"));n.data("index",n.data("index")+1),o.addClass("moved"),i.rtl?(a.css({right:-(100*n.data("index"))+"%"}),a.find(">.name").css({right:100*n.data("index")+"%"})):(a.css({left:-(100*n.data("index"))+"%"}),a.find(">.name").css({left:100*n.data("index")+"%"})),n.css("height",e.siblings("ul").outerHeight(!0)+n.data("height"))}}),s(e).off(".topbar").on("resize.fndtn.topbar",i.throttle(function(){i.resize.call(i)},50)).trigger("resize.fndtn.topbar").load(function(){s(this).trigger("resize.fndtn.topbar")}),s("body").off(".topbar").on("click.fndtn.topbar",function(t){var e=s(t.target).closest("li").closest("li.hover");e.length>0||s("["+i.attr_name()+"] li.hover").removeClass("hover")}),s(this.scope).on("click.fndtn.topbar","["+this.attr_name()+"] .has-dropdown .back",function(t){t.preventDefault();var e=s(this),n=e.closest("["+i.attr_name()+"]"),a=n.find("section, .top-bar-section"),o=(n.data(i.attr_name(!0)+"-init"),e.closest("li.moved")),r=o.parent();n.data("index",n.data("index")-1),i.rtl?(a.css({right:-(100*n.data("index"))+"%"}),a.find(">.name").css({right:100*n.data("index")+"%"})):(a.css({left:-(100*n.data("index"))+"%"}),a.find(">.name").css({left:100*n.data("index")+"%"})),0===n.data("index")?n.css("height",""):n.css("height",r.outerHeight(!0)+n.data("height")),setTimeout(function(){o.removeClass("moved")},300)}),s(this.scope).find(".dropdown a").focus(function(){t(this).parents(".has-dropdown").addClass("hover")}).blur(function(){t(this).parents(".has-dropdown").removeClass("hover")})},resize:function(){var t=this;t.S("["+this.attr_name()+"]").each(function(){var e,s=t.S(this),n=s.data(t.attr_name(!0)+"-init"),a=s.parent("."+t.settings.sticky_class);if(!t.breakpoint()){var o=s.hasClass("expanded");s.css("height","").removeClass("expanded").find("li").removeClass("hover"),o&&t.toggle(s)}t.is_sticky(s,a,n)&&(a.hasClass("fixed")?(a.removeClass("fixed"),e=a.offset().top,t.S(i.body).hasClass("f-topbar-fixed")&&(e-=s.data("height")),s.data("stickyoffset",e),a.addClass("fixed")):(e=a.offset().top,s.data("stickyoffset",e)))})},breakpoint:function(){return!matchMedia(Foundation.media_queries.topbar).matches},small:function(){return matchMedia(Foundation.media_queries.small).matches},medium:function(){return matchMedia(Foundation.media_queries.medium).matches},large:function(){return matchMedia(Foundation.media_queries.large).matches},assemble:function(e){var i=this,s=e.data(this.attr_name(!0)+"-init"),n=i.S("section, .top-bar-section",e);n.detach(),i.S(".has-dropdown>a",n).each(function(){var e,n=i.S(this),a=n.siblings(".dropdown"),o=n.attr("href");a.find(".title.back").length||(e=t(1==s.mobile_show_parent_link&&o?'<li class="title back js-generated"><h5><a href="javascript:void(0)"></a></h5></li><li class="parent-link hide-for-medium-up"><a class="parent-link js-generated" href="'+o+'">'+n.html()+"</a></li>":'<li class="title back js-generated"><h5><a href="javascript:void(0)"></a></h5>'),t("h5>a",e).html(1==s.custom_back_text?s.back_text:"« "+n.html()),a.prepend(e))}),n.appendTo(e),this.sticky(),this.assembled(e)},assembled:function(e){e.data(this.attr_name(!0),t.extend({},e.data(this.attr_name(!0)),{assembled:!0}))},height:function(e){var i=0,s=this;return t("> li",e).each(function(){i+=s.S(this).outerHeight(!0)}),i},sticky:function(){var t=this;this.S(e).on("scroll",function(){t.update_sticky_positioning()})},update_sticky_positioning:function(){var t="."+this.settings.sticky_class,i=this.S(e),s=this;if(s.settings.sticky_topbar&&s.is_sticky(this.settings.sticky_topbar,this.settings.sticky_topbar.parent(),this.settings)){var n=this.settings.sticky_topbar.data("stickyoffset")+this.settings.start_offset;s.S(t).hasClass("expanded")||(i.scrollTop()>n?s.S(t).hasClass("fixed")||(s.S(t).addClass("fixed"),s.S("body").addClass("f-topbar-fixed")):i.scrollTop()<=n&&s.S(t).hasClass("fixed")&&(s.S(t).removeClass("fixed"),s.S("body").removeClass("f-topbar-fixed")))}},off:function(){this.S(this.scope).off(".fndtn.topbar"),this.S(e).off(".fndtn.topbar")},reflow:function(){}}}
vendor: 5,004 bytes, line 23796
23796(jQuery,window,window.document),function(t,e,i,s){"use strict";Foundation.libs.tab={name:"tab",version:"5.5.3",settings:{active_class:"active",callback:function(){},deep_linking:!1,scroll_to_content:!0,is_hover:!1},default_tab_hashes:[],init:function(t,e,i){var s=this,n=this.S;n("["+this.attr_name()+"] > .active > a",this.scope).each(function(){s.default_tab_hashes.push(this.hash)}),this.bindings(e,i),this.handle_location_hash_change()},events:function(){var t=this,i=this.S,s=function(e,s){var n=i(s).closest("["+t.attr_name()+"]").data(t.attr_name(!0)+"-init");if(!n.is_hover||Modernizr.touch){var a=e.keyCode||e.which;9!==a&&(e.preventDefault(),e.stopPropagation()),t.toggle_active_tab(i(s).parent())}};i(this.scope).off(".tab").on("keydown.fndtn.tab","["+this.attr_name()+"] > * > a",function(t){var e=t.keyCode||t.which;if(13===e||32===e){var i=this;s(t,i)}}).on("click.fndtn.tab","["+this.attr_name()+"] > * > a",function(t){var e=this;s(t,e)}).on("mouseenter.fndtn.tab","["+this.attr_name()+"] > * > a",function(){var e=i(this).closest("["+t.attr_name()+"]").data(t.attr_name(!0)+"-init");e.is_hover&&t.toggle_active_tab(i(this).parent())}),i(e).on("hashchange.fndtn.tab",function(e){e.preventDefault(),t.handle_location_hash_change()})},handle_location_hash_change:function(){var e=this,i=this.S;i("["+this.attr_name()+"]",this.scope).each(function(){var n=i(this).data(e.attr_name(!0)+"-init");if(n.deep_linking){var a;if(a=n.scroll_to_content?e.scope.location.hash:e.scope.location.hash.replace("fndtn-",""),""!=a){var o=i(a);if(o.hasClass("content")&&o.parent().hasClass("tabs-content"))e.toggle_active_tab(t("["+e.attr_name()+"] > * > a[href="+a+"]").parent());else{var r=o.closest(".content").attr("id");r!=s&&e.toggle_active_tab(t("["+e.attr_name()+"] > * > a[href=#"+r+"]").parent(),a)}}else for(var l=0;l<e.default_tab_hashes.length;l++)e.toggle_active_tab(t("["+e.attr_name()+"] > * > a[href="+e.default_tab_hashes[l]+"]").parent())}})},toggle_active_tab:function(n,a){var o=this,r=o.S,l=n.closest("["+this.attr_name()+"]"),d=n.find("a"),c=n.children("a").first(),h="#"+c.attr("href").split("#")[1],u=r(h),f=n.siblings(),p=l.data(this.attr_name(!0)+"-init"),g=function(e){var s,n=t(this),a=t(this).parents("li").prev().children('[role="tab"]'),o=t(this).parents("li").next().children('[role="tab"]');switch(e.keyCode){case 37:s=a;break;case 39:s=o;break;default:s=!1}s.length&&(n.attr({tabindex:"-1","aria-selected":null}),s.attr({tabindex:"0","aria-selected":!0}).focus()),t('[role="tabpanel"]').attr("aria-hidden","true"),t("#"+t(i.activeElement).attr("href").substring(1)).attr("aria-hidden",null)},_=function(t){var i=p.scroll_to_content?o.default_tab_hashes[0]:"fndtn-"+o.default_tab_hashes[0].replace("#","");(t!==i||e.location.hash)&&(e.location.hash=t)};c.data("tab-content")&&(h="#"+c.data("tab-content").split("#")[1],u=r(h)),p.deep_linking&&(p.scroll_to_content?(_(a||h),a==s||a==h?n.parent()[0].scrollIntoView():r(h)[0].scrollIntoView()):_(a!=s?"fndtn-"+a.replace("#",""):"fndtn-"+h.replace("#",""))),n.addClass(p.active_class).triggerHandler("opened"),d.attr({"aria-selected":"true",tabindex:0}),f.removeClass(p.active_class),f.find("a").attr({"aria-selected":"false"}),u.siblings().removeClass(p.active_class).attr({"aria-hidden":"true"}),u.addClass(p.active_class).attr("aria-hidden","false").removeAttr("tabindex"),p.callback(n),u.triggerHandler("toggled",[u]),l.triggerHandler("toggled",[n]),d.off("keydown").on("keydown",g)},data_attr:function(t){return this.namespace.length>0?this.namespace+"-"+t:t},off:function(){},reflow:function(){}}}(jQuery,window,window.document),function(t,e,i){"use strict";Foundation.libs.abide={name:"abide",version:"5.5.3",settings:{live_validate:!0,validate_on_blur:!0,focus_on_invalid:!0,error_labels:!0,error_class:"error",timeout:1e3,patterns:{alpha:/^[a-zA-Z]+$/,alpha_numeric:/^[a-zA-Z0-9]+$/,integer:/^[-+]?\d+$/,number:/^[-+]?\d*(?:[\.\,]\d+)?$/,card:/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/,cvv:/^([0-9]){3,4}$/,email:/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/,url:/^(https?|ftp|file|ssh):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+~%\/\.\w]+)?\??([-\+=&;%@\.\w]+)?#?([\w]+)?)?/,domain:/^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,8}$/,datetime:/^([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])T([0-5][0-9])\:([0-5][0-9])\:([0-5][0-9])(Z|([\-\+]([0-1][0-9])\:00))$/,date:/(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))$/,time:/^(0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]){2}$/,dateISO:/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/,month_day_year:/^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.]\d{4}$/,day_month_year:/^(0[1-9]|[12][0-9]|3[01])[- \/.](0[1-9]|1[012])[- \/.]\d{4}$/,color:/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/}
23796,validators:{equalTo:function(t){var e=i.getElementById(t.getAttribute(this.add_namespace("data-equalto"))).value,s=t.value,n=e===s;return n}}},timer:null,init:function(t,e,i){this.bindings(e,i)},events:function(e){function i(t,e){clearTimeout(s.timer),s.timer=setTimeout(function(){s.validate([t],e)}.bind(t),a.timeout)}var s=this,n=s.S(e).attr("novalidate","novalidate"),a=n.data(this.attr_name(!0)+"-init")||{};this.invalid_attr=this.add_namespace("data-invalid"),n.off(".abide").on("submit.fndtn.abide",function(t){var e=/ajax/i.test(s.S(this).attr(s.attr_name()));return s.validate(s.S(this).find("input, textarea, select").not(":hidden, [data-abide-ignore]").get(),t,e)}).on("validate.fndtn.abide",function(t){"manual"===a.validate_on&&s.validate([t.target],t)}).on("reset",function(e){return s.reset(t(this),e)}).find("input, textarea, select").not(":hidden, [data-abide-ignore]").off(".abide").on("blur.fndtn.abide change.fndtn.abide",function(t){var e=this.getAttribute("id"),s=n.find('[data-equalto="'+e+'"]');a.validate_on_blur&&a.validate_on_blur===!0&&i(this,t),"undefined"!=typeof s.get(0)&&s.val().length&&i(s.get(0),t),"change"===a.validate_on&&i(this,t)}).on("keydown.fndtn.abide",function(t){var e=this.getAttribute("id"),s=n.find('[data-equalto="'+e+'"]');a.live_validate&&a.live_validate===!0&&9!=t.which&&i(this,t),"undefined"!=typeof s.get(0)&&s.val().length&&i(s.get(0),t),"tab"===a.validate_on&&9===t.which?i(this,t):"change"===a.validate_on&&i(this,t)}).on("focus",function(e){navigator.userAgent.match(/iPad|iPhone|Android|BlackBerry|Windows Phone|webOS/i)&&t("html, body").animate({scrollTop:t(e.target).offset().top},100)})},reset:function(e){var i=this;e.removeAttr(i.invalid_attr),t("["+i.invalid_attr+"]",e).removeAttr(i.invalid_attr),t("."+i.settings.error_class,e).not("small").removeClass(i.settings.error_class),t(":input",e).not(":button, :submit, :reset, :hidden, [data-abide-ignore]").val("").removeAttr(i.invalid_attr)},validate:function(t,e,i){for(var s=this.parse_patterns(t),n=s.length,a=this.S(t[0]).closest("form"),o=/submit/.test(e.type),r=0;n>r;r++)if(!s[r]&&(o||i))return this.settings.focus_on_invalid&&t[r].focus(),a.trigger("invalid.fndtn.abide"),this.S(t[r]).closest("form").attr(this.invalid_attr,""),!1;return(o||i)&&a.trigger("valid.fndtn.abide"),a.removeAttr(this.invalid_attr),i?!1:!0},parse_patterns:function(t){for(var e=t.length,i=[];e--;)i.push(this.pattern(t[e]));return this.check_validation_and_apply_styles(i)},pattern:function(t){var e=t.getAttribute("type"),i="string"==typeof t.getAttribute("required"),s=t.getAttribute("pattern")||"";return this.settings.patterns.hasOwnProperty(s)&&s.length>0?[t,this.settings.patterns[s],i]:s.length>0?[t,new RegExp(s),i]:this.settings.patterns.hasOwnProperty(e)?[t,this.settings.patterns[e],i]:(s=/.*/,[t,s,i])},check_validation_and_apply_styles:function(e){var i=e.length,s=[];if(0==i)return s;var n=this.S(e[0][0]).closest("[data-"+this.attr_name(!0)+"]");for(n.data(this.attr_name(!0)+"-init")||{};i--;){var a,o,r=e[i][0],l=e[i][2],d=r.value.trim(),c=this.S(r).parent(),h=r.getAttribute(this.add_namespace("data-abide-validator")),u="radio"===r.type,f="checkbox"===r.type,p=this.S('label[for="'+r.getAttribute("id")+'"]'),g=l?r.value.length>0:!0,_=[];if(r.getAttribute(this.add_namespace("data-equalto"))&&(h="equalTo"),a=c.is("label")?c.parent():c,u&&l)_.push(this.valid_radio(r,l));else if(f&&l)_.push(this.valid_checkbox(r,l));else if(h){for(var m=h.split(" "),v=!0,b=!0,x=0;x<m.length;x++)o=this.settings.validators[m[x]].apply(this,[r,l,a]),_.push(o),b=o&&v,v=o;b?(this.S(r).removeAttr(this.invalid_attr),a.removeClass("error"),p.length>0&&this.settings.error_labels&&p.removeClass(this.settings.error_class).removeAttr("role"),t(r).triggerHandler("valid")):(this.S(r).attr(this.invalid_attr,""),a.addClass("error"),p.length>0&&this.settings.error_labels&&p.addClass(this.settings.error_class).attr("role","alert"),t(r).triggerHandler("invalid"))}else if(_.push(e[i][1].test(d)&&g||!l&&r.value.length<1||t(r).attr("disabled")?!0:!1),_=[_.every(function(t){return t})],_[0])this.S(r).removeAttr(this.invalid_attr),r.setAttribute("aria-invalid","false"),r.removeAttribute("aria-describedby"),a.removeClass(this.settings.error_class),p.length>0&&this.settings.error_labels&&p.removeClass(this.settings.error_class).removeAttr("role"),t(r).triggerHandler("valid");else{this.S(r).attr(this.invalid_attr,""),r.setAttribute("aria-invalid","true");var y=a.find("small."+this.settings.error_class,"span."+this.settings.error_class),w=y.length>0?y[0].id:"";w.length>0&&r.setAttribute("aria-describedby",w),a.addClass(this.settings.error_class),p.length>0&&this.settings.error_labels&&p.addClass(this.settings.error_class).attr("role","alert"),t(r).triggerHandler("invalid")}s=s.concat(_)}return s},valid_checkbox:function(e,i){var e=this.S(e),s=e.is(":checked")||!i||e.get(0).getAttribute("disabled");return s?(e.removeAttr(this.invalid_attr).parent().removeClass(this.settings.error_class),t(e).triggerHandler("valid")):(e.attr(this.invalid_attr,"").parent().addClass(this.settings.error_class),t(e).triggerHandler("invalid")),s 23797 23798},valid_radio:function(e){for(var i=e.getAttribute("name"),s=this.S(e).closest("[data-"+this.attr_name(!0)+"]").find("[name='"+i+"']"),n=s.length,a=!1,o=!1,r=0;n>r;r++)s[r].getAttribute("disabled")?(o=!0,a=!0):s[r].checked?a=!0:o&&(a=!1);for(var r=0;n>r;r++)a?(this.S(s[r]).removeAttr(this.invalid_attr).parent().removeClass(this.settings.error_class),t(s[r]).triggerHandler("valid")):(this.S(s[r]).attr(this.invalid_attr,"").parent().addClass(this.settings.error_class),t(s[r]).triggerHandler("invalid"));return a},valid_equal:function(t,e,s){var n=i.getElementById(t.getAttribute(this.add_namespace("data-equalto"))).value,a=t.value,o=n===a;return o?(this.S(t).removeAttr(this.invalid_attr),s.removeClass(this.settings.error_class),label.length>0&&settings.error_labels&&label.removeClass(this.settings.error_class)):(this.S(t).attr(this.invalid_attr,""),s.addClass(this.settings.error_class),label.length>0&&settings.error_labels&&label.addClass(this.settings.error_class)),o}
23798,valid_oneof:function(t,e,i,s){var t=this.S(t),n=this.S("["+this.add_namespace("data-oneof")+"]"),a=n.filter(":checked").length>0;if(a?t.removeAttr(this.invalid_attr).parent().removeClass(this.settings.error_class):t.attr(this.invalid_attr,"").parent().addClass(this.settings.error_class),!s){var o=this;n.each(function(){o.valid_oneof.call(o,this,null,null,!0)})}return a},reflow:function(){var t=this,e=t.S("["+this.attr_name()+"]").attr("novalidate","novalidate");t.S(e).each(function(e,i){t.events(i)})}}}(jQuery,window,window.document),function(t,e){"use strict";Foundation.libs.tooltip={name:"tooltip",version:"5.5.3",settings:{additional_inheritable_classes:[],tooltip_class:".tooltip",append_to:"body",touch_close_text:"Tap To Close",disable_for_touch:!1,hover_delay:200,fade_in_duration:150,fade_out_duration:150,show_on:"all",tip_template:function(t,e){return'<span data-selector="'+t+'" id="'+t+'" class="'+Foundation.libs.tooltip.settings.tooltip_class.substring(1)+'" role="tooltip">'+e+'<span class="nub"></span></span>'}},cache:{},init:function(t,e,i){Foundation.inherit(this,"random_str"),this.bindings(e,i)},should_show:function(e){var i=t.extend({},this.settings,this.data_options(e));return"all"===i.show_on?!0:this.small()&&"small"===i.show_on?!0:this.medium()&&"medium"===i.show_on?!0:this.large()&&"large"===i.show_on?!0:!1},medium:function(){return matchMedia(Foundation.media_queries.medium).matches},large:function(){return matchMedia(Foundation.media_queries.large).matches},events:function(e){function i(t,e,i){t.timer||(i?(t.timer=null,n.showTip(e)):t.timer=setTimeout(function(){t.timer=null,n.showTip(e)}.bind(t),n.settings.hover_delay))}function s(t,e){t.timer&&(clearTimeout(t.timer),t.timer=null),n.hide(e)}var n=this,a=n.S;n.create(this.S(e)),t(this.scope).off(".tooltip").on("mouseenter.fndtn.tooltip mouseleave.fndtn.tooltip touchstart.fndtn.tooltip MSPointerDown.fndtn.tooltip","["+this.attr_name()+"]",function(e){var o=a(this),r=t.extend({},n.settings,n.data_options(o)),l=!1;if(Modernizr.touch&&/touchstart|MSPointerDown/i.test(e.type)&&a(e.target).is("a"))return!1;if(/mouse/i.test(e.type)&&n.ie_touch(e))return!1;if(o.hasClass("open"))Modernizr.touch&&/touchstart|MSPointerDown/i.test(e.type)&&e.preventDefault(),n.hide(o);else{if(r.disable_for_touch&&Modernizr.touch&&/touchstart|MSPointerDown/i.test(e.type))return;if(!r.disable_for_touch&&Modernizr.touch&&/touchstart|MSPointerDown/i.test(e.type)&&(e.preventDefault(),a(r.tooltip_class+".open").hide(),l=!0,t(".open["+n.attr_name()+"]").length>0)){var d=a(t(".open["+n.attr_name()+"]")[0]);n.hide(d)}/enter|over/i.test(e.type)?i(this,o):"mouseout"===e.type||"mouseleave"===e.type?s(this,o):i(this,o,!0)}}).on("mouseleave.fndtn.tooltip touchstart.fndtn.tooltip MSPointerDown.fndtn.tooltip","["+this.attr_name()+"].open",function(e){return/mouse/i.test(e.type)&&n.ie_touch(e)?!1:void(("touch"!=t(this).data("tooltip-open-event-type")||"mouseleave"!=e.type)&&("mouse"==t(this).data("tooltip-open-event-type")&&/MSPointerDown|touchstart/i.test(e.type)?n.convert_to_touch(t(this)):s(this,t(this))))}).on("DOMNodeRemoved DOMAttrModified","["+this.attr_name()+"]:not(a)",function(){s(this,a(this))})},ie_touch:function(){return!1},showTip:function(t){var e=this.getTip(t);return this.should_show(t,e)?this.show(t):void 0},getTip:function(e){var i=this.selector(e),s=t.extend({},this.settings,this.data_options(e)),n=null;return i&&(n=this.S('span[data-selector="'+i+'"]'+s.tooltip_class)),"object"==typeof n?n:!1},selector:function(t){var e=t.attr(this.attr_name())||t.attr("data-selector");return"string"!=typeof e&&(e=this.random_str(6),t.attr("data-selector",e).attr("aria-describedby",e)),e},create:function(i){var s=this,n=t.extend({},this.settings,this.data_options(i)),a=this.settings.tip_template;"string"==typeof n.tip_template&&e.hasOwnProperty(n.tip_template)&&(a=e[n.tip_template]);var o=t(a(this.selector(i),t("<div></div>").html(i.attr("title")).html())),r=this.inheritable_classes(i);o.addClass(r).appendTo(n.append_to),Modernizr.touch&&(o.append('<span class="tap-to-close">'+n.touch_close_text+"</span>"),o.on("touchstart.fndtn.tooltip MSPointerDown.fndtn.tooltip",function(){s.hide(i)})),i.removeAttr("title").attr("title","")},reposition:function(e,i,s){var n,a,o,r,l;i.css("visibility","hidden").show(),n=e.data("width"),a=i.children(".nub"),o=a.outerHeight(),r=a.outerWidth(),i.css(this.small
23798()?{width:"100%"}:{width:n?n:"auto"}),l=function(t,e,i,s,n){return t.css({top:e?e:"auto",bottom:s?s:"auto",left:n?n:"auto",right:i?i:"auto"}).end()};var d=e.offset().top,c=e.offset().left,h=e.outerHeight();if(l(i,d+h+10,"auto","auto",c),this.small())l(i,d+h+10,"auto","auto",12.5,t(this.scope).width()),i.addClass("tip-override"),l(a,-o,"auto","auto",c);else{Foundation.rtl&&(a.addClass("rtl"),c=c+e.outerWidth()-i.outerWidth()),l(i,d+h+10,"auto","auto",c),a.attr("style")&&a.removeAttr("style"),i.removeClass("tip-override");var u=i.outerHeight();s&&s.indexOf("tip-top")>-1?(Foundation.rtl&&a.addClass("rtl"),l(i,d-u,"auto","auto",c).removeClass("tip-override")):s&&s.indexOf("tip-left")>-1?(l(i,d+h/2-u/2,"auto","auto",c-i.outerWidth()-o).removeClass("tip-override"),a.removeClass("rtl")):s&&s.indexOf("tip-right")>-1&&(l(i,d+h/2-u/2,"auto","auto",c+e.outerWidth()+o).removeClass("tip-override"),a.removeClass("rtl"))}i.css("visibility","visible").hide()},small:function(){return matchMedia(Foundation.media_queries.small).matches&&!matchMedia(Foundation.media_queries.medium).matches},inheritable_classes:function(e){var i=t.extend({},this.settings,this.data_options(e)),s=["tip-top","tip-left","tip-bottom","tip-right","radius","round"].concat(i.additional_inheritable_classes),n=e.attr("class"),a=n?t.map(n.split(" "),function(e){return-1!==t.inArray(e,s)?e:void 0}).join(" "):"";return t.trim(a)},convert_to_touch:function(e){var i=this,s=i.getTip(e),n=t.extend({},i.settings,i.data_options(e));0===s.find(".tap-to-close").length&&(s.append('<span class="tap-to-close">'+n.touch_close_text+"</span>"),s.on("click.fndtn.tooltip.tapclose touchstart.fndtn.tooltip.tapclose MSPointerDown.fndtn.tooltip.tapclose",function(){i.hide(e)})),e.data("tooltip-open-event-type","touch")},show:function(t){var e=this.getTip(t);"touch"==t.data("tooltip-open-event-type")&&this.convert_to_touch(t),this.reposition(t,e,t.attr("class")),t.addClass("open"),e.fadeIn(this.settings.fade_in_duration)},hide:function(t){var e=this.getTip(t);e.fadeOut(this.settings.fade_out_duration,function(){e.find(".tap-to-close").remove(),e.off("click.fndtn.tooltip.tapclose MSPointerDown.fndtn.tapclose"),t.removeClass("open")})},off:function(){var e=this;this.S(this.scope).off(".fndtn.tooltip"),this.S(this.settings.tooltip_class).each(function(i){t("["+e.attr_name()+"]").eq(i).attr("title",t(this).text())}).remove()},reflow:function(){}}}(jQuery,window,window.document); 23799 23800 23801/*! 23802 23803 * jQuery Form Plugin 23804 23805 * version: 3.51.0-2014.06.20 23806 23807 * Requires jQuery v1.5 or later 23808 23809 * Copyright (c) 2014 M. Alsup 23810 23811 * Examples and documentation at: http://malsup.com/jquery/form/ 23812 23813 * Project repository: https://github.com/malsup/form 23814 23815 * Dual licensed under the MIT and GPL licenses. 23816 23817 * https://github.com/malsup/form#copyright-and-license 23818 23819 */ 23820 23821!function(e){"use strict";"function"==typeof define&&define.amd?define(["jquery"],e):e("undefined"!=typeof jQuery?jQuery:window.Zepto)}(function(e){"use strict";function t(t){var r=t.data;t.isDefaultPrevented()||(t.preventDefault(),e(t.target).ajaxSubmit(r))}function r(t){var r=t.target,a=e(r);if(!a.is("[type=submit],[type=image]")){var n=a.closest("[type=submit]");if(0===n.length)return;r=n[0]}var i=this;if(i.clk=r,"image"==r.type)if(void 0!==t.offsetX)i.clk_x=t.offsetX,i.clk_y=t.offsetY;else if("function"==typeof e.fn.offset){var o=a.offset();i.clk_x=t.pageX-o.left,i.clk_y=t.pageY-o.top}else i.clk_x=t.pageX-r.offsetLeft,i.clk_y=t.pageY-r.offsetTop;setTimeout(function(){i.clk=i.clk_x=i.clk_y=null},100)}function a(){if(e.fn.ajaxSubmit.debug){var t="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(t):window.opera&&window.opera.postError&&window.opera.postError(t)}}var n={};n.fileapi=void 0!==e("<input type='file'/>").get(0).files,n.formdata=void 0!==window.FormData;var i=!!e.fn.prop;e.fn.attr2=function(){if(!i)return this.attr.apply(this,arguments);var e=this.prop.apply(this,arguments);return e&&e.jquery||"string"==typeof e?e:this.attr.apply(this,arguments)},e.fn.ajaxSubmit=function(t){function r(r){var a,n,i=e.param(r,t.traditional).split("&"),o=i.length,s=[];for(a=0;o>a;a++)i[a]=i[a].replace(/\+/g," "),n=i[a].split("="),s.push([decodeURIComponent(n[0]),decodeURIComponent(n[1])]);return s}function o(a){for(var n=new FormData,i=0;i<a.length;i++)n.append(a[i].name,a[i].value);if(t.extraData){var o=r(t.extraData);for(i=0;i<o.length;i++)o[i]&&n.append(o[i][0],o[i][1])}t.data=null;var s=e.extend(!0,{},e.ajaxSettings,t,{contentType:!1,processData:!1,cache:!1,type:u||"POST"});t.uploadProgress&&(s.xhr=function(){var r=e.ajaxSettings.xhr();return r.upload&&r.upload.addEventListener("progress",function(e){var r=0,a=e.loaded||e.position,n=e.total;e.lengthComputable&&(r=Math.ceil(a/n*100)),t.uploadProgress(e,a,n,r)},!1),r}),s.data=null;var c=s.beforeSend;return s.beforeSend=function(e,r){r.data=t.formData?t.formData:n,c&&c.call(this,e,r)},e.ajax(s)}function s(r){function n(e){var t=null;try{e.contentWindow&&(t=e.contentWindow.document)}catch(r){a("cannot get iframe.contentWindow document: "+r)}if(t)return t;try{t=e.contentDocument?e.contentDocument:e.document}catch(r){a("cannot get iframe.contentDocument: "+r),t=e.document}return t}function o(){function t(){try{var e=n(g).readyState;a("state = "+e),e&&"uninitialized"==e.toLowerCase()&&setTimeout(t,50)}catch(r){a("Server abort: ",r," (",r.name,")"),s(k),j&&clearTimeout(j),j=void 0}}
23821var r=f.attr2("target"),i=f.attr2("action"),o="multipart/form-data",c=f.attr("enctype")||f.attr("encoding")||o;w.setAttribute("target",p),(!u||/post/i.test(u))&&w.setAttribute("method","POST"),i!=m.url&&w.setAttribute("action",m.url),m.skipEncodingOverride||u&&!/post/i.test(u)||f.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"}),m.timeout&&(j=setTimeout(function(){T=!0,s(D)},m.timeout));var l=[];try{if(m.extraData)for(var d in m.extraData)m.extraData.hasOwnProperty(d)&&l.push(e.isPlainObject(m.extraData[d])&&m.extraData[d].hasOwnProperty("name")&&m.extraData[d].hasOwnProperty("value")?e('<input type="hidden" name="'+m.extraData[d].name+'">').val(m.extraData[d].value).appendTo(w)[0]:e('<input type="hidden" name="'+d+'">').val(m.extraData[d]).appendTo(w)[0]);m.iframeTarget||v.appendTo("body"),g.attachEvent?g.attachEvent("onload",s):g.addEventListener("load",s,!1),setTimeout(t,15);try{w.submit()}catch(h){var x=document.createElement("form").submit;x.apply(w)}}finally{w.setAttribute("action",i),w.setAttribute("enctype",c),r?w.setAttribute("target",r):f.removeAttr("target"),e(l).remove()}}function s(t){if(!x.aborted&&!F){if(M=n(g),M||(a("cannot access response document"),t=k),t===D&&x)return x.abort("timeout"),void S.reject(x,"timeout");if(t==k&&x)return x.abort("server abort"),void S.reject(x,"error","server abort");if(M&&M.location.href!=m.iframeSrc||T){g.detachEvent?g.detachEvent("onload",s):g.removeEventListener("load",s,!1);var r,i="success";try{if(T)throw"timeout";var o="xml"==m.dataType||M.XMLDocument||e.isXMLDoc(M);if(a("isXml="+o),!o&&window.opera&&(null===M.body||!M.body.innerHTML)&&--O)return a("requeing onLoad callback, DOM not available"),void setTimeout(s,250);var u=M.body?M.body:M.documentElement;x.responseText=u?u.innerHTML:null,x.responseXML=M.XMLDocument?M.XMLDocument:M,o&&(m.dataType="xml"),x.getResponseHeader=function(e){var t={"content-type":m.dataType};return t[e.toLowerCase()]},u&&(x.status=Number(u.getAttribute("status"))||x.status,x.statusText=u.getAttribute("statusText")||x.statusText);var c=(m.dataType||"").toLowerCase(),l=/(json|script|text)/.test(c);if(l||m.textarea){var f=M.getElementsByTagName("textarea")[0];if(f)x.responseText=f.value,x.status=Number(f.getAttribute("status"))||x.status,x.statusText=f.getAttribute("statusText")||x.statusText;else if(l){var p=M.getElementsByTagName("pre")[0],h=M.getElementsByTagName("body")[0];p?x.responseText=p.textContent?p.textContent:p.innerText:h&&(x.responseText=h.textContent?h.textContent:h.innerText)}}else"xml"==c&&!x.responseXML&&x.responseText&&(x.responseXML=X(x.responseText));try{E=_(x,c,m)}catch(y){i="parsererror",x.error=r=y||i}}catch(y){a("error caught: ",y),i="error",x.error=r=y||i}x.aborted&&(a("upload aborted"),i=null),x.status&&(i=x.status>=200&&x.status<300||304===x.status?"success":"error"),"success"===i?(m.success&&m.success.call(m.context,E,"success",x),S.resolve(x.responseText,"success",x),d&&e.event.trigger("ajaxSuccess",[x,m])):i&&(void 0===r&&(r=x.statusText),m.error&&m.error.call(m.context,x,i,r),S.reject(x,"error",r),d&&e.event.trigger("ajaxError",[x,m,r])),d&&e.event.trigger("ajaxComplete",[x,m]),d&&!--e.active&&e.event.trigger("ajaxStop"),m.complete&&m.complete.call(m.context,x,i),F=!0,m.timeout&&clearTimeout(j),setTimeout(function(){m.iframeTarget?v.attr("src",m.iframeSrc):v.remove(),x.responseXML=null},100)}}}var c,l,m,d,p,v,g,x,y,b,T,j,w=f[0],S=e.Deferred();if(S.abort=function(e){x.abort(e)},r)for(l=0;l<h.length;l++)c=e(h[l]),i?c.prop("disabled",!1):c.removeAttr("disabled");if(m=e.extend(!0,{},e.ajaxSettings,t),m.context=m.context||m,p="jqFormIO"+(new Date).getTime(),m.iframeTarget?(v=e(m.iframeTarget),b=v.attr2("name"),b?p=b:v.attr2("name",p)):(v=e('<iframe name="'+p+'" src="'+m.iframeSrc+'" />'),v.css({position:"absolute",top:"-1000px",left:"-1000px"})),g=v[0],x={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(t){var r="timeout"===t?"timeout":"aborted";a("aborting upload... "+r),this.aborted=1;try{g.contentWindow.document.execCommand&&g.contentWindow.document.execCommand("Stop")}catch(n){}v.attr("src",m.iframeSrc),x.error=r,m.error&&m.error.call(m.context,x,r,t),d&&e.event.trigger("ajaxError",[x,m,r]),m.complete&&m.complete.call(m.context,x,r)}},d=m.global,d&&0===e.active++&&e.event.trigger("ajaxStart"),d&&e.event.trigger("ajaxSend",[x,m]),m.beforeSend&&m.beforeSend.c
23821all(m.context,x,m)===!1)return m.global&&e.active--,S.reject(),S;if(x.aborted)return S.reject(),S;y=w.clk,y&&(b=y.name,b&&!y.disabled&&(m.extraData=m.extraData||{},m.extraData[b]=y.value,"image"==y.type&&(m.extraData[b+".x"]=w.clk_x,m.extraData[b+".y"]=w.clk_y)));var D=1,k=2,A=e("meta[name=csrf-token]").attr("content"),L=e("meta[name=csrf-param]").attr("content");L&&A&&(m.extraData=m.extraData||{},m.extraData[L]=A),m.forceSync?o():setTimeout(o,10);var E,M,F,O=50,X=e.parseXML||function(e,t){return window.ActiveXObject?(t=new ActiveXObject("Microsoft.XMLDOM"),t.async="false",t.loadXML(e)):t=(new DOMParser).parseFromString(e,"text/xml"),t&&t.documentElement&&"parsererror"!=t.documentElement.nodeName?t:null},C=e.parseJSON||function(e){return window.eval("("+e+")")},_=function(t,r,a){var n=t.getResponseHeader("content-type")||"",i="xml"===r||!r&&n.indexOf("xml")>=0,o=i?t.responseXML:t.responseText;return i&&"parsererror"===o.documentElement.nodeName&&e.error&&e.error("parsererror"),a&&a.dataFilter&&(o=a.dataFilter(o,r)),"string"==typeof o&&("json"===r||!r&&n.indexOf("json")>=0?o=C(o):("script"===r||!r&&n.indexOf("javascript")>=0)&&e.globalEval(o)),o};return S}if(!this.length)return a("ajaxSubmit: skipping submit process - no element selected"),this;var u,c,l,f=this;"function"==typeof t?t={success:t}:void 0===t&&(t={}),u=t.type||this.attr2("method"),c=t.url||this.attr2("action"),l="string"==typeof c?e.trim(c):"",l=l||window.location.href||"",l&&(l=(l.match(/^([^#]+)/)||[])[1]),t=e.extend(!0,{url:l,success:e.ajaxSettings.success,type:u||e.ajaxSettings.type,iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},t);var m={};if(this.trigger("form-pre-serialize",[this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(t.beforeSerialize&&t.beforeSerialize(this,t)===!1)return a("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var d=t.traditional;void 0===d&&(d=e.ajaxSettings.traditional);var p,h=[],v=this.formToArray(t.semantic,h);if(t.data&&(t.extraData=t.data,p=e.param(t.data,d)),t.beforeSubmit&&t.beforeSubmit(v,this,t)===!1)return a("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[v,this,t,m]),m.veto)return a("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var g=e.param(v,d);p&&(g=g?g+"&"+p:p),"GET"==t.type.toUpperCase()?(t.url+=(t.url.indexOf("?")>=0?"&":"?")+g,t.data=null):t.data=g;var x=[];if(t.resetForm&&x.push(function(){f.resetForm()}),t.clearForm&&x.push(function(){f.clearForm(t.includeHidden)}),!t.dataType&&t.target){var y=t.success||function(){};x.push(function(r){var a=t.replaceTarget?"replaceWith":"html";e(t.target)[a](r).each(y,arguments)})}else t.success&&x.push(t.success);if(t.success=function(e,r,a){for(var n=t.context||this,i=0,o=x.length;o>i;i++)x[i].apply(n,[e,r,a||f,f])},t.error){var b=t.error;t.error=function(e,r,a){var n=t.context||this;b.apply(n,[e,r,a,f])}}if(t.complete){var T=t.complete;t.complete=function(e,r){var a=t.context||this;T.apply(a,[e,r,f])}}var j=e("input[type=file]:enabled",this).filter(function(){return""!==e(this).val()}),w=j.length>0,S="multipart/form-data",D=f.attr("enctype")==S||f.attr("encoding")==S,k=n.fileapi&&n.formdata;a("fileAPI :"+k);var A,L=(w||D)&&!k;t.iframe!==!1&&(t.iframe||L)?t.closeKeepAlive?e.get(t.closeKeepAlive,function(){A=s(v)}):A=s(v):A=(w||D)&&k?o(v):e.ajax(t),f.removeData("jqxhr").data("jqxhr",A);for(var E=0;E<h.length;E++)h[E]=null;return this.trigger("form-submit-notify",[this,t]),this},e.fn.ajaxForm=function(n){if(n=n||{},n.delegation=n.delegation&&e.isFunction(e.fn.on),!n.delegation&&0===this.length){var i={s:this.selector,c:this.context};return!e.isReady&&i.s?(a("DOM not ready, queuing ajaxForm"),e(function(){e(i.s,i.c).ajaxForm(n)}),this):(a("terminating; zero elements found by selector"+(e.isReady?"":" (DOM not ready)")),this)}return n.delegation?(e(document).off("submit.form-plugin",this.selector,t).off("click.form-plugin",this.selector,r).on("submit.form-plugin",this.selector,n,t).on("click.form-plugin",this.selector,n,r),this):this.ajaxFormUnbind().bind("submit.form-plugin",n,t).bind("click.form-plugin",n,r)},e.fn.ajaxFormUnbind=function(){return this.unbind("submit.form-plugin click.form-plugin")},e.fn.formToArray=function(t,r){var a=[];if(0===this.length)return a;var i,o=this[0],s=this.attr("id"),u=t?o.getElementsByTagName("*"):o.elements;if(u&&!/MSIE [678]/.test(navigator.userAgent)&&(u=e(u).get()),s&&(i=e(':input[form="'+s+'"]').get(),i.length&&(u=(u||[]).concat(i))),!u||!u.length)return a;var c,l,f,m,d,p,h;for(c=0,p=u.length;p>c;c++)if(d=u[c],f=d.name,f&&!d.disabled)if(t&&o.clk&&"image"==d.type)o.clk==d&&(a.push({name:f,value:e(d).val(),type:d.type}),a.push({name:f+".x",value:o.clk_x},{name:f+".y",value:o.clk_y}));else if(m=e.fieldValue(d,!0),m&&m.constructor==Array)for(r&&r.push(d),l=0,h=m.length;h>l;l++)a.push({name:f,value:m[l]});else if(n.fileapi&&"file"==d.type){r&&r.push(d);var v=d.files;if(v.length)for(l=0;l<v.length;l++)a.push({name:f,value:v[l],type:d.type});else a.push({name:f,value:"",type:d.type})}else null!==m&&"undefined"!=typeof m&&(r&&r.push(d),a.push({name:f,value:m,type:d.type,required:d.required}));if(!t&&o.clk){var g=e(o.clk),x=g[0];f=x.name,f&&!x.disabled&&"image"==x.type&&(a.push({name:f,value:g.val()}),a.push({name:f+".x",value:o.clk_x},{name:f+".y",value:o.clk_y}))}return a}
23821,e.fn.formSerialize=function(t){return e.param(this.formToArray(t))},e.fn.fieldSerialize=function(t){var r=[];return this.each(function(){var a=this.name;if(a){var n=e.fieldValue(this,t);if(n&&n.constructor==Array)for(var i=0,o=n.length;o>i;i++)r.push({name:a,value:n[i]});else null!==n&&"undefined"!=typeof n&&r.push({name:this.name,value:n})}}),e.param(r)},e.fn.fieldValue=function(t){for(var r=[],a=0,n=this.length;n>a;a++){var i=this[a],o=e.fieldValue(i,t);null===o||"undefined"==typeof o||o.constructor==Array&&!o.length||(o.constructor==Array?e.merge(r,o):r.push(o))}return r},e.fieldValue=function(t,r){var a=t.name,n=t.type,i=t.tagName.toLowerCase();if(void 0===r&&(r=!0),r&&(!a||t.disabled||"reset"==n||"button"==n||("checkbox"==n||"radio"==n)&&!t.checked||("submit"==n||"image"==n)&&t.form&&t.form.clk!=t||"select"==i&&-1==t.selectedIndex))return null;if("select"==i){var o=t.selectedIndex;if(0>o)return null;for(var s=[],u=t.options,c="select-one"==n,l=c?o+1:u.length,f=c?o:0;l>f;f++){var m=u[f];if(m.selected){var d=m.value;if(d||(d=m.attributes&&m.attributes.value&&!m.attributes.value.specified?m.text:m.value),c)return d;s.push(d)}}return s}return e(t).val()},e.fn.clearForm=function(t){return this.each(function(){e("input,select,textarea",this).clearFields(t)})},e.fn.clearFields=e.fn.clearInputs=function(t){var r=/^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i;return this.each(function(){var a=this.type,n=this.tagName.toLowerCase();r.test(a)||"textarea"==n?this.value="":"checkbox"==a||"radio"==a?this.checked=!1:"select"==n?this.selectedIndex=-1:"file"==a?/MSIE/.test(navigator.userAgent)?e(this).replaceWith(e(this).clone(!0)):e(this).val(""):t&&(t===!0&&/hidden/.test(a)||"string"==typeof t&&e(this).is(t))&&(this.value="")})},e.fn.resetForm=function(){return this.each(function(){("function"==typeof this.reset||"object"==typeof this.reset&&!this.reset.nodeType)&&this.reset()})},e.fn.enable=function(e){return void 0===e&&(e=!0),this.each(function(){this.disabled=!e})},e.fn.selected=function(t){return void 0===t&&(t=!0),this.each(function(){var r=this.type;if("checkbox"==r||"radio"==r)this.checked=t;else if("option"==this.tagName.toLowerCase()){var a=e(this).parent("select");t&&a[0]&&"select-one"==a[0].type&&a.find("option").selected(!1),this.selected=t}})},e.fn.ajaxSubmit.debug=!1}); 23822/*! Magnific Popup - v1.0.0 - 2015-12-16 23823 23824* http://dimsemenov.com/plugins/magnific-popup/ 23825 23826* Copyright (c) 2015 Dmitry Semenov; */ 23827 23828!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):window.jQuery||window.Zepto)}(function(a){var b,c,d,e,f,g,h="Close",i="BeforeClose",j="AfterClose",k="BeforeAppend",l="MarkupParse",m="Open",n="Change",o="mfp",p="."+o,q="mfp-ready",r="mfp-removing",s="mfp-prevent-close",t=function(){},u=!!window.jQuery,v=a(window),w=function(a,c){b.ev.on(o+a+p,c)},x=function(b,c,d,e){var f=document.createElement("div");return f.className="mfp-"+b,d&&(f.innerHTML=d),e?c&&c.appendChild(f):(f=a(f),c&&f.appendTo(c)),f},y=function(c,d){b.ev.triggerHandler(o+c,d),b.st.callbacks&&(c=c.charAt(0).toLowerCase()+c.slice(1),b.st.callbacks[c]&&b.st.callbacks[c].apply(b,a.isArray(d)?d:[d]))},z=function(c){return c===g&&b.currTemplate.closeBtn||(b.currTemplate.closeBtn=a(b.st.closeMarkup.replace("%title%",b.st.tClose)),g=c),b.currTemplate.closeBtn},A=function(){a.magnificPopup.instance||(b=new t,b.init(),a.magnificPopup.instance=b)},B=function(){var a=document.createElement("p").style,b=["ms","O","Moz","Webkit"];if(void 0!==a.transition)return!0;for(;b.length;)if(b.pop()+"Transition"in a)return!0;return!1};t.prototype={constructor:t,init:function(){var c=navigator.appVersion;b.isIE7=-1!==c.indexOf("MSIE 7."),b.isIE8=-1!==c.indexOf("MSIE 8."),b.isLowIE=b.isIE7||b.isIE8,b.isAndroid=/android/gi.test(c),b.isIOS=/iphone|ipad|ipod/gi.test(c),b.supportsTransition=B(),b.probablyMobile=b.isAndroid||b.isIOS||/(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent),d=a(document),b.popupsCache={}},open:function(c){var e;if(c.isObj===!1){b.items=c.items.toArray(),b.index=0;var g,h=c.items;for(e=0;e<h.length;e++)if(g=h[e],g.parsed&&(g=g.el[0]),g===c.el[0]){b.index=e;break}}else b.items=a.isArray(c.items)?c.items:[c.items],b.index=c.index||0;if(b.isOpen)return void b.updateItemHTML();b.types=[],f="",c.mainEl&&c.mainEl.length?b.ev=c.mainEl.eq(0):b.ev=d,c.key?(b.popupsCache[c.key]||(b.popupsCache[c.key]={}),b.currTemplate=b.popupsCache[c.key]):b.currTemplate={},b.st=a.extend(!0,{},a.magnificPopup.defaults,c),b.fixedContentPos="auto"===b.st.fixedContentPos?!b.probablyMobile:b.st.fixedContentPos,b.st.modal&&(b.st.closeOnContentClick=!1,b.st.closeOnBgClick=!1,b.st.showCloseBtn=!1,b.st.enableEscapeKey=!1),b.bgOverlay||(b.bgOverlay=x("bg").on("click"+p,function(){b.close()}),b.wrap=x("wrap").attr("tabindex",-1).on("click"+p,function(a){b._checkIfClose(a.target)&&b.close()}),b.container=x("container",b.wrap)),b.contentContainer=x("content"),b.st.preloader&&(b.preloader=x("preloader",b.container,b.st.tLoading));var i=a.magnificPopup.modules;for(e=0;e<i.length;e++){var j=i[e];j=j.charAt(0).toUpperCase()+j.slice(1),b["init"+j].call(b)}y("BeforeOpen"),b.st.showCloseBtn&&(b.st.closeBtnInside?(w(l,function(a,b,c,d){c.close_replaceWith=z(d.type)}),f+=" mfp-close-btn-in"):b.wrap.append(z())),b.st.alignTop&&(f+=" mfp-align-top"),b.fixedContentPos?b.wrap.css({overflow:b.st.overflowY,overflowX:"hidden",overflowY:b.
23828st.overflowY}):b.wrap.css({top:v.scrollTop(),position:"absolute"}),(b.st.fixedBgPos===!1||"auto"===b.st.fixedBgPos&&!b.fixedContentPos)&&b.bgOverlay.css({height:d.height(),position:"absolute"}),b.st.enableEscapeKey&&d.on("keyup"+p,function(a){27===a.keyCode&&b.close()}),v.on("resize"+p,function(){b.updateSize()}),b.st.closeOnContentClick||(f+=" mfp-auto-cursor"),f&&b.wrap.addClass(f);var k=b.wH=v.height(),n={};if(b.fixedContentPos&&b._hasScrollBar(k)){var o=b._getScrollbarSize();o&&(n.marginRight=o)}b.fixedContentPos&&(b.isIE7?a("body, html").css("overflow","hidden"):n.overflow="hidden");var r=b.st.mainClass;return b.isIE7&&(r+=" mfp-ie7"),r&&b._addClassToMFP(r),b.updateItemHTML(),y("BuildControls"),a("html").css(n),b.bgOverlay.add(b.wrap).prependTo(b.st.prependTo||a(document.body)),b._lastFocusedEl=document.activeElement,setTimeout(function(){b.content?(b._addClassToMFP(q),b._setFocus()):b.bgOverlay.addClass(q),d.on("focusin"+p,b._onFocusIn)},16),b.isOpen=!0,b.updateSize(k),y(m),c},close:function(){b.isOpen&&(y(i),b.isOpen=!1,b.st.removalDelay&&!b.isLowIE&&b.supportsTransition?(b._addClassToMFP(r),setTimeout(function(){b._close()},b.st.removalDelay)):b._close())},_close:function(){y(h);var c=r+" "+q+" ";if(b.bgOverlay.detach(),b.wrap.detach(),b.container.empty(),b.st.mainClass&&(c+=b.st.mainClass+" "),b._removeClassFromMFP(c),b.fixedContentPos){var e={marginRight:""};b.isIE7?a("body, html").css("overflow",""):e.overflow="",a("html").css(e)}d.off("keyup"+p+" focusin"+p),b.ev.off(p),b.wrap.attr("class","mfp-wrap").removeAttr("style"),b.bgOverlay.attr("class","mfp-bg"),b.container.attr("class","mfp-container"),!b.st.showCloseBtn||b.st.closeBtnInside&&b.currTemplate[b.currItem.type]!==!0||b.currTemplate.closeBtn&&b.currTemplate.closeBtn.detach(),b.st.autoFocusLast&&b._lastFocusedEl&&a(b._lastFocusedEl).focus(),b.currItem=null,b.content=null,b.currTemplate=null,b.prevHeight=0,y(j)},updateSize:function(a){if(b.isIOS){var c=document.documentElement.clientWidth/window.innerWidth,d=window.innerHeight*c;b.wrap.css("height",d),b.wH=d}else b.wH=a||v.height();b.fixedContentPos||b.wrap.css("height",b.wH),y("Resize")},updateItemHTML:function(){var c=b.items[b.index];b.contentContainer.detach(),b.content&&b.content.detach(),c.parsed||(c=b.parseEl(b.index));var d=c.type;if(y("BeforeChange",[b.currItem?b.currItem.type:"",d]),b.currItem=c,!b.currTemplate[d]){var f=b.st[d]?b.st[d].markup:!1;y("FirstMarkupParse",f),f?b.currTemplate[d]=a(f):b.currTemplate[d]=!0}e&&e!==c.type&&b.container.removeClass("mfp-"+e+"-holder");var g=b["get"+d.charAt(0).toUpperCase()+d.slice(1)](c,b.currTemplate[d]);b.appendContent(g,d),c.preloaded=!0,y(n,c),e=c.type,b.container.prepend(b.contentContainer),y("AfterChange")},appendContent:function(a,c){b.content=a,a?b.st.showCloseBtn&&b.st.closeBtnInside&&b.currTemplate[c]===!0?b.content.find(".mfp-close").length||b.content.append(z()):b.content=a:b.content="",y(k),b.container.addClass("mfp-"+c+"-holder"),b.contentContainer.append(b.content)},parseEl:function(c){var d,e=b.items[c];if(e.tagName?e={el:a(e)}:(d=e.type,e={data:e,src:e.src}),e.el){for(var f=b.types,g=0;g<f.length;g++)if(e.el.hasClass("mfp-"+f[g])){d=f[g];break}e.src=e.el.attr("data-mfp-src"),e.src||(e.src=e.el.attr("href"))}return e.type=d||b.st.type||"inline",e.index=c,e.parsed=!0,b.items[c]=e,y("ElementParse",e),b.items[c]},addGroup:function(a,c){var d=function(d){d.mfpEl=this,b._openClick(d,a,c)};c||(c={});var e="click.magnificPopup";c.mainEl=a,c.items?(c.isObj=!0,a.off(e).on(e,d)):(c.isObj=!1,c.delegate?a.off(e).on(e,c.delegate,d):(c.items=a,a.off(e).on(e,d)))},_openClick:function(c,d,e){var f=void 0!==e.midClick?e.midClick:a.magnificPopup.defaults.midClick;if(f||!(2===c.which||c.ctrlKey||c.metaKey||c.altKey||c.shiftKey)){var g=void 0!==e.disableOn?e.disableOn:a.magnificPopup.defaults.disableOn;if(g)if(a.isFunction(g)){if(!g.call(b))return!0}else if(v.width()<g)return!0;c.type&&(c.preventDefault(),b.isOpen&&c.stopPropagation()),e.el=a(c.mfpEl),e.delegate&&(e.items=d.find(e.delegate)),b.open(e)}},updateStatus:function(a,d){if(b.preloader){c!==a&&b.container.removeClass("mfp-s-"+c),d||"loading"!==a||(d=b.st.tLoading);var e={status:a,text:d};y("UpdateStatus",e),a=e.status,d=e.text,b.preloader.html(d),b.preloader.find("a").on("click",function(a){a.stopImmediatePropagation()}),b.container.addClass("mfp-s-"+a),c=a}},_checkIfClose:function(c){if(!a(c).hasClass(s)){var d=b.st.closeOnContentClick,e=b.st.closeOnBgClick;if(d&&e)return!0;
23828if(!b.content||a(c).hasClass("mfp-close")||b.preloader&&c===b.preloader[0])return!0;if(c===b.content[0]||a.contains(b.content[0],c)){if(d)return!0}else if(e&&a.contains(document,c))return!0;return!1}},_addClassToMFP:function(a){b.bgOverlay.addClass(a),b.wrap.addClass(a)},_removeClassFromMFP:function(a){this.bgOverlay.removeClass(a),b.wrap.removeClass(a)},_hasScrollBar:function(a){return(b.isIE7?d.height():document.body.scrollHeight)>(a||v.height())},_setFocus:function(){(b.st.focus?b.content.find(b.st.focus).eq(0):b.wrap).focus()},_onFocusIn:function(c){return c.target===b.wrap[0]||a.contains(b.wrap[0],c.target)?void 0:(b._setFocus(),!1)},_parseMarkup:function(b,c,d){var e;d.data&&(c=a.extend(d.data,c)),y(l,[b,c,d]),a.each(c,function(a,c){if(void 0===c||c===!1)return!0;if(e=a.split("_"),e.length>1){var d=b.find(p+"-"+e[0]);if(d.length>0){var f=e[1];"replaceWith"===f?d[0]!==c[0]&&d.replaceWith(c):"img"===f?d.is("img")?d.attr("src",c):d.replaceWith('<img src="'+c+'" class="'+d.attr("class")+'" />'):d.attr(e[1],c)}}else b.find(p+"-"+a).html(c)})},_getScrollbarSize:function(){if(void 0===b.scrollbarSize){var a=document.createElement("div");a.style.cssText="width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;",document.body.appendChild(a),b.scrollbarSize=a.offsetWidth-a.clientWidth,document.body.removeChild(a)}return b.scrollbarSize}},a.magnificPopup={instance:null,proto:t.prototype,modules:[],open:function(b,c){return A(),b=b?a.extend(!0,{},b):{},b.isObj=!0,b.index=c||0,this.instance.open(b)},close:function(){return a.magnificPopup.instance&&a.magnificPopup.instance.close()},registerModule:function(b,c){c.options&&(a.magnificPopup.defaults[b]=c.options),a.extend(this.proto,c.proto),this.modules.push(b)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,prependTo:null,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'<button title="%title%" type="button" class="mfp-close">×</button>',tClose:"Close (Esc)",tLoading:"Loading...",autoFocusLast:!0}},a.fn.magnificPopup=function(c){A();var d=a(this);if("string"==typeof c)if("open"===c){var e,f=u?d.data("magnificPopup"):d[0].magnificPopup,g=parseInt(arguments[1],10)||0;f.items?e=f.items[g]:(e=d,f.delegate&&(e=e.find(f.delegate)),e=e.eq(g)),b._openClick({mfpEl:e},d,f)}else b.isOpen&&b[c].apply(b,Array.prototype.slice.call(arguments,1));else c=a.extend(!0,{},c),u?d.data("magnificPopup",c):d[0].magnificPopup=c,b.addGroup(d,c);return d};var C,D,E,F="inline",G=function(){E&&(D.after(E.addClass(C)).detach(),E=null)};a.magnificPopup.registerModule(F,{options:{hiddenClass:"hide",markup:"",tNotFound:"Content not found"},proto:{initInline:function(){b.types.push(F),w(h+"."+F,function(){G()})},getInline:function(c,d){if(G(),c.src){var e=b.st.inline,f=a(c.src);if(f.length){var g=f[0].parentNode;g&&g.tagName&&(D||(C=e.hiddenClass,D=x(C),C="mfp-"+C),E=f.after(D).detach().removeClass(C)),b.updateStatus("ready")}else b.updateStatus("error",e.tNotFound),f=a("<div>");return c.inlineElement=f,f}return b.updateStatus("ready"),b._parseMarkup(d,{},c),d}}});var H,I="ajax",J=function(){H&&a(document.body).removeClass(H)},K=function(){J(),b.req&&b.req.abort()};a.magnificPopup.registerModule(I,{options:{settings:null,cursor:"mfp-ajax-cur",tError:'<a href="%url%">The content</a> could not be loaded.'},proto:{initAjax:function(){b.types.push(I),H=b.st.ajax.cursor,w(h+"."+I,K),w("BeforeChange."+I,K)},getAjax:function(c){H&&a(document.body).addClass(H),b.updateStatus("loading");var d=a.extend({url:c.src,success:function(d,e,f){var g={data:d,xhr:f};y("ParseAjax",g),b.appendContent(a(g.data),I),c.finished=!0,J(),b._setFocus(),setTimeout(function(){b.wrap.addClass(q)},16),b.updateStatus("ready"),y("AjaxContentAdded")},error:function(){J(),c.finished=c.loadError=!0,b.updateStatus("error",b.st.ajax.tError.replace("%url%",c.src))}},b.st.ajax.settings);return b.req=a.ajax(d),""}}});var L,M=function(c){if(c.data&&void 0!==c.data.title)return c.data.title;
23828var d=b.st.image.titleSrc;if(d){if(a.isFunction(d))return d.call(b,c);if(c.el)return c.el.attr(d)||""}return""};a.magnificPopup.registerModule("image",{options:{markup:'<div class="mfp-figure"><div class="mfp-close"></div><figure><div class="mfp-img"></div><figcaption><div class="mfp-bottom-bar"><div class="mfp-title"></div><div class="mfp-counter"></div></div></figcaption></figure></div>',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'<a href="%url%">The image</a> could not be loaded.'},proto:{initImage:function(){var c=b.st.image,d=".image";b.types.push("image"),w(m+d,function(){"image"===b.currItem.type&&c.cursor&&a(document.body).addClass(c.cursor)}),w(h+d,function(){c.cursor&&a(document.body).removeClass(c.cursor),v.off("resize"+p)}),w("Resize"+d,b.resizeImage),b.isLowIE&&w("AfterChange",b.resizeImage)},resizeImage:function(){var a=b.currItem;if(a&&a.img&&b.st.image.verticalFit){var c=0;b.isLowIE&&(c=parseInt(a.img.css("padding-top"),10)+parseInt(a.img.css("padding-bottom"),10)),a.img.css("max-height",b.wH-c)}},_onImageHasSize:function(a){a.img&&(a.hasSize=!0,L&&clearInterval(L),a.isCheckingImgSize=!1,y("ImageHasSize",a),a.imgHidden&&(b.content&&b.content.removeClass("mfp-loading"),a.imgHidden=!1))},findImageSize:function(a){var c=0,d=a.img[0],e=function(f){L&&clearInterval(L),L=setInterval(function(){return d.naturalWidth>0?void b._onImageHasSize(a):(c>200&&clearInterval(L),c++,void(3===c?e(10):40===c?e(50):100===c&&e(500)))},f)};e(1)},getImage:function(c,d){var e=0,f=function(){c&&(c.img[0].complete?(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("ready")),c.hasSize=!0,c.loaded=!0,y("ImageLoadComplete")):(e++,200>e?setTimeout(f,100):g()))},g=function(){c&&(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("error",h.tError.replace("%url%",c.src))),c.hasSize=!0,c.loaded=!0,c.loadError=!0)},h=b.st.image,i=d.find(".mfp-img");if(i.length){var j=document.createElement("img");j.className="mfp-img",c.el&&c.el.find("img").length&&(j.alt=c.el.find("img").attr("alt")),c.img=a(j).on("load.mfploader",f).on("error.mfploader",g),j.src=c.src,i.is("img")&&(c.img=c.img.clone()),j=c.img[0],j.naturalWidth>0?c.hasSize=!0:j.width||(c.hasSize=!1)}return b._parseMarkup(d,{title:M(c),img_replaceWith:c.img},c),b.resizeImage(),c.hasSize?(L&&clearInterval(L),c.loadError?(d.addClass("mfp-loading"),b.updateStatus("error",h.tError.replace("%url%",c.src))):(d.removeClass("mfp-loading"),b.updateStatus("ready")),d):(b.updateStatus("loading"),c.loading=!0,c.hasSize||(c.imgHidden=!0,d.addClass("mfp-loading"),b.findImageSize(c)),d)}}});var N,O=function(){return void 0===N&&(N=void 0!==document.createElement("p").style.MozTransform),N};a.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(a){return a.is("img")?a:a.find("img")}},proto:{initZoom:function(){var a,c=b.st.zoom,d=".zoom";if(c.enabled&&b.supportsTransition){var e,f,g=c.duration,j=function(a){var b=a.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),d="all "+c.duration/1e3+"s "+c.easing,e={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},f="transition";return e["-webkit-"+f]=e["-moz-"+f]=e["-o-"+f]=e[f]=d,b.css(e),b},k=function(){b.content.css("visibility","visible")};w("BuildControls"+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.content.css("visibility","hidden"),a=b._getItemToZoom(),!a)return void k();f=j(a),f.css(b._getOffset()),b.wrap.append(f),e=setTimeout(function(){f.css(b._getOffset(!0)),e=setTimeout(function(){k(),setTimeout(function(){f.remove(),a=f=null,y("ZoomAnimationEnded")},16)},g)},16)}}),w(i+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.st.removalDelay=g,!a){if(a=b._getItemToZoom(),!a)return;f=j(a)}f.css(b._getOffset(!0)),b.wrap.append(f),b.content.css("visibility","hidden"),setTimeout(function(){f.css(b._getOffset())},16)}}),w(h+d,function(){b._allowZoom()&&(k(),f&&f.remove(),a=null)})}},_allowZoom:function(){return"image"===b.currItem.type},_getItemToZoom:function(){return b.currItem.hasSize?b.currItem.img:!1},_getOffset:function(c){var d;d=c?b.currItem.img:b.st.zoom.opener(b.currItem.el||b.currItem);var e=d.offset(),f=parseInt(d.css("padding-top"),10),g=parseInt(d.css("padding-bottom"),10);e.top-=a(window).scrollTop()-f;var h={width:d.width(),height:(u?d.innerHeight():d[0].offsetHeight)-g-f};return O()?h["-moz-transform"]=h.transform="translate("+e.left+"px,"+e.top+"px)":(h.left=e.left,h.top=e.top),h}}});
23828var P="iframe",Q="//about:blank",R=function(a){if(b.currTemplate[P]){var c=b.currTemplate[P].find("iframe");c.length&&(a||(c[0].src=Q),b.isIE8&&c.css("display",a?"block":"none"))}};a.magnificPopup.registerModule(P,{options:{markup:'<div class="mfp-iframe-scaler"><div class="mfp-close"></div><iframe class="mfp-iframe" src="//about:blank" frameborder="0" allowfullscreen></iframe></div>',srcAction:"iframe_src",patterns:{youtube:{index:"youtube.com",id:"v=",src:"//www.youtube.com/embed/%id%?autoplay=1"},vimeo:{index:"vimeo.com/",id:"/",src:"//player.vimeo.com/video/%id%?autoplay=1"},gmaps:{index:"//maps.google.",src:"%id%&output=embed"}}},proto:{initIframe:function(){b.types.push(P),w("BeforeChange",function(a,b,c){b!==c&&(b===P?R():c===P&&R(!0))}),w(h+"."+P,function(){R()})},getIframe:function(c,d){var e=c.src,f=b.st.iframe;a.each(f.patterns,function(){return e.indexOf(this.index)>-1?(this.id&&(e="string"==typeof this.id?e.substr(e.lastIndexOf(this.id)+this.id.length,e.length):this.id.call(this,e)),e=this.src.replace("%id%",e),!1):void 0});var g={};return f.srcAction&&(g[f.srcAction]=e),b._parseMarkup(d,g,c),b.updateStatus("ready"),d}}});var S=function(a){var c=b.items.length;return a>c-1?a-c:0>a?c+a:a},T=function(a,b,c){return a.replace(/%curr%/gi,b+1).replace(/%total%/gi,c)};a.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'<button title="%title%" type="button" class="mfp-arrow mfp-arrow-%dir%"></button>',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous (Left arrow key)",tNext:"Next (Right arrow key)",tCounter:"%curr% of %total%"},proto:{initGallery:function(){var c=b.st.gallery,e=".mfp-gallery",g=Boolean(a.fn.mfpFastClick);return b.direction=!0,c&&c.enabled?(f+=" mfp-gallery",w(m+e,function(){c.navigateByImgClick&&b.wrap.on("click"+e,".mfp-img",function(){return b.items.length>1?(b.next(),!1):void 0}),d.on("keydown"+e,function(a){37===a.keyCode?b.prev():39===a.keyCode&&b.next()})}),w("UpdateStatus"+e,function(a,c){c.text&&(c.text=T(c.text,b.currItem.index,b.items.length))}),w(l+e,function(a,d,e,f){var g=b.items.length;e.counter=g>1?T(c.tCounter,f.index,g):""}),w("BuildControls"+e,function(){if(b.items.length>1&&c.arrows&&!b.arrowLeft){var d=c.arrowMarkup,e=b.arrowLeft=a(d.replace(/%title%/gi,c.tPrev).replace(/%dir%/gi,"left")).addClass(s),f=b.arrowRight=a(d.replace(/%title%/gi,c.tNext).replace(/%dir%/gi,"right")).addClass(s),h=g?"mfpFastClick":"click";e[h](function(){b.prev()}),f[h](function(){b.next()}),b.isIE7&&(x("b",e[0],!1,!0),x("a",e[0],!1,!0),x("b",f[0],!1,!0),x("a",f[0],!1,!0)),b.container.append(e.add(f))}}),w(n+e,function(){b._preloadTimeout&&clearTimeout(b._preloadTimeout),b._preloadTimeout=setTimeout(function(){b.preloadNearbyImages(),b._preloadTimeout=null},16)}),void w(h+e,function(){d.off(e),b.wrap.off("click"+e),b.arrowLeft&&g&&b.arrowLeft.add(b.arrowRight).destroyMfpFastClick(),b.arrowRight=b.arrowLeft=null})):!1},next:function(){b.direction=!0,b.index=S(b.index+1),b.updateItemHTML()},prev:function(){b.direction=!1,b.index=S(b.index-1),b.updateItemHTML()},goTo:function(a){b.direction=a>=b.index,b.index=a,b.updateItemHTML()},preloadNearbyImages:function(){var a,c=b.st.gallery.preload,d=Math.min(c[0],b.items.length),e=Math.min(c[1],b.items.length);for(a=1;a<=(b.direction?e:d);a++)b._preloadItem(b.index+a);for(a=1;a<=(b.direction?d:e);a++)b._preloadItem(b.index-a)},_preloadItem:function(c){if(c=S(c),!b.items[c].preloaded){var d=b.items[c];d.parsed||(d=b.parseEl(c)),y("LazyLoad",d),"image"===d.type&&(d.img=a('<img class="mfp-img" />').on("load.mfploader",function(){d.hasSize=!0}).on("error.mfploader",function(){d.hasSize=!0,d.loadError=!0,y("LazyLoadError",d)}).attr("src",d.src)),d.preloaded=!0}}}});var U="retina";a.magnificPopup.registerModule(U,{options:{replaceSrc:function(a){return a.src.replace(/\.\w+$/,function(a){return"@2x"+a})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var a=b.st.retina,c=a.ratio;c=isNaN(c)?c():c,c>1&&(w("ImageHasSize."+U,function(a,b){b.img.css({"max-width":b.img[0].naturalWidth/c,width:"100%"})}),w("ElementParse."+U,function(b,d){d.src=a.replaceSrc(d,c)}))}}}}),function(){var b=1e3,c="ontouchstart"in window,d=function(){v.off("touchmove"+f+" touchend"+f)},e="mfpFastClick",f="."+e;a.fn.mfpFastClick=function(e){return a(this).each(function(){var g,h=a(this);if(c){var i,j,k,l,m,n;h.on("touchstart"+f,function(a){l=!1,n=1,m=a.originalEvent?a.originalEvent.touches[0]:a.touches[0],j=m.clientX,k=m.clientY,v.on("touchmove"+f,function(a){m=a.originalEvent?a.originalEvent.touches:a.touches,n=m.length,m=m[0],(Math.abs(m.clientX-j)>10||Math.abs(m.clientY-k)>10)&&(l=!0,d())}).on("touchend"+f,function(a){d(),l||n>1||(g=!0,a.preventDefault(),clearTimeout(i),i=setTimeout(function(){g=!1},b),e())})})}h.on("click"+f,function(){g||e()})})},a.fn.destroyMfpFastClick=function(){a(this).off("touchstart"+f+" click"+f),c&&v.off("touchmove"+f+" touchend"+f)}}(),A()}); 23829/*! waitForImages jQuery Plugin - v2.0.2 - 2015-06-02 23830 23831* https://github.com/alexanderdickson/waitForImages 23832 23833* Copyright (c) 2015 Alex Dickson; Licensed MIT */ 23834 23835;(function (factory) { 23836 23837 if (typeof define === 'function' && define.amd) { 23838 23839 // AMD. Register as an anonymous module. 23840 23841 define(['jquery'], factory); 23842 23843 } else if (typeof exports === 'object') { 23844 23845 // CommonJS / nodejs module 23846 23847 module.exports = factory(require('jquery')); 23848 23849 } else { 23850 23851 // Browser globals 23852 23853 factory(jQuery); 23854 23855 } 23856 23857}(function ($) { 23858 23859 // Namespace all events. 23860 23861 var eventNamespace = 'waitForImages'; 23862 23863 23864 23865 // CSS properties which contain references to images. 23866 23867 $.waitForImages = { 23868 23869 hasImageProperties: [ 23870 23871 'backgroundImage', 23872 23873 'listStyleImage', 23874 23875 'borderImage', 23876 23877 'borderCornerImage', 23878 23879 'cursor' 23880 23881 ], 23882 23883 hasImageAttributes: ['srcset'] 23884 23885 }; 23886 23887 23888 23889 // Custom selector to find all `img` elements with a valid `src` attribute. 23890 23891 $.expr[':']['has-src'] = function (obj) { 23892 23893 // Ensure we are dealing with an `img` element with a valid 23894 23895 // `src` attribute. 23896 23897 return $(obj).is('img[src][src!=""]'); 23898 23899 }; 23900 23901 23902 23903 // Custom selector to find images which are not already cached by the 23904 23905 // browser. 23906 23907 $.expr[':'].uncached = function (obj) { 23908 23909 // Ensure we are dealing with an `img` element with a valid 23910 23911 // `src` attribute. 23912 23913 if (!$(obj).is(':has-src')) { 23914 23915 return false;
23916 23917 } 23918 23919 23920 23921 return !obj.complete; 23922 23923 }; 23924 23925 23926 23927 $.fn.waitForImages = function () { 23928 23929 23930 23931 var allImgsLength = 0; 23932 23933 var allImgsLoaded = 0; 23934 23935 var deferred = $.Deferred(); 23936 23937 23938 23939 var finishedCallback; 23940 23941 var eachCallback; 23942 23943 var waitForAll; 23944 23945 23946 23947 // Handle options object (if passed). 23948 23949 if ($.isPlainObject(arguments[0])) { 23950 23951 23952 23953 waitForAll = arguments[0].waitForAll; 23954 23955 eachCallback = arguments[0].each; 23956 23957 finishedCallback = arguments[0].finished; 23958 23959 23960 23961 } else { 23962 23963 23964 23965 // Handle if using deferred object and only one param was passed in. 23966 23967 if (arguments.length === 1 && $.type(arguments[0]) === 'boolean') { 23968 23969 waitForAll = arguments[0]; 23970 23971 } else { 23972 23973 finishedCallback = arguments[0]; 23974 23975 eachCallback = arguments[1]; 23976 23977 waitForAll = arguments[2]; 23978 23979 } 23980 23981 23982 23983 } 23984 23985 23986 23987 // Handle missing callbacks. 23988 23989 finishedCallback = finishedCallback || $.noop; 23990 23991 eachCallback = eachCallback || $.noop; 23992 23993 23994 23995 // Convert waitForAll to Boolean 23996 23997 waitForAll = !! waitForAll; 23998 23999 24000 24001 // Ensure callbacks are functions. 24002 24003 if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) { 24004 24005 throw new TypeError('An invalid callback was supplied.'); 24006 24007 } 24008 24009 24010 24011 this.each(function () { 24012 24013 // Build a list of all imgs, dependent on what images will 24014 24015 // be considered. 24016 24017 var obj = $(this); 24018 24019 var allImgs = []; 24020 24021 // CSS properties which may contain an image. 24022 24023 var hasImgProperties = $.waitForImages.hasImageProperties || []; 24024 24025 // Element attributes which may contain an image. 24026 24027 var hasImageAttributes = $.waitForImages.hasImageAttributes || []; 24028 24029 // To match `url()` references. 24030 24031 // Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri 24032 24033 var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g; 24034 24035 24036 24037 if (waitForAll) { 24038 24039 24040 24041 // Get all elements (including the original), as any one of 24042 24043 // them could have a background image. 24044 24045 obj.find('*').addBack().each(function () { 24046 24047 var element = $(this); 24048 24049 24050 24051 // If an `img` element, add it. But keep iterating in 24052 24053 // case it has a background image too. 24054 24055 if (element.is('img:has-src')) { 24056 24057 allImgs.push({ 24058 24059 src: element.attr('src'), 24060 24061 element: element[0] 24062 24063 }); 24064 24065 } 24066 24067 24068 24069 $.each(hasImgProperties, function (i, property) { 24070 24071 var propertyValue = element.css(property); 24072 24073 var match; 24074 24075 24076 24077 // If it doesn't contain this property, skip. 24078 24079 if (!propertyValue) { 24080 24081 return true; 24082 24083 } 24084 24085 24086 24087 // Get all url() of this element. 24088 24089 while (match = matchUrl.exec(propertyValue)) { 24090 24091 allImgs.push({ 24092 24093 src: match[2], 24094 24095 element: element[0] 24096 24097 }); 24098 24099 } 24100 24101 }); 24102 24103 24104 24105 $.each(hasImageAttributes, function (i, attribute) { 24106 24107 var attributeValue = element.attr(attribute); 24108 24109 var attributeValues; 24110 24111 24112 24113 // If it doesn't contain this property, skip. 24114 24115 if (!attributeValue) { 24116 24117 return true; 24118 24119 } 24120 24121 24122 24123 // Check for multiple comma separated images 24124 24125 attributeValues = attributeValue.split(','); 24126 24127 24128 24129 $.each(attributeValues, function(i, value) { 24130 24131 // Trim value and get string before first 24132 24133 // whitespace (for use with srcset). 24134 24135 value = $.trim(value).split(' ')[0]; 24136 24137 allImgs.push({ 24138 24139 src: value, 24140 24141 element: element[0] 24142 24143 }); 24144 24145 }); 24146 24147 }); 24148 24149 }); 24150 24151 } else { 24152 24153 // For images only, the task is simpler. 24154 24155 obj.find('img:has-src') 24156 24157 .each(function () { 24158 24159 allImgs.push({ 24160 24161 src: this.src, 24162 24163 element: this 24164 24165 }); 24166 24167 }); 24168 24169 } 24170 24171 24172 24173 allImgsLength = allImgs.length; 24174 24175 allImgsLoaded = 0; 24176 24177 24178 24179 // If no images found, don't bother. 24180 24181 if (allImgsLength === 0) { 24182 24183 finishedCallback.call(obj[0]); 24184 24185 deferred.resolveWith(obj[0]); 24186 24187 } 24188 24189 24190 24191 $.each(allImgs, function (i, img) { 24192 24193 24194 24195 var image = new Image(); 24196 24197 var events = 24198 24199 'load.' + eventNamespace + ' error.' + eventNamespace; 24200 24201 24202 24203 // Handle the image loading and error with the same callback. 24204 24205 $(image).one(events, function me (event) { 24206 24207 // If an error occurred with loading the image, set the 24208 24209 // third argument accordingly. 24210 24211 var eachArguments = [ 24212 24213 allImgsLoaded, 24214 24215 allImgsLength,
24216 24217 event.type == 'load' 24218 24219 ]; 24220 24221 allImgsLoaded++; 24222 24223 24224 24225 eachCallback.apply(img.element, eachArguments); 24226 24227 deferred.notifyWith(img.element, eachArguments); 24228 24229 24230 24231 // Unbind the event listeners. I use this in addition to 24232 24233 // `one` as one of those events won't be called (either 24234 24235 // 'load' or 'error' will be called). 24236 24237 $(this).off(events, me); 24238 24239 24240 24241 if (allImgsLoaded == allImgsLength) { 24242 24243 finishedCallback.call(obj[0]); 24244 24245 deferred.resolveWith(obj[0]); 24246 24247 return false; 24248 24249 } 24250 24251 24252 24253 }); 24254 24255 24256 24257 image.src = img.src; 24258 24259 }); 24260 24261 }); 24262 24263 24264 24265 return deferred.promise(); 24266 24267 24268 24269 }; 24270 24271})); 24272 24273 24274/*! 24275 24276 * JavaScript Cookie v2.0.4 24277 24278 * https://github.com/js-cookie/js-cookie 24279 24280 * 24281 24282 * Copyright 2006, 2015 Klaus Hartl & Fagner Brack 24283 24284 * Released under the MIT license 24285 24286 */ 24287 24288(function (factory) { 24289 24290 if (typeof define === 'function' && define.amd) { 24291 24292 define(factory); 24293 24294 } else if (typeof exports === 'object') { 24295 24296 module.exports = factory(); 24297 24298 } else { 24299 24300 var _OldCookies = window.Cookies; 24301 24302 var api = window.Cookies = factory(); 24303 24304 api.noConflict = function () { 24305 24306 window.Cookies = _OldCookies; 24307 24308 return api; 24309 24310 }; 24311 24312 } 24313 24314}(function () { 24315 24316 function extend () { 24317 24318 var i = 0; 24319 24320 var result = {}; 24321 24322 for (; i < arguments.length; i++) { 24323 24324 var attributes = arguments[ i ]; 24325 24326 for (var key in attributes) { 24327 24328 result[key] = attributes[key]; 24329 24330 } 24331 24332 } 24333 24334 return result; 24335 24336 } 24337 24338 24339 24340 function init (converter) { 24341 24342 function api (key, value, attributes) { 24343 24344 var result; 24345 24346 24347 24348 // Write 24349 24350 24351 24352 if (arguments.length > 1) { 24353 24354 attributes = extend({ 24355 24356 path: '/' 24357 24358 }, api.defaults, attributes); 24359 24360 24361 24362 if (typeof attributes.expires === 'number') { 24363 24364 var expires = new Date(); 24365 24366 expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); 24367 24368 attributes.expires = expires; 24369 24370 } 24371 24372 24373 24374 try { 24375 24376 result = JSON.stringify(value); 24377 24378 if (/^[\{\[]/.test(result)) { 24379 24380 value = result; 24381 24382 } 24383 24384 } catch (e) {} 24385 24386 24387 24388 if (!converter.write) { 24389 24390 value = encodeURIComponent(String(value)) 24391 24392 .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); 24393 24394 } else { 24395 24396 value = converter.write(value, key); 24397 24398 } 24399 24400 24401 24402 key = encodeURIComponent(String(key)); 24403 24404 key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); 24405 24406 key = key.replace(/[\(\)]/g, escape); 24407 24408 24409 24410 return (document.cookie = [ 24411 24412 key, '=', value, 24413 24414 attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE 24415 24416 attributes.path && '; path=' + attributes.path, 24417 24418 attributes.domain && '; domain=' + attributes.domain, 24419 24420 attributes.secure ? '; secure' : '' 24421 24422 ].join('')); 24423 24424 } 24425 24426 24427 24428 // Read 24429 24430 24431 24432 if (!key) { 24433 24434 result = {}; 24435 24436 } 24437 24438 24439 24440 // To prevent the for loop in the first place assign an empty array 24441 24442 // in case there are no cookies at all. Also prevents odd result when 24443 24444 // calling "get()" 24445 24446 var cookies = document.cookie ? document.cookie.split('; ') : []; 24447 24448 var rdecode = /(%[0-9A-Z]{2})+/g; 24449 24450 var i = 0; 24451 24452 24453 24454 for (; i < cookies.length; i++) { 24455 24456 var parts = cookies[i].split('='); 24457 24458 var name = parts[0].replace(rdecode, decodeURIComponent); 24459 24460 var cookie = parts.slice(1).join('='); 24461 24462 24463 24464 if (cookie.charAt(0) === '"') { 24465 24466 cookie = cookie.slice(1, -1); 24467 24468 } 24469 24470 24471 24472 try { 24473 24474 cookie = converter.read ? 24475 24476 converter.read(cookie, name) : converter(cookie, name) || 24477 24478 cookie.replace(rdecode, decodeURIComponent); 24479 24480 24481 24482 if (this.json) { 24483 24484 try { 24485 24486 cookie = JSON.parse(cookie); 24487 24488 } catch (e) {} 24489 24490 } 24491 24492 24493 24494 if (key === name) { 24495 24496 result = cookie; 24497 24498 break; 24499 24500 } 24501 24502 24503 24504 if (!key) { 24505 24506 result[name] = cookie; 24507 24508 } 24509 24510 } catch (e) {} 24511 24512 } 24513 24514 24515 24516 return result; 24517 24518 } 24519 24520 24521 24522 api.get = api.set = api; 24523 24524 api.getJSON = function () { 24525 24526 return api.apply({ 24527 24528 json: true 24529 24530 }, [].slice.call(arguments)); 24531 24532 }; 24533 24534 api.defaults = {}; 24535 24536 24537 24538 api.remove = function (key, attributes) { 24539 24540 api(key, '', extend(attributes, { 24541 24542 expires: -1 24543 24544 })); 24545 24546 }; 24547 24548 24549 24550 api.withConverter = init; 24551 24552 24553 24554 return api; 24555 24556 } 24557 24558 24559 24560 return init(function () {}); 24561 24562})); 24563 24564 24565/*! 24566 24567 * Masonry PACKAGED v3.3.2 24568 24569 * Cascading grid layout library 24570 24571 * http://masonry.desandro.com 24572 24573 * MIT License 24574 24575 * by David DeSandro 24576 24577 */ 24578 24579 24580 24581!function(a){function b(){}function c(a){function c(b){b.prototype.option||(b.prototype.option=function(b){a.isPlainObject(b)&&(this.options=a.extend(!0,this.options,b))})}function e(b,c){a.fn[b]=function(e){if("string"==typeof e){for(var g=d.c
24581all(arguments,1),h=0,i=this.length;i>h;h++){var j=this[h],k=a.data(j,b);if(k)if(a.isFunction(k[e])&&"_"!==e.charAt(0)){var l=k[e].apply(k,g);if(void 0!==l)return l}else f("no such method '"+e+"' for "+b+" instance");else f("cannot call methods on "+b+" prior to initialization; attempted to call '"+e+"'")}return this}return this.each(function(){var d=a.data(this,b);d?(d.option(e),d._init()):(d=new c(this,e),a.data(this,b,d))})}}if(a){var f="undefined"==typeof console?b:function(a){console.error(a)};return a.bridget=function(a,b){c(b),e(a,b)},a.bridget}}var d=Array.prototype.slice;"function"==typeof define&&define.amd?define("jquery-bridget/jquery.bridget",["jquery"],c):c("object"==typeof exports?require("jquery"):a.jQuery)}(window),function(a){function b(b){var c=a.event;return c.target=c.target||c.srcElement||b,c}var c=document.documentElement,d=function(){};c.addEventListener?d=function(a,b,c){a.addEventListener(b,c,!1)}:c.attachEvent&&(d=function(a,c,d){a[c+d]=d.handleEvent?function(){var c=b(a);d.handleEvent.call(d,c)}:function(){var c=b(a);d.call(a,c)},a.attachEvent("on"+c,a[c+d])});var e=function(){};c.removeEventListener?e=function(a,b,c){a.removeEventListener(b,c,!1)}:c.detachEvent&&(e=function(a,b,c){a.detachEvent("on"+b,a[b+c]);try{delete a[b+c]}catch(d){a[b+c]=void 0}});var f={bind:d,unbind:e};"function"==typeof define&&define.amd?define("eventie/eventie",f):"object"==typeof exports?module.exports=f:a.eventie=f}(window),function(){function a(){}function b(a,b){for(var c=a.length;c--;)if(a[c].listener===b)return c;return-1}function c(a){return function(){return this[a].apply(this,arguments)}}var d=a.prototype,e=this,f=e.EventEmitter;d.getListeners=function(a){var b,c,d=this._getEvents();if(a instanceof RegExp){b={};for(c in d)d.hasOwnProperty(c)&&a.test(c)&&(b[c]=d[c])}else b=d[a]||(d[a]=[]);return b},d.flattenListeners=function(a){var b,c=[];for(b=0;b<a.length;b+=1)c.push(a[b].listener);return c},d.getListenersAsObject=function(a){var b,c=this.getListeners(a);return c instanceof Array&&(b={},b[a]=c),b||c},d.addListener=function(a,c){var d,e=this.getListenersAsObject(a),f="object"==typeof c;for(d in e)e.hasOwnProperty(d)&&-1===b(e[d],c)&&e[d].push(f?c:{listener:c,once:!1});return this},d.on=c("addListener"),d.addOnceListener=function(a,b){return this.addListener(a,{listener:b,once:!0})},d.once=c("addOnceListener"),d.defineEvent=function(a){return this.getListeners(a),this},d.defineEvents=function(a){for(var b=0;b<a.length;b+=1)this.defineEvent(a[b]);return this},d.removeListener=function(a,c){var d,e,f=this.getListenersAsObject(a);for(e in f)f.hasOwnProperty(e)&&(d=b(f[e],c),-1!==d&&f[e].splice(d,1));return this},d.off=c("removeListener"),d.addListeners=function(a,b){return this.manipulateListeners(!1,a,b)},d.removeListeners=function(a,b){return this.manipulateListeners(!0,a,b)},d.manipulateListeners=function(a,b,c){var d,e,f=a?this.removeListener:this.addListener,g=a?this.removeListeners:this.addListeners;if("object"!=typeof b||b instanceof RegExp)for(d=c.length;d--;)f.call(this,b,c[d]);else for(d in b)b.hasOwnProperty(d)&&(e=b[d])&&("function"==typeof e?f.call(this,d,e):g.call(this,d,e));return this},d.removeEvent=function(a){var b,c=typeof a,d=this._getEvents();if("string"===c)delete d[a];else if(a instanceof RegExp)for(b in d)d.hasOwnProperty(b)&&a.test(b)&&delete d[b];else delete this._events;return this},d.removeAllListeners=c("removeEvent"),d.emitEvent=function(a,b){var c,d,e,f,g=this.getListenersAsObject(a);for(e in g)if(g.hasOwnProperty(e))for(d=g[e].length;d--;)c=g[e][d],c.once===!0&&this.removeListener(a,c.listener),f=c.listener.apply(this,b||[]),f===this._getOnceReturnValue()&&this.removeListener(a,c.listener);return this},d.trigger=c("emitEvent"),d.emit=function(a){var b=Array.prototype.slice.call(arguments,1);return this.emitEvent(a,b)},d.setOnceReturnValue=function(a){return this._onceReturnValue=a,this},d._getOnceReturnValue=function(){return this.hasOwnProperty("_onceReturnValue")?this._onceReturnValue:!0},d._getEvents=function(){return this._events||(this._events={})},a.noConflict=function(){return e.EventEmitter=f,a},"function"==typeof define&&define.amd?define("eventEmitter/EventEmitter",[],function(){return a}):"object"==typeof module&&module.exports?module.exports=a:e.EventEmitter=a}.call(this),function(a){function b(a){if(a){if("string"==typeof d[a])return a;a=a.charAt(0).toUpperCase()+a.slice(1);for(var b,e=0,f=c.length;f>e;e++)if(b=c[e]+a,"string"==typeof d[b])return b}}var c="Webkit Moz ms Ms O".split(" "),d=document.documentElement.style;"function"==typeof define&&define.amd?define("get-style-property/get-style-property",[],function(){return b}):"object"==typeof exports?module.exports=b:a.getStyleProperty=b}(window),function(a){function b(a){var b=parseFloat(a),c=-1===a.indexOf("%")&&!isNaN(b);return c&&b}function c(){}function d(){for(var a={width:0,height:0,innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0},b=0,c=g.length;c>b;b++){var d=g[b];a[d]=0}return a}function e(c){function e(){if(!m){m=!0;var d=a.getComputedStyle;if(j=function(){var a=d?function(a){return d(a,null)}:function(a){return a.currentStyle};return function(b){var c=a(b);return c||f("Style returned "+c+". Are you running this code in a hidden iframe on Firefox? See http://bit.ly/getsizebug1"),c}}(),k=c("boxSizing")){var e=document.createElement("div");e.style.width="200px",e.style.padding="1px 2px 3px 4px",e.style.borderStyle="solid",e.style.borderWidth="1px 2px 3px 4px",e.style[k]="border-box";var g=document.body||document.documentElement;g.appendChild(e);var h=j(e);l=200===b(h.width),g.removeChild(e)}}}
24581function h(a){if(e(),"string"==typeof a&&(a=document.querySelector(a)),a&&"object"==typeof a&&a.nodeType){var c=j(a);if("none"===c.display)return d();var f={};f.width=a.offsetWidth,f.height=a.offsetHeight;for(var h=f.isBorderBox=!(!k||!c[k]||"border-box"!==c[k]),m=0,n=g.length;n>m;m++){var o=g[m],p=c[o];p=i(a,p);var q=parseFloat(p);f[o]=isNaN(q)?0:q}var r=f.paddingLeft+f.paddingRight,s=f.paddingTop+f.paddingBottom,t=f.marginLeft+f.marginRight,u=f.marginTop+f.marginBottom,v=f.borderLeftWidth+f.borderRightWidth,w=f.borderTopWidth+f.borderBottomWidth,x=h&&l,y=b(c.width);y!==!1&&(f.width=y+(x?0:r+v));var z=b(c.height);return z!==!1&&(f.height=z+(x?0:s+w)),f.innerWidth=f.width-(r+v),f.innerHeight=f.height-(s+w),f.outerWidth=f.width+t,f.outerHeight=f.height+u,f}}function i(b,c){if(a.getComputedStyle||-1===c.indexOf("%"))return c;var d=b.style,e=d.left,f=b.runtimeStyle,g=f&&f.left;return g&&(f.left=b.currentStyle.left),d.left=c,c=d.pixelLeft,d.left=e,g&&(f.left=g),c}var j,k,l,m=!1;return h}var f="undefined"==typeof console?c:function(a){console.error(a)},g=["paddingLeft","paddingRight","paddingTop","paddingBottom","marginLeft","marginRight","marginTop","marginBottom","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth"];"function"==typeof define&&define.amd?define("get-size/get-size",["get-style-property/get-style-property"],e):"object"==typeof exports?module.exports=e(require("desandro-get-style-property")):a.getSize=e(a.getStyleProperty)}(window),function(a){function b(a){"function"==typeof a&&(b.isReady?a():g.push(a))}function c(a){var c="readystatechange"===a.type&&"complete"!==f.readyState;b.isReady||c||d()}function d(){b.isReady=!0;for(var a=0,c=g.length;c>a;a++){var d=g[a];d()}}function e(e){return"complete"===f.readyState?d():(e.bind(f,"DOMContentLoaded",c),e.bind(f,"readystatechange",c),e.bind(a,"load",c)),b}var f=a.document,g=[];b.isReady=!1,"function"==typeof define&&define.amd?define("doc-ready/doc-ready",["eventie/eventie"],e):"object"==typeof exports?module.exports=e(require("eventie")):a.docReady=e(a.eventie)}(window),function(a){function b(a,b){return a[g](b)}function c(a){if(!a.parentNode){var b=document.createDocumentFragment();b.appendChild(a)}}function d(a,b){c(a);for(var d=a.parentNode.querySelectorAll(b),e=0,f=d.length;f>e;e++)if(d[e]===a)return!0;return!1}function e(a,d){return c(a),b(a,d)}var f,g=function(){if(a.matches)return"matches";if(a.matchesSelector)return"matchesSelector";for(var b=["webkit","moz","ms","o"],c=0,d=b.length;d>c;c++){var e=b[c],f=e+"MatchesSelector";if(a[f])return f}}();if(g){var h=document.createElement("div"),i=b(h,"div");f=i?b:e}else f=d;"function"==typeof define&&define.amd?define("matches-selector/matches-selector",[],function(){return f}):"object"==typeof exports?module.exports=f:window.matchesSelector=f}(Element.prototype),function(a,b){"function"==typeof define&&define.amd?define("fizzy-ui-utils/utils",["doc-ready/doc-ready","matches-selector/matches-selector"],function(c,d){return b(a,c,d)}):"object"==typeof exports?module.exports=b(a,require("doc-ready"),require("desandro-matches-selector")):a.fizzyUIUtils=b(a,a.docReady,a.matchesSelector)}(window,function(a,b,c){var d={};d.extend=function(a,b){for(var c in b)a[c]=b[c];return a},d.modulo=function(a,b){return(a%b+b)%b};var e=Object.prototype.toString;d.isArray=function(a){return"[object Array]"==e.call(a)},d.makeArray=function(a){var b=[];if(d.isArray(a))b=a;else if(a&&"number"==typeof a.length)for(var c=0,e=a.length;e>c;c++)b.push(a[c]);else b.push(a);return b},d.indexOf=Array.prototype.indexOf?function(a,b){return a.indexOf(b)}:function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},d.removeFrom=function(a,b){var c=d.indexOf(a,b);-1!=c&&a.splice(c,1)},d.isElement="function"==typeof HTMLElement||"object"==typeof HTMLElement?function(a){return a instanceof HTMLElement}:function(a){return a&&"object"==typeof a&&1==a.nodeType&&"string"==typeof a.nodeName},d.setText=function(){function a(a,c){b=b||(void 0!==document.documentElement.textContent?"textContent":"innerText"),a[b]=c}var b;return a}(),d.getParent=function(a,b){for(;a!=document.body;)if(a=a.parentNode,c(a,b))return a},d.getQueryElement=function(a){return"string"==typeof a?document.querySelector(a):a},d.handleEvent=function(a){var b="on"+a.type;this[b]&&this[b](a)},d.filterFindElements=function(a,b){a=d.makeArray(a);for(var e=[],f=0,g=a.length;g>f;f++){var h=a[f];if(d.isElement(h))if(b){c(h,b)&&e.push(h);for(var i=h.querySelectorAll(b),j=0,k=i.length;k>j;j++)e.push(i[j])}else e.push(h)}return e},d.debounceMethod=function(a,b,c){var d=a.prototype[b],e=b+"Timeout";a.prototype[b]=function(){var a=this[e];a&&clearTimeout(a);var b=arguments,f=this;this[e]=setTimeout(function(){d.apply(f,b),delete f[e]},c||100)}},d.toDashed=function(a){return a.replace(/(.)([A-Z])/g,function(a,b,c){return b+"-"+c}).toLowerCase()};var f=a.console;return d.htmlInit=function(c,e){b(function(){for(var b=d.toDashed(e),g=document.querySelectorAll(".js-"+b),h="data-"+b+"-options",i=0,j=g.length;j>i;i++){var k,l=g[i],m=l.getAttribute(h);try{k=m&&JSON.parse(m)}catch(n){f&&f.error("Error parsing "+h+" on "+l.nodeName.toLowerCase()+(l.id?"#"+l.id:"")+": "+n);continue}var o=new c(l,k),p=a.jQuery;p&&p.data(l,e,o)}})},d}),function(a,b){"function"==typeof define&&define.amd?define("outlayer/item",["eventEmitter/EventEmitter","get-size/get-size","get-style-property/get-style-property","fizzy-ui-utils/utils"],function(c,d,e,f){return b(a,c,d,e,f)}):"object"==typeof exports?module.exports=b(a,require("wolfy87-eventemitter"),require("get-size"),require("desandro-get-style-property"),require("fizzy-ui-utils")):(a.Outlayer={}
24581,a.Outlayer.Item=b(a,a.EventEmitter,a.getSize,a.getStyleProperty,a.fizzyUIUtils))}(window,function(a,b,c,d,e){function f(a){for(var b in a)return!1;return b=null,!0}function g(a,b){a&&(this.element=a,this.layout=b,this.position={x:0,y:0},this._create())}function h(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}var i=a.getComputedStyle,j=i?function(a){return i(a,null)}:function(a){return a.currentStyle},k=d("transition"),l=d("transform"),m=k&&l,n=!!d("perspective"),o={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"otransitionend",transition:"transitionend"}[k],p=["transform","transition","transitionDuration","transitionProperty"],q=function(){for(var a={},b=0,c=p.length;c>b;b++){var e=p[b],f=d(e);f&&f!==e&&(a[e]=f)}return a}();e.extend(g.prototype,b.prototype),g.prototype._create=function(){this._transn={ingProperties:{},clean:{},onEnd:{}},this.css({position:"absolute"})},g.prototype.handleEvent=function(a){var b="on"+a.type;this[b]&&this[b](a)},g.prototype.getSize=function(){this.size=c(this.element)},g.prototype.css=function(a){var b=this.element.style;for(var c in a){var d=q[c]||c;b[d]=a[c]}},g.prototype.getPosition=function(){var a=j(this.element),b=this.layout.options,c=b.isOriginLeft,d=b.isOriginTop,e=a[c?"left":"right"],f=a[d?"top":"bottom"],g=this.layout.size,h=-1!=e.indexOf("%")?parseFloat(e)/100*g.width:parseInt(e,10),i=-1!=f.indexOf("%")?parseFloat(f)/100*g.height:parseInt(f,10);h=isNaN(h)?0:h,i=isNaN(i)?0:i,h-=c?g.paddingLeft:g.paddingRight,i-=d?g.paddingTop:g.paddingBottom,this.position.x=h,this.position.y=i},g.prototype.layoutPosition=function(){var a=this.layout.size,b=this.layout.options,c={},d=b.isOriginLeft?"paddingLeft":"paddingRight",e=b.isOriginLeft?"left":"right",f=b.isOriginLeft?"right":"left",g=this.position.x+a[d];c[e]=this.getXValue(g),c[f]="";var h=b.isOriginTop?"paddingTop":"paddingBottom",i=b.isOriginTop?"top":"bottom",j=b.isOriginTop?"bottom":"top",k=this.position.y+a[h];c[i]=this.getYValue(k),c[j]="",this.css(c),this.emitEvent("layout",[this])},g.prototype.getXValue=function(a){var b=this.layout.options;return b.percentPosition&&!b.isHorizontal?a/this.layout.size.width*100+"%":a+"px"},g.prototype.getYValue=function(a){var b=this.layout.options;return b.percentPosition&&b.isHorizontal?a/this.layout.size.height*100+"%":a+"px"},g.prototype._transitionTo=function(a,b){this.getPosition();var c=this.position.x,d=this.position.y,e=parseInt(a,10),f=parseInt(b,10),g=e===this.position.x&&f===this.position.y;if(this.setPosition(a,b),g&&!this.isTransitioning)return void this.layoutPosition();var h=a-c,i=b-d,j={};j.transform=this.getTranslate(h,i),this.transition({to:j,onTransitionEnd:{transform:this.layoutPosition},isCleaning:!0})},g.prototype.getTranslate=function(a,b){var c=this.layout.options;return a=c.isOriginLeft?a:-a,b=c.isOriginTop?b:-b,n?"translate3d("+a+"px, "+b+"px, 0)":"translate("+a+"px, "+b+"px)"},g.prototype.goTo=function(a,b){this.setPosition(a,b),this.layoutPosition()},g.prototype.moveTo=m?g.prototype._transitionTo:g.prototype.goTo,g.prototype.setPosition=function(a,b){this.position.x=parseInt(a,10),this.position.y=parseInt(b,10)},g.prototype._nonTransition=function(a){this.css(a.to),a.isCleaning&&this._removeStyles(a.to);for(var b in a.onTransitionEnd)a.onTransitionEnd[b].call(this)},g.prototype._transition=function(a){if(!parseFloat(this.layout.options.transitionDuration))return void this._nonTransition(a);var b=this._transn;for(var c in a.onTransitionEnd)b.onEnd[c]=a.onTransitionEnd[c];for(c in a.to)b.ingProperties[c]=!0,a.isCleaning&&(b.clean[c]=!0);if(a.from){this.css(a.from);var d=this.element.offsetHeight;d=null}this.enableTransition(a.to),this.css(a.to),this.isTransitioning=!0};var r="opacity,"+h(q.transform||"transform");g.prototype.enableTransition=function(){this.isTransitioning||(this.css({transitionProperty:r,transitionDuration:this.layout.options.transitionDuration}),this.element.addEventListener(o,this,!1))},g.prototype.transition=g.prototype[k?"_transition":"_nonTransition"],g.prototype.onwebkitTransitionEnd=function(a){this.ontransitionend(a)},g.prototype.onotransitionend=function(a){this.ontransitionend(a)};var s={"-webkit-transform":"transform","-moz-transform":"transform","-o-transform":"transform"};
24581g.prototype.ontransitionend=function(a){if(a.target===this.element){var b=this._transn,c=s[a.propertyName]||a.propertyName;if(delete b.ingProperties[c],f(b.ingProperties)&&this.disableTransition(),c in b.clean&&(this.element.style[a.propertyName]="",delete b.clean[c]),c in b.onEnd){var d=b.onEnd[c];d.call(this),delete b.onEnd[c]}this.emitEvent("transitionEnd",[this])}},g.prototype.disableTransition=function(){this.removeTransitionStyles(),this.element.removeEventListener(o,this,!1),this.isTransitioning=!1},g.prototype._removeStyles=function(a){var b={};for(var c in a)b[c]="";this.css(b)};var t={transitionProperty:"",transitionDuration:""};return g.prototype.removeTransitionStyles=function(){this.css(t)},g.prototype.removeElem=function(){this.element.parentNode.removeChild(this.element),this.css({display:""}),this.emitEvent("remove",[this])},g.prototype.remove=function(){if(!k||!parseFloat(this.layout.options.transitionDuration))return void this.removeElem();var a=this;this.once("transitionEnd",function(){a.removeElem()}),this.hide()},g.prototype.reveal=function(){delete this.isHidden,this.css({display:""});var a=this.layout.options,b={},c=this.getHideRevealTransitionEndProperty("visibleStyle");b[c]=this.onRevealTransitionEnd,this.transition({from:a.hiddenStyle,to:a.visibleStyle,isCleaning:!0,onTransitionEnd:b})},g.prototype.onRevealTransitionEnd=function(){this.isHidden||this.emitEvent("reveal")},g.prototype.getHideRevealTransitionEndProperty=function(a){var b=this.layout.options[a];if(b.opacity)return"opacity";for(var c in b)return c},g.prototype.hide=function(){this.isHidden=!0,this.css({display:""});var a=this.layout.options,b={},c=this.getHideRevealTransitionEndProperty("hiddenStyle");b[c]=this.onHideTransitionEnd,this.transition({from:a.visibleStyle,to:a.hiddenStyle,isCleaning:!0,onTransitionEnd:b})},g.prototype.onHideTransitionEnd=function(){this.isHidden&&(this.css({display:"none"}),this.emitEvent("hide"))},g.prototype.destroy=function(){this.css({position:"",left:"",right:"",top:"",bottom:"",transition:"",transform:""})},g}),function(a,b){"function"==typeof define&&define.amd?define("outlayer/outlayer",["eventie/eventie","eventEmitter/EventEmitter","get-size/get-size","fizzy-ui-utils/utils","./item"],function(c,d,e,f,g){return b(a,c,d,e,f,g)}):"object"==typeof exports?module.exports=b(a,require("eventie"),require("wolfy87-eventemitter"),require("get-size"),require("fizzy-ui-utils"),require("./item")):a.Outlayer=b(a,a.eventie,a.EventEmitter,a.getSize,a.fizzyUIUtils,a.Outlayer.Item)}(window,function(a,b,c,d,e,f){function g(a,b){var c=e.getQueryElement(a);if(!c)return void(h&&h.error("Bad element for "+this.constructor.namespace+": "+(c||a)));this.element=c,i&&(this.$element=i(this.element)),this.options=e.extend({},this.constructor.defaults),this.option(b);var d=++k;this.element.outlayerGUID=d,l[d]=this,this._create(),this.options.isInitLayout&&this.layout()}var h=a.console,i=a.jQuery,j=function(){},k=0,l={};return g.namespace="outlayer",g.Item=f,g.defaults={containerStyle:{position:"relative"},isInitLayout:!0,isOriginLeft:!0,isOriginTop:!0,isResizeBound:!0,isResizingContainer:!0,transitionDuration:"0.4s",hiddenStyle:{opacity:0,transform:"scale(0.001)"},visibleStyle:{opacity:1,transform:"scale(1)"}},e.extend(g.prototype,c.prototype),g.prototype.option=function(a){e.extend(this.options,a)},g.prototype._create=function(){this.reloadItems(),this.stamps=[],this.stamp(this.options.stamp),e.extend(this.element.style,this.options.containerStyle),this.options.isResizeBound&&this.bindResize()},g.prototype.reloadItems=function(){this.items=this._itemize(this.element.children)},g.prototype._itemize=function(a){for(var b=this._filterFindItemElements(a),c=this.constructor.Item,d=[],e=0,f=b.length;f>e;e++){var g=b[e],h=new c(g,this);d.push(h)}return d},g.prototype._filterFindItemElements=function(a){return e.filterFindElements(a,this.options.itemSelector)},g.prototype.getItemElements=function(){for(var a=[],b=0,c=this.items.length;c>b;b++)a.push(this.items[b].element);return a},g.prototype.layout=function(){this._resetLayout(),this._manageStamps();var a=void 0!==this.options.isLayoutInstant?this.options.isLayoutInstant:!this._isLayoutInited;this.layoutItems(this.items,a),this._isLayoutInited=!0},g.prototype._init=g.prototype.layout,g.prototype._resetLayout=function(){this.get
24581Size()},g.prototype.getSize=function(){this.size=d(this.element)},g.prototype._getMeasurement=function(a,b){var c,f=this.options[a];f?("string"==typeof f?c=this.element.querySelector(f):e.isElement(f)&&(c=f),this[a]=c?d(c)[b]:f):this[a]=0},g.prototype.layoutItems=function(a,b){a=this._getItemsForLayout(a),this._layoutItems(a,b),this._postLayout()},g.prototype._getItemsForLayout=function(a){for(var b=[],c=0,d=a.length;d>c;c++){var e=a[c];e.isIgnored||b.push(e)}return b},g.prototype._layoutItems=function(a,b){if(this._emitCompleteOnItems("layout",a),a&&a.length){for(var c=[],d=0,e=a.length;e>d;d++){var f=a[d],g=this._getItemLayoutPosition(f);g.item=f,g.isInstant=b||f.isLayoutInstant,c.push(g)}this._processLayoutQueue(c)}},g.prototype._getItemLayoutPosition=function(){return{x:0,y:0}},g.prototype._processLayoutQueue=function(a){for(var b=0,c=a.length;c>b;b++){var d=a[b];this._positionItem(d.item,d.x,d.y,d.isInstant)}},g.prototype._positionItem=function(a,b,c,d){d?a.goTo(b,c):a.moveTo(b,c)},g.prototype._postLayout=function(){this.resizeContainer()},g.prototype.resizeContainer=function(){if(this.options.isResizingContainer){var a=this._getContainerSize();a&&(this._setContainerMeasure(a.width,!0),this._setContainerMeasure(a.height,!1))}},g.prototype._getContainerSize=j,g.prototype._setContainerMeasure=function(a,b){if(void 0!==a){var c=this.size;c.isBorderBox&&(a+=b?c.paddingLeft+c.paddingRight+c.borderLeftWidth+c.borderRightWidth:c.paddingBottom+c.paddingTop+c.borderTopWidth+c.borderBottomWidth),a=Math.max(a,0),this.element.style[b?"width":"height"]=a+"px"}},g.prototype._emitCompleteOnItems=function(a,b){function c(){e.dispatchEvent(a+"Complete",null,[b])}function d(){g++,g===f&&c()}var e=this,f=b.length;if(!b||!f)return void c();for(var g=0,h=0,i=b.length;i>h;h++){var j=b[h];j.once(a,d)}},g.prototype.dispatchEvent=function(a,b,c){var d=b?[b].concat(c):c;if(this.emitEvent(a,d),i)if(this.$element=this.$element||i(this.element),b){var e=i.Event(b);e.type=a,this.$element.trigger(e,c)}else this.$element.trigger(a,c)},g.prototype.ignore=function(a){var b=this.getItem(a);b&&(b.isIgnored=!0)},g.prototype.unignore=function(a){var b=this.getItem(a);b&&delete b.isIgnored},g.prototype.stamp=function(a){if(a=this._find(a)){this.stamps=this.stamps.concat(a);for(var b=0,c=a.length;c>b;b++){var d=a[b];this.ignore(d)}}},g.prototype.unstamp=function(a){if(a=this._find(a))for(var b=0,c=a.length;c>b;b++){var d=a[b];e.removeFrom(this.stamps,d),this.unignore(d)}},g.prototype._find=function(a){return a?("string"==typeof a&&(a=this.element.querySelectorAll(a)),a=e.makeArray(a)):void 0},g.prototype._manageStamps=function(){if(this.stamps&&this.stamps.length){this._getBoundingRect();for(var a=0,b=this.stamps.length;b>a;a++){var c=this.stamps[a];this._manageStamp(c)}}},g.prototype._getBoundingRect=function(){var a=this.element.getBoundingClientRect(),b=this.size;this._boundingRect={left:a.left+b.paddingLeft+b.borderLeftWidth,top:a.top+b.paddingTop+b.borderTopWidth,right:a.right-(b.paddingRight+b.borderRightWidth),bottom:a.bottom-(b.paddingBottom+b.borderBottomWidth)}},g.prototype._manageStamp=j,g.prototype._getElementOffset=function(a){var b=a.getBoundingClientRect(),c=this._boundingRect,e=d(a),f={left:b.left-c.left-e.marginLeft,top:b.top-c.top-e.marginTop,right:c.right-b.right-e.marginRight,bottom:c.bottom-b.bottom-e.marginBottom};return f},g.prototype.handleEvent=function(a){var b="on"+a.type;this[b]&&this[b](a)},g.prototype.bindResize=function(){this.isResizeBound||(b.bind(a,"resize",this),this.isResizeBound=!0)},g.prototype.unbindResize=function(){this.isResizeBound&&b.unbind(a,"resize",this),this.isResizeBound=!1},g.prototype.onresize=function(){function a(){b.resize(),delete b.resizeTimeout}this.resizeTimeout&&clearTimeout(this.resizeTimeout);var b=this;this.resizeTimeout=setTimeout(a,100)},g.prototype.resize=function(){this.isResizeBound&&this.needsResizeLayout()&&this.layout()},g.prototype.needsResizeLayout=function(){var a=d(this.element),b=this.size&&a;return b&&a.innerWidth!==this.size.innerWidth},g.prototype.addItems=function(a){var b=this._itemize(a);return b.length&&(this.items=this.items.concat(b)),b},g.prototype.appended=function(a){var b=this.addItems(a);b.length&&(this.layoutItems(b,!0),this.reveal(b))},g.prototype.prepended=function(a){var b=this._itemize(a);if(b.length){var c=this.items.slice(0);this.items=b.concat(c),this._resetLayout(),this._manageStamps(),this.layoutItems(b,!0),this.reveal(b),this.layoutItems(c)}},g.prototype.reveal=function(a){this._emitCompleteOnItems("reveal",a);for(var b=a&&a.length,c=0;b&&b>c;c++){var d=a[c];d.reveal()}},g.prototype.hide=function(a){this._emitCompleteOnItems("hide",a);for(var b=a&&a.length,c=0;b&&b>c;c++){var d=a[c];d.hide()}},g.prototype.revealItemElements=function(a){var b=this.getItems(a);this.reveal(b)},g.prototype.hideItemElements=function(a){var b=this.getItems(a);this.hide(b)},g.prototype.getItem=function(a){for(var b=0,c=this.items.length;c>b;b++){var d=this.items[b];if(d.element===a)return d}},g.prototype.getItems=function(a){a=e.makeArray(a);for(var b=[],c=0,d=a.length;d>c;c++){var f=a[c],g=this.getItem(f);g&&b.push(g)}return b},g.prototype.remove=function(a){var b=this.getItems(a);if(this._emitCompleteOnItems("remove",b),b&&b.length)for(var c=0,d=b.length;d>c;c++){var f=b[c];f.remove(),e.removeFrom(this.items,f)}},g.prototype.destroy=function(){var a=this.element.style;a.height="",a.position="",a.width="";for(var b=0,c=this.items.length;c>b;b++){var d=this.items[b];d.destroy()}this.unbindResize();var e=this.element.outlayerGUID;delete l[e],delete this.element.outlayerGUID,i&&i.removeData(this.element,this.constructor.namespace)},g.data=function(a){a=e.getQueryElement(a);var b=a&&a.outlayerGUID;return b&&l[b]}
24581,g.create=function(a,b){function c(){g.apply(this,arguments)}return Object.create?c.prototype=Object.create(g.prototype):e.extend(c.prototype,g.prototype),c.prototype.constructor=c,c.defaults=e.extend({},g.defaults),e.extend(c.defaults,b),c.prototype.settings={},c.namespace=a,c.data=g.data,c.Item=function(){f.apply(this,arguments)},c.Item.prototype=new f,e.htmlInit(c,a),i&&i.bridget&&i.bridget(a,c),c},g.Item=f,g}),function(a,b){"function"==typeof define&&define.amd?define(["outlayer/outlayer","get-size/get-size","fizzy-ui-utils/utils"],b):"object"==typeof exports?module.exports=b(require("outlayer"),require("get-size"),require("fizzy-ui-utils")):a.Masonry=b(a.Outlayer,a.getSize,a.fizzyUIUtils)}(window,function(a,b,c){var d=a.create("masonry");return d.prototype._resetLayout=function(){this.getSize(),this._getMeasurement("columnWidth","outerWidth"),this._getMeasurement("gutter","outerWidth"),this.measureColumns();var a=this.cols;for(this.colYs=[];a--;)this.colYs.push(0);this.maxY=0},d.prototype.measureColumns=function(){if(this.getContainerWidth(),!this.columnWidth){var a=this.items[0],c=a&&a.element;this.columnWidth=c&&b(c).outerWidth||this.containerWidth}var d=this.columnWidth+=this.gutter,e=this.containerWidth+this.gutter,f=e/d,g=d-e%d,h=g&&1>g?"round":"floor";f=Math[h](f),this.cols=Math.max(f,1)},d.prototype.getContainerWidth=function(){var a=this.options.isFitWidth?this.element.parentNode:this.element,c=b(a);this.containerWidth=c&&c.innerWidth},d.prototype._getItemLayoutPosition=function(a){a.getSize();var b=a.size.outerWidth%this.columnWidth,d=b&&1>b?"round":"ceil",e=Math[d](a.size.outerWidth/this.columnWidth);e=Math.min(e,this.cols);for(var f=this._getColGroup(e),g=Math.min.apply(Math,f),h=c.indexOf(f,g),i={x:this.columnWidth*h,y:g},j=g+a.size.outerHeight,k=this.cols+1-f.length,l=0;k>l;l++)this.colYs[h+l]=j;return i},d.prototype._getColGroup=function(a){if(2>a)return this.colYs;for(var b=[],c=this.cols+1-a,d=0;c>d;d++){var e=this.colYs.slice(d,d+a);b[d]=Math.max.apply(Math,e)}return b},d.prototype._manageStamp=function(a){var c=b(a),d=this._getElementOffset(a),e=this.options.isOriginLeft?d.left:d.right,f=e+c.outerWidth,g=Math.floor(e/this.columnWidth);g=Math.max(0,g);var h=Math.floor(f/this.columnWidth);h-=f%this.columnWidth?0:1,h=Math.min(this.cols-1,h);for(var i=(this.options.isOriginTop?d.top:d.bottom)+c.outerHeight,j=g;h>=j;j++)this.colYs[j]=Math.max(i,this.colYs[j])},d.prototype._getContainerSize=function(){this.maxY=Math.max.apply(Math,this.colYs);var a={height:this.maxY};return this.options.isFitWidth&&(a.width=this._getContainerFitWidth()),a},d.prototype._getContainerFitWidth=function(){for(var a=0,b=this.cols;--b&&0===this.colYs[b];)a++;return(this.cols-a)*this.columnWidth-this.gutter},d.prototype.needsResizeLayout=function(){var a=this.containerWidth;return this.getContainerWidth(),a!==this.containerWidth},d}); 24582/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress 24583 24584 * @license MIT */ 24585 24586 24587 24588;(function(root, factory) { 24589 24590 24591 24592 if (typeof define === 'function' && define.amd) { 24593 24594 define(factory); 24595 24596 } else if (typeof exports === 'object') { 24597 24598 module.exports = factory(); 24599 24600 } else { 24601 24602 root.NProgress = factory(); 24603 24604 } 24605 24606 24607 24608})(this, function() { 24609 24610 var NProgress = {}; 24611 24612 24613 24614 NProgress.version = '0.2.0'; 24615 24616 24617 24618 var Settings = NProgress.settings = { 24619 24620 minimum: 0.08, 24621 24622 easing: 'ease', 24623 24624 positionUsing: '', 24625 24626 speed: 200, 24627 24628 trickle: true, 24629 24630 trickleRate: 0.02, 24631 24632 trickleSpeed: 800, 24633 24634 showSpinner: true, 24635 24636 barSelector: '[role="bar"]', 24637 24638 spinnerSelector: '[role="spinner"]', 24639 24640 parent: 'body', 24641 24642 template: '<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>' 24643 24644 }; 24645 24646 24647 24648 /** 24649 24650 * Updates configuration. 24651 24652 * 24653 24654 * NProgress.configure({ 24655 24656 * minimum: 0.1 24657 24658 * }); 24659 24660 */ 24661 24662 NProgress.configure = function(options) { 24663 24664 var key, value; 24665 24666 for (key in options) { 24667 24668 value = options[key]; 24669 24670 if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value; 24671 24672 } 24673 24674 24675 24676 return this; 24677 24678 }; 24679 24680 24681 24682 /** 24683 24684 * Last number. 24685 24686 */ 24687 24688 24689 24690 NProgress.status = null; 24691 24692 24693 24694 /** 24695
vendor: 9,088 bytes, lines 24696-25401
24696 * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`. 24697 24698 * 24699 24700 * NProgress.set(0.4); 24701 24702 * NProgress.set(1.0); 24703 24704 */ 24705 24706 24707 24708 NProgress.set = function(n) { 24709 24710 var started = NProgress.isStarted(); 24711 24712 24713 24714 n = clamp(n, Settings.minimum, 1); 24715 24716 NProgress.status = (n === 1 ? null : n); 24717 24718 24719 24720 var progress = NProgress.render(!started), 24721 24722 bar = progress.querySelector(Settings.barSelector), 24723 24724 speed = Settings.speed, 24725 24726 ease = Settings.easing; 24727 24728 24729 24730 progress.offsetWidth; /* Repaint */ 24731 24732 24733 24734 queue(function(next) { 24735 24736 // Set positionUsing if it hasn't already been set 24737 24738 if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS(); 24739 24740 24741 24742 // Add transition 24743 24744 css(bar, barPositionCSS(n, speed, ease)); 24745 24746 24747 24748 if (n === 1) { 24749 24750 // Fade out 24751 24752 css(progress, { 24753 24754 transition: 'none', 24755 24756 opacity: 1 24757 24758 }); 24759 24760 progress.offsetWidth; /* Repaint */ 24761 24762 24763 24764 setTimeout(function() { 24765 24766 css(progress, { 24767 24768 transition: 'all ' + speed + 'ms linear', 24769 24770 opacity: 0 24771 24772 }); 24773 24774 setTimeout(function() { 24775 24776 NProgress.remove(); 24777 24778 next(); 24779 24780 }, speed); 24781 24782 }, speed); 24783 24784 } else { 24785 24786 setTimeout(next, speed); 24787 24788 } 24789 24790 }); 24791 24792 24793 24794 return this; 24795 24796 }; 24797 24798 24799 24800 NProgress.isStarted = function() { 24801 24802 return typeof NProgress.status === 'number'; 24803 24804 }; 24805 24806 24807 24808 /** 24809 24810 * Shows the progress bar. 24811 24812 * This is the same as setting the status to 0%, except that it doesn't go backwards. 24813 24814 * 24815 24816 * NProgress.start(); 24817 24818 * 24819 24820 */ 24821 24822 NProgress.start = function() { 24823 24824 if (!NProgress.status) NProgress.set(0); 24825 24826 24827 24828 var work = function() { 24829 24830 setTimeout(function() { 24831 24832 if (!NProgress.status) return; 24833 24834 NProgress.trickle(); 24835 24836 work(); 24837 24838 }, Settings.trickleSpeed); 24839 24840 }; 24841 24842 24843 24844 if (Settings.trickle) work(); 24845 24846 24847 24848 return this; 24849 24850 }; 24851 24852 24853 24854 /** 24855 24856 * Hides the progress bar. 24857 24858 * This is the *sort of* the same as setting the status to 100%, with the 24859 24860 * difference being `done()` makes some placebo effect of some realistic motion. 24861 24862 * 24863 24864 * NProgress.done(); 24865 24866 * 24867 24868 * If `true` is passed, it will show the progress bar even if its hidden. 24869 24870 * 24871 24872 * NProgress.done(true); 24873 24874 */ 24875 24876 24877 24878 NProgress.done = function(force) { 24879 24880 if (!force && !NProgress.status) return this; 24881 24882 24883 24884 return NProgress.inc(0.3 + 0.5 * Math.random()).set(1); 24885 24886 }; 24887 24888 24889 24890 /** 24891 24892 * Increments by a random amount. 24893 24894 */ 24895 24896 24897 24898 NProgress.inc = function(amount) { 24899 24900 var n = NProgress.status; 24901 24902 24903 24904 if (!n) { 24905 24906 return NProgress.start(); 24907 24908 } else { 24909 24910 if (typeof amount !== 'number') { 24911 24912 amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95); 24913 24914 } 24915 24916 24917 24918 n = clamp(n + amount, 0, 0.994); 24919 24920 return NProgress.set(n); 24921 24922 } 24923 24924 }; 24925 24926 24927 24928 NProgress.trickle = function() { 24929 24930 return NProgress.inc(Math.random() * Settings.trickleRate); 24931 24932 }; 24933 24934 24935 24936 /** 24937 24938 * Waits for all supplied jQuery promises and 24939 24940 * increases the progress as the promises resolve. 24941 24942 * 24943 24944 * @param $promise jQUery Promise 24945 24946 */ 24947 24948 (function() { 24949 24950 var initial = 0, current = 0; 24951 24952 24953 24954 NProgress.promise = function($promise) { 24955 24956 if (!$promise || $promise.state() === "resolved") { 24957 24958 return this; 24959 24960 } 24961 24962 24963 24964 if (current === 0) { 24965 24966 NProgress.start(); 24967 24968 } 24969 24970 24971 24972 initial++; 24973 24974 current++; 24975 24976 24977 24978 $promise.always(function() { 24979 24980 current--; 24981 24982 if (current === 0) { 24983 24984 initial = 0; 24985 24986 NProgress.done(); 24987 24988 } else { 24989 24990 NProgress.set((initial - current) / initial); 24991 24992 } 24993 24994 }); 24995 24996 24997 24998 return this; 24999 25000 }; 25001 25002 25003 25004 })(); 25005 25006 25007 25008 /** 25009 25010 * (Internal) renders the progress bar markup based on the `template` 25011 25012 * setting. 25013 25014 */ 25015 25016 25017 25018 NProgress.render = function(fromStart) { 25019 25020 if (NProgress.isRendered()) return document.getElementById('nprogress'); 25021 25022 25023 25024 addClass(document.documentElement, 'nprogress-busy'); 25025 25026 25027 25028 var progress = document.createElement('div'); 25029 25030 progress.id = 'nprogress'; 25031 25032 progress.innerHTML = Settings.template; 25033 25034 25035 25036 var bar = progress.querySelector(Settings.barSelector), 25037 25038 perc = fromStart ? '-100' : toBarPerc(NProgress.status || 0), 25039 25040 parent = document.querySelector(Settings.parent), 25041 25042 spinner; 25043 25044 25045 25046 css(bar, { 25047 25048 transition: 'all 0 linear', 25049 25050 transform: 'translate3d(' + perc + '%,0,0)' 25051 25052 }); 25053 25054 25055 25056 if (!Settings.showSpinner) { 25057 25058 spinner = progress.querySelector(Settings.spinnerSelector); 25059 25060 spinner && removeElement(spinner); 25061 25062 } 25063 25064 25065 25066 if (parent != document.body) { 25067 25068 addClass(parent, 'nprogress-custom-parent'); 25069 25070 } 25071 25072 25073 25074 parent.appendChild(progress); 25075 25076 return progress; 25077 25078 }; 25079 25080 25081 25082 /** 25083 25084 * Removes the element. Opposite of render(). 25085 25086 */ 25087 25088 25089 25090 NProgress.remove = function() { 25091 25092 removeClass(document.documentElement, 'nprogress-busy'); 25093 25094 removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent'); 25095 25096 var progress = document.getElementById('nprogress'); 25097 25098 progress && removeElement(progress); 25099 25100 }; 25101 25102 25103 25104 /** 25105 25106 * Checks if the progress bar is rendered. 25107 25108 */ 25109 25110 25111 25112 NProgress.isRendered = function() { 25113 25114 return !!document.getElementById('nprogress'); 25115 25116 }; 25117 25118 25119 25120 /** 25121 25122 * Determine which positioning CSS rule to use. 25123 25124 */ 25125 25126 25127 25128 NProgress.getPositioningCSS = function() { 25129 25130 // Sniff on document.body.style 25131 25132 var bodyStyle = document.body.style; 25133 25134 25135 25136 // Sniff prefixes 25137 25138 var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' : 25139 25140 ('MozTransform' in bodyStyle) ? 'Moz' : 25141 25142 ('msTransform' in bodyStyle) ? 'ms' : 25143 25144 ('OTransform' in bodyStyle) ? 'O' : ''; 25145 25146 25147 25148 if (vendorPrefix + 'Perspective' in bodyStyle) { 25149 25150 // Modern browsers with 3D support, e.g. Webkit, IE10 25151 25152 return 'translate3d'; 25153 25154 } else if (vendorPrefix + 'Transform' in bodyStyle) { 25155 25156 // Browsers without 3D support, e.g. IE9 25157 25158 return 'translate'; 25159 25160 } else { 25161 25162 // Browsers without translate() support, e.g. IE7-8 25163 25164 return 'margin'; 25165 25166 } 25167 25168 }; 25169 25170 25171 25172 /** 25173 25174 * Helpers 25175 25176 */ 25177 25178 25179 25180 function clamp(n, min, max) { 25181 25182 if (n < min) return min; 25183 25184 if (n > max) return max; 25185 25186 return n; 25187 25188 } 25189 25190 25191 25192 /** 25193 25194 * (Internal) converts a percentage (`0..1`) to a bar translateX 25195 25196 * percentage (`-100%..0%`). 25197 25198 */ 25199 25200 25201 25202 function toBarPerc(n) { 25203 25204 return (-1 + n) * 100; 25205 25206 } 25207 25208 25209 25210 25211 25212 /** 25213 25214 * (Internal) returns the correct CSS for changing the bar's 25215 25216 * position given an n percentage, and speed and ease from Settings 25217 25218 */ 25219 25220 25221 25222 function barPositionCSS(n, speed, ease) { 25223 25224 var barCSS; 25225 25226 25227 25228 if (Settings.positionUsing === 'translate3d') { 25229 25230 barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' }; 25231 25232 } else if (Settings.positionUsing === 'translate') { 25233 25234 barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' }; 25235 25236 } else { 25237 25238 barCSS = { 'margin-left': toBarPerc(n)+'%' }; 25239 25240 } 25241 25242 25243 25244 barCSS.transition = 'all '+speed+'ms '+ease; 25245 25246 25247 25248 return barCSS; 25249 25250 } 25251 25252 25253 25254 /** 25255 25256 * (Internal) Queues a function to be executed. 25257 25258 */ 25259 25260 25261 25262 var queue = (function() { 25263 25264 var pending = []; 25265 25266 25267 25268 function next() { 25269 25270 var fn = pending.shift(); 25271 25272 if (fn) { 25273 25274 fn(next); 25275 25276 } 25277 25278 } 25279 25280 25281 25282 return function(fn) { 25283 25284 pending.push(fn); 25285 25286 if (pending.length == 1) next(); 25287 25288 }; 25289 25290 })(); 25291 25292 25293 25294 /** 25295 25296 * (Internal) Applies css properties to an element, similar to the jQuery 25297 25298 * css method. 25299 25300 * 25301 25302 * While this helper does assist with vendor prefixed property names, it 25303 25304 * does not perform any manipulation of values prior to setting styles. 25305 25306 */ 25307 25308 25309 25310 var css = (function() { 25311 25312 var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ], 25313 25314 cssProps = {}; 25315 25316 25317 25318 function camelCase(string) { 25319 25320 return string.replace(/^-ms-/, 'ms-').replace(/-([\da-z])/gi, function(match, letter) { 25321 25322 return letter.toUpperCase(); 25323 25324 }); 25325 25326 } 25327 25328 25329 25330 function getVendorProp(name) { 25331 25332 var style = document.body.style; 25333 25334 if (name in style) return name; 25335 25336 25337 25338 var i = cssPrefixes.length, 25339 25340 capName = name.charAt(0).toUpperCase() + name.slice(1), 25341 25342 vendorName; 25343 25344 while (i--) { 25345 25346 vendorName = cssPrefixes[i] + capName; 25347 25348 if (vendorName in style) return vendorName; 25349 25350 } 25351 25352 25353 25354 return name; 25355 25356 } 25357 25358 25359 25360 function getStyleProp(name) { 25361 25362 name = camelCase(name); 25363 25364 return cssProps[name] || (cssProps[name] = getVendorProp(name)); 25365 25366 } 25367 25368 25369 25370 function applyCss(element, prop, value) { 25371 25372 prop = getStyleProp(prop); 25373 25374 element.style[prop] = value; 25375 25376 } 25377 25378 25379 25380 return function(element, properties) { 25381 25382 var args = arguments, 25383 25384 prop, 25385 25386 value; 25387 25388 25389 25390 if (args.length == 2) { 25391 25392 for (prop in properties) { 25393 25394 value = properties[prop]; 25395 25396 if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value); 25397 25398 } 25399 25400 } else { 25401
25402 applyCss(element, args[1], args[2]); 25403 25404 } 25405 25406 } 25407 25408 })(); 25409 25410 25411 25412 /** 25413 25414 * (Internal) Determines if an element or space separated list of class names contains a class name. 25415 25416 */ 25417 25418 25419 25420 function hasClass(element, name) { 25421 25422 var list = typeof element == 'string' ? element : classList(element); 25423 25424 return list.indexOf(' ' + name + ' ') >= 0; 25425 25426 } 25427 25428 25429 25430 /** 25431 25432 * (Internal) Adds a class to an element. 25433 25434 */ 25435 25436 25437 25438 function addClass(element, name) { 25439 25440 var oldList = classList(element), 25441 25442 newList = oldList + name; 25443 25444 25445 25446 if (hasClass(oldList, name)) return; 25447 25448 25449 25450 // Trim the opening space. 25451 25452 element.className = newList.substring(1); 25453 25454 } 25455 25456 25457 25458 /** 25459 25460 * (Internal) Removes a class from an element. 25461 25462 */ 25463 25464 25465 25466 function removeClass(element, name) { 25467 25468 var oldList = classList(element), 25469 25470 newList; 25471 25472 25473 25474 if (!hasClass(element, name)) return; 25475 25476 25477 25478 // Replace the class name. 25479 25480 newList = oldList.replace(' ' + name + ' ', ' '); 25481 25482 25483 25484 // Trim the opening and closing spaces. 25485 25486 element.className = newList.substring(1, newList.length - 1); 25487 25488 } 25489 25490 25491 25492 /** 25493 25494 * (Internal) Gets a space separated list of the class names on the element. 25495 25496 * The list is wrapped with a single space on each end to facilitate finding 25497 25498 * matches within the list. 25499 25500 */ 25501 25502 25503 25504 function classList(element) { 25505 25506 return (' ' + (element.className || '') + ' ').replace(/\s+/gi, ' '); 25507 25508 } 25509 25510 25511 25512 /** 25513 25514 * (Internal) Removes an element from the DOM. 25515 25516 */ 25517 25518 25519 25520 function removeElement(element) { 25521 25522 element && element.parentNode && element.parentNode.removeChild(element); 25523 25524 } 25525 25526 25527 25528 return NProgress; 25529 25530}); 25531 25532 25533 25534 25535/* 25536 25537 _ _ _ _ 25538 25539 ___| (_) ___| | __ (_)___ 25540 25541/ __| | |/ __| |/ / | / __| 25542 25543\__ \ | | (__| < _ | \__ \ 25544 25545|___/_|_|\___|_|\_(_)/ |___/ 25546 25547 |__/ 25548 25549 25550 25551 Version: 1.8.0 25552 25553 Author: Ken Wheeler 25554 25555 Website: http://kenwheeler.github.io 25556 25557 Docs: http://kenwheeler.github.io/slick 25558 25559 Repo: http://github.com/kenwheeler/slick 25560 25561 Issues: http://github.com/kenwheeler/slick/issues 25562 25563 25564 25565 */ 25566 25567/* global window, document, define, jQuery, setInterval, clearInterval */ 25568 25569;(function(factory) { 25570 25571 'use strict'; 25572 25573 if (typeof define === 'function' && define.amd) { 25574 25575 define(['jquery'], factory); 25576 25577 } else if (typeof exports !== 'undefined') { 25578 25579 module.exports = factory(require('jquery')); 25580 25581 } else { 25582 25583 factory(jQuery); 25584 25585 } 25586 25587 25588 25589}(function($) { 25590 25591 'use strict'; 25592 25593 var Slick = window.Slick || {}; 25594 25595 25596 25597 Slick = (function() { 25598 25599 25600 25601 var instanceUid = 0; 25602 25603 25604 25605 function Slick(element, settings) { 25606 25607 25608 25609 var _ = this, dataSettings; 25610 25611 25612 25613 _.defaults = { 25614 25615 accessibility: true, 25616 25617 adaptiveHeight: false, 25618 25619 appendArrows: $(element), 25620 25621 appendDots: $(element), 25622 25623 arrows: true, 25624 25625 asNavFor: null, 25626 25627 prevArrow: '<button class="slick-prev" aria-label="Previous" type="button">Previous</button>', 25628 25629 nextArrow: '<button class="slick-next" aria-label="Next" type="button">Next</button>', 25630 25631 autoplay: false, 25632 25633 autoplaySpeed: 3000, 25634 25635 centerMode: false, 25636 25637 centerPadding: '50px', 25638 25639 cssEase: 'ease', 25640 25641 customPaging: function(slider, i) { 25642 25643 return $('<button type="button" />').text(i + 1); 25644 25645 }, 25646 25647 dots: false, 25648 25649 dotsClass: 'slick-dots', 25650 25651 draggable: true, 25652 25653 easing: 'linear', 25654 25655 edgeFriction: 0.35, 25656 25657 fade: false, 25658 25659 focusOnSelect: false, 25660 25661 focusOnChange: false, 25662 25663 infinite: true, 25664 25665 initialSlide: 0, 25666 25667 lazyLoad: 'ondemand', 25668 25669 mobileFirst: false, 25670 25671 pauseOnHover: true, 25672 25673 pauseOnFocus: true, 25674 25675 pauseOnDotsHover: false, 25676 25677 respondTo: 'window', 25678 25679 responsive: null, 25680 25681 rows: 1, 25682 25683 rtl: false, 25684 25685 slide: '', 25686 25687 slidesPerRow: 1, 25688 25689 slidesToShow: 1, 25690 25691 slidesToScroll: 1, 25692 25693 speed: 500, 25694 25695 swipe: true, 25696 25697 swipeToSlide: false, 25698 25699 touchMove: true, 25700 25701 touchThreshold: 5, 25702 25703 useCSS: true, 25704 25705 useTransform: true, 25706 25707 variableWidth: false, 25708 25709 vertical: false, 25710 25711 verticalSwiping: false, 25712 25713 waitForAnimate: true, 25714 25715 zIndex: 1000 25716 25717 }; 25718 25719 25720 25721 _.initials = { 25722 25723 animating: false, 25724 25725 dragging: false, 25726 25727 autoPlayTimer: null, 25728 25729 currentDirection: 0, 25730 25731 currentLeft: null, 25732 25733 currentSlide: 0, 25734 25735 direction: 1, 25736 25737 $dots: null, 25738 25739 listWidth: null, 25740 25741 listHeight: null, 25742 25743 loadIndex: 0, 25744 25745 $nextArrow: null, 25746 25747 $prevArrow: null, 25748 25749 scrolling: false, 25750 25751 slideCount: null, 25752 25753 slideWidth: null, 25754 25755 $slideTrack: null, 25756 25757 $slides: null, 25758 25759 sliding: false, 25760 25761 slideOffset: 0, 25762 25763 swipeLeft: null, 25764 25765 swiping: false, 25766 25767 $list: null, 25768 25769 touchObject: {}, 25770 25771 transformsEnabled: false, 25772
vendor: 83,404 bytes, lines 25773-31199
25773 unslicked: false 25774 25775 }; 25776 25777 25778 25779 $.extend(_, _.initials); 25780 25781 25782 25783 _.activeBreakpoint = null; 25784 25785 _.animType = null; 25786 25787 _.animProp = null; 25788 25789 _.breakpoints = []; 25790 25791 _.breakpointSettings = []; 25792 25793 _.cssTransitions = false; 25794 25795 _.focussed = false; 25796 25797 _.interrupted = false; 25798 25799 _.hidden = 'hidden'; 25800 25801 _.paused = true; 25802 25803 _.positionProp = null; 25804 25805 _.respondTo = null; 25806 25807 _.rowCount = 1; 25808 25809 _.shouldClick = true; 25810 25811 _.$slider = $(element); 25812 25813 _.$slidesCache = null; 25814 25815 _.transformType = null; 25816 25817 _.transitionType = null; 25818 25819 _.visibilityChange = 'visibilitychange'; 25820 25821 _.windowWidth = 0; 25822 25823 _.windowTimer = null; 25824 25825 25826 25827 dataSettings = $(element).data('slick') || {}; 25828 25829 25830 25831 _.options = $.extend({}, _.defaults, settings, dataSettings); 25832 25833 25834 25835 _.currentSlide = _.options.initialSlide; 25836 25837 25838 25839 _.originalSettings = _.options; 25840 25841 25842 25843 if (typeof document.mozHidden !== 'undefined') { 25844 25845 _.hidden = 'mozHidden'; 25846 25847 _.visibilityChange = 'mozvisibilitychange'; 25848 25849 } else if (typeof document.webkitHidden !== 'undefined') { 25850 25851 _.hidden = 'webkitHidden'; 25852 25853 _.visibilityChange = 'webkitvisibilitychange'; 25854 25855 } 25856 25857 25858 25859 _.autoPlay = $.proxy(_.autoPlay, _); 25860 25861 _.autoPlayClear = $.proxy(_.autoPlayClear, _); 25862 25863 _.autoPlayIterator = $.proxy(_.autoPlayIterator, _); 25864 25865 _.changeSlide = $.proxy(_.changeSlide, _); 25866 25867 _.clickHandler = $.proxy(_.clickHandler, _); 25868 25869 _.selectHandler = $.proxy(_.selectHandler, _); 25870 25871 _.setPosition = $.proxy(_.setPosition, _); 25872 25873 _.swipeHandler = $.proxy(_.swipeHandler, _); 25874 25875 _.dragHandler = $.proxy(_.dragHandler, _); 25876 25877 _.keyHandler = $.proxy(_.keyHandler, _); 25878 25879 25880 25881 _.instanceUid = instanceUid++; 25882 25883 25884 25885 // A simple way to check for HTML strings 25886 25887 // Strict HTML recognition (must start with <) 25888 25889 // Extracted from jQuery v1.11 source 25890 25891 _.htmlExpr = /^(?:\s*(<[\w\W]+>)[^>]*)$/; 25892 25893 25894 25895 25896 25897 _.registerBreakpoints(); 25898 25899 _.init(true); 25900 25901 25902 25903 } 25904 25905 25906 25907 return Slick; 25908 25909 25910 25911 }()); 25912 25913 25914 25915 Slick.prototype.activateADA = function() { 25916 25917 var _ = this; 25918 25919 25920 25921 _.$slideTrack.find('.slick-active').attr({ 25922 25923 'aria-hidden': 'false' 25924 25925 }).find('a, input, button, select').attr({ 25926 25927 'tabindex': '0' 25928 25929 }); 25930 25931 25932 25933 }; 25934 25935 25936 25937 Slick.prototype.addSlide = Slick.prototype.slickAdd = function(markup, index, addBefore) { 25938 25939 25940 25941 var _ = this; 25942 25943 25944 25945 if (typeof(index) === 'boolean') { 25946 25947 addBefore = index; 25948 25949 index = null; 25950 25951 } else if (index < 0 || (index >= _.slideCount)) { 25952 25953 return false; 25954 25955 } 25956 25957 25958 25959 _.unload(); 25960 25961 25962 25963 if (typeof(index) === 'number') { 25964 25965 if (index === 0 && _.$slides.length === 0) { 25966 25967 $(markup).appendTo(_.$slideTrack); 25968 25969 } else if (addBefore) { 25970 25971 $(markup).insertBefore(_.$slides.eq(index)); 25972 25973 } else { 25974 25975 $(markup).insertAfter(_.$slides.eq(index)); 25976 25977 } 25978 25979 } else { 25980 25981 if (addBefore === true) { 25982 25983 $(markup).prependTo(_.$slideTrack); 25984 25985 } else { 25986 25987 $(markup).appendTo(_.$slideTrack); 25988 25989 } 25990 25991 } 25992 25993 25994 25995 _.$slides = _.$slideTrack.children(this.options.slide); 25996 25997 25998 25999 _.$slideTrack.children(this.options.slide).detach(); 26000 26001 26002 26003 _.$slideTrack.append(_.$slides); 26004 26005 26006 26007 _.$slides.each(function(index, element) { 26008 26009 $(element).attr('data-slick-index', index); 26010 26011 }); 26012 26013 26014 26015 _.$slidesCache = _.$slides; 26016 26017 26018 26019 _.reinit(); 26020 26021 26022 26023 }; 26024 26025 26026 26027 Slick.prototype.animateHeight = function() { 26028 26029 var _ = this; 26030 26031 if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) { 26032 26033 var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true); 26034 26035 _.$list.animate({ 26036 26037 height: targetHeight 26038 26039 }, _.options.speed); 26040 26041 } 26042 26043 }; 26044 26045 26046 26047 Slick.prototype.animateSlide = function(targetLeft, callback) { 26048 26049 26050 26051 var animProps = {}, 26052 26053 _ = this; 26054 26055 26056 26057 _.animateHeight(); 26058 26059 26060 26061 if (_.options.rtl === true && _.options.vertical === false) { 26062 26063 targetLeft = -targetLeft; 26064 26065 } 26066 26067 if (_.transformsEnabled === false) { 26068 26069 if (_.options.vertical === false) { 26070 26071 _.$slideTrack.animate({ 26072 26073 left: targetLeft 26074 26075 }, _.options.speed, _.options.easing, callback); 26076 26077 } else { 26078 26079 _.$slideTrack.animate({ 26080 26081 top: targetLeft 26082 26083 }, _.options.speed, _.options.easing, callback); 26084 26085 } 26086 26087 26088 26089 } else { 26090 26091 26092 26093 if (_.cssTransitions === false) { 26094 26095 if (_.options.rtl === true) { 26096 26097 _.currentLeft = -(_.currentLeft); 26098 26099 } 26100 26101 $({ 26102 26103 animStart: _.currentLeft 26104 26105 }).animate({ 26106 26107 animStart: targetLeft 26108 26109 }, { 26110 26111 duration: _.options.speed, 26112 26113 easing: _.options.easing, 26114 26115 step: function(now) { 26116 26117 now = Math.ceil(now); 26118 26119 if (_.options.vertical === false) { 26120 26121 animProps[_.animType] = 'translate(' + 26122 26123 now + 'px, 0px)'; 26124 26125 _.$slideTrack.css(animProps); 26126 26127 } else { 26128 26129 animProps[_.animType] = 'translate(0px,' + 26130 26131 now + 'px)'; 26132 26133 _.$slideTrack.css(animProps); 26134 26135 } 26136 26137 }, 26138 26139 complete: function() { 26140 26141 if (callback) { 26142 26143 callback.call(); 26144 26145 } 26146 26147 } 26148 26149 }); 26150 26151 26152 26153 } else { 26154 26155 26156 26157 _.applyTransition(); 26158 26159 targetLeft = Math.ceil(targetLeft); 26160 26161 26162 26163 if (_.options.vertical === false) { 26164 26165 animProps[_.animType] = 'translate3d(' + targetLeft + 'px, 0px, 0px)'; 26166 26167 } else { 26168 26169 animProps[_.animType] = 'translate3d(0px,' + targetLeft + 'px, 0px)'; 26170 26171 } 26172 26173 _.$slideTrack.css(animProps); 26174 26175 26176 26177 if (callback) { 26178 26179 setTimeout(function() { 26180 26181 26182 26183 _.disableTransition(); 26184 26185 26186 26187 callback.call(); 26188 26189 }, _.options.speed); 26190 26191 } 26192 26193 26194 26195 } 26196 26197 26198 26199 } 26200 26201 26202 26203 }; 26204 26205 26206 26207 Slick.prototype.getNavTarget = function() { 26208 26209 26210 26211 var _ = this, 26212 26213 asNavFor = _.options.asNavFor; 26214 26215 26216 26217 if ( asNavFor && asNavFor !== null ) { 26218 26219 asNavFor = $(asNavFor).not(_.$slider); 26220 26221 } 26222 26223 26224 26225 return asNavFor; 26226 26227 26228 26229 }; 26230 26231 26232 26233 Slick.prototype.asNavFor = function(index) { 26234 26235 26236 26237 var _ = this, 26238 26239 asNavFor = _.getNavTarget(); 26240 26241 26242 26243 if ( asNavFor !== null && typeof asNavFor === 'object' ) { 26244 26245 asNavFor.each(function() { 26246 26247 var target = $(this).slick('getSlick'); 26248 26249 if(!target.unslicked) { 26250 26251 target.slideHandler(index, true); 26252 26253 } 26254 26255 }); 26256 26257 } 26258 26259 26260 26261 }; 26262 26263 26264 26265 Slick.prototype.applyTransition = function(slide) { 26266 26267 26268 26269 var _ = this, 26270 26271 transition = {}; 26272 26273 26274 26275 if (_.options.fade === false) { 26276 26277 transition[_.transitionType] = _.transformType + ' ' + _.options.speed + 'ms ' + _.options.cssEase; 26278 26279 } else { 26280 26281 transition[_.transitionType] = 'opacity ' + _.options.speed + 'ms ' + _.options.cssEase; 26282 26283 } 26284 26285 26286 26287 if (_.options.fade === false) { 26288 26289 _.$slideTrack.css(transition); 26290 26291 } else { 26292 26293 _.$slides.eq(slide).css(transition); 26294 26295 } 26296 26297 26298 26299 }; 26300 26301 26302 26303 Slick.prototype.autoPlay = function() { 26304 26305 26306 26307 var _ = this; 26308 26309 26310 26311 _.autoPlayClear(); 26312 26313 26314 26315 if ( _.slideCount > _.options.slidesToShow ) { 26316 26317 _.autoPlayTimer = setInterval( _.autoPlayIterator, _.options.autoplaySpeed ); 26318 26319 } 26320 26321 26322 26323 }; 26324 26325 26326 26327 Slick.prototype.autoPlayClear = function() { 26328 26329 26330 26331 var _ = this; 26332 26333 26334 26335 if (_.autoPlayTimer) { 26336 26337 clearInterval(_.autoPlayTimer); 26338 26339 } 26340 26341 26342 26343 }; 26344 26345 26346 26347 Slick.prototype.autoPlayIterator = function() { 26348 26349 26350 26351 var _ = this, 26352 26353 slideTo = _.currentSlide + _.options.slidesToScroll; 26354 26355 26356 26357 if ( !_.paused && !_.interrupted && !_.focussed ) { 26358 26359 26360 26361 if ( _.options.infinite === false ) { 26362 26363 26364 26365 if ( _.direction === 1 && ( _.currentSlide + 1 ) === ( _.slideCount - 1 )) { 26366 26367 _.direction = 0; 26368 26369 } 26370 26371 26372 26373 else if ( _.direction === 0 ) { 26374 26375 26376 26377 slideTo = _.currentSlide - _.options.slidesToScroll; 26378 26379 26380 26381 if ( _.currentSlide - 1 === 0 ) { 26382 26383 _.direction = 1; 26384 26385 } 26386 26387 26388 26389 } 26390 26391 26392 26393 } 26394 26395 26396 26397 _.slideHandler( slideTo ); 26398 26399 26400 26401 } 26402 26403 26404 26405 }; 26406 26407 26408 26409 Slick.prototype.buildArrows = function() { 26410 26411 26412 26413 var _ = this; 26414 26415 26416 26417 if (_.options.arrows === true ) { 26418 26419 26420 26421 _.$prevArrow = $(_.options.prevArrow).addClass('slick-arrow'); 26422 26423 _.$nextArrow = $(_.options.nextArrow).addClass('slick-arrow'); 26424 26425 26426 26427 if( _.slideCount > _.options.slidesToShow ) { 26428 26429 26430 26431 _.$prevArrow.removeClass('slick-hidden').removeAttr('aria-hidden tabindex'); 26432 26433 _.$nextArrow.removeClass('slick-hidden').removeAttr('aria-hidden tabindex'); 26434 26435 26436 26437 if (_.htmlExpr.test(_.options.prevArrow)) { 26438 26439 _.$prevArrow.prependTo(_.options.appendArrows); 26440 26441 } 26442 26443 26444 26445 if (_.htmlExpr.test(_.options.nextArrow)) { 26446 26447 _.$nextArrow.appendTo(_.options.appendArrows); 26448 26449 } 26450 26451 26452 26453 if (_.options.infinite !== true) { 26454 26455 _.$prevArrow 26456 26457 .addClass('slick-disabled') 26458 26459 .attr('aria-disabled', 'true'); 26460 26461 } 26462 26463 26464 26465 } else { 26466 26467 26468 26469 _.$prevArrow.add( _.$nextArrow ) 26470 26471 26472 26473 .addClass('slick-hidden') 26474 26475 .attr({ 26476 26477 'aria-disabled': 'true', 26478 26479 'tabindex': '-1' 26480 26481 }); 26482 26483 26484 26485 } 26486 26487 26488 26489 } 26490 26491 26492 26493 }; 26494 26495 26496 26497 Slick.prototype.buildDots = function() { 26498 26499 26500 26501 var _ = this, 26502 26503 i, dot; 26504 26505 26506 26507 if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { 26508 26509 26510 26511 _.$slider.addClass('slick-dotted'); 26512 26513 26514 26515 dot = $('<ul />').addClass(_.options.dotsClass); 26516 26517 26518 26519 for (i = 0; i <= _.getDotCount(); i += 1) { 26520 26521 dot.append($('<li />').append(_.options.customPaging.call(this, _, i))); 26522 26523 } 26524 26525 26526 26527 _.$dots = dot.appendTo(_.options.appendDots); 26528 26529 26530 26531 _.$dots.find('li').first().addClass('slick-active'); 26532 26533 26534 26535 } 26536 26537 26538 26539 }; 26540 26541 26542 26543 Slick.prototype.buildOut = function() { 26544 26545 26546 26547 var _ = this; 26548 26549 26550 26551 _.$slides = 26552 26553 _.$slider 26554 26555 .children( _.options.slide + ':not(.slick-cloned)') 26556 26557 .addClass('slick-slide'); 26558 26559 26560 26561 _.slideCount = _.$slides.length; 26562 26563 26564 26565 _.$slides.each(function(index, element) { 26566 26567 $(element) 26568 26569 .attr('data-slick-index', index) 26570 26571 .data('originalStyling', $(element).attr('style') || ''); 26572 26573 }); 26574 26575 26576 26577 _.$slider.addClass('slick-slider'); 26578 26579 26580 26581 _.$slideTrack = (_.slideCount === 0) ? 26582 26583 $('<div class="slick-track"/>').appendTo(_.$slider) : 26584 26585 _.$slides.wrapAll('<div class="slick-track"/>').parent(); 26586 26587 26588 26589 _.$list = _.$slideTrack.wrap( 26590 26591 '<div class="slick-list"/>').parent(); 26592 26593 _.$slideTrack.css('opacity', 0); 26594 26595 26596 26597 if (_.options.centerMode === true || _.options.swipeToSlide === true) { 26598 26599 _.options.slidesToScroll = 1; 26600 26601 } 26602 26603 26604 26605 $('img[data-lazy]', _.$slider).not('[src]').addClass('slick-loading'); 26606 26607 26608 26609 _.setupInfinite(); 26610 26611 26612 26613 _.buildArrows(); 26614 26615 26616 26617 _.buildDots(); 26618 26619 26620 26621 _.updateDots(); 26622 26623 26624 26625 26626 26627 _.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0); 26628 26629 26630 26631 if (_.options.draggable === true) { 26632 26633 _.$list.addClass('draggable'); 26634 26635 } 26636 26637 26638 26639 }; 26640 26641 26642 26643 Slick.prototype.buildRows = function() { 26644 26645 26646 26647 var _ = this, a, b, c, newSlides, numOfSlides, originalSlides,slidesPerSection; 26648 26649 26650 26651 newSlides = document.createDocumentFragment(); 26652 26653 originalSlides = _.$slider.children(); 26654 26655 26656 26657 if(_.options.rows > 0) { 26658 26659 26660 26661 slidesPerSection = _.options.slidesPerRow * _.options.rows; 26662 26663 numOfSlides = Math.ceil( 26664 26665 originalSlides.length / slidesPerSection 26666 26667 ); 26668 26669 26670 26671 for(a = 0; a < numOfSlides; a++){ 26672 26673 var slide = document.createElement('div'); 26674 26675 for(b = 0; b < _.options.rows; b++) { 26676 26677 var row = document.createElement('div'); 26678 26679 for(c = 0; c < _.options.slidesPerRow; c++) { 26680 26681 var target = (a * slidesPerSection + ((b * _.options.slidesPerRow) + c)); 26682 26683 if (originalSlides.get(target)) { 26684 26685 row.appendChild(originalSlides.get(target)); 26686 26687 } 26688 26689 } 26690 26691 slide.appendChild(row); 26692 26693 } 26694 26695 newSlides.appendChild(slide); 26696 26697 } 26698 26699 26700 26701 _.$slider.empty().append(newSlides); 26702 26703 _.$slider.children().children().children() 26704 26705 .css({ 26706 26707 'width':(100 / _.options.slidesPerRow) + '%', 26708 26709 'display': 'inline-block' 26710 26711 }); 26712 26713 26714 26715 } 26716 26717 26718 26719 }; 26720 26721 26722 26723 Slick.prototype.checkResponsive = function(initial, forceUpdate) { 26724 26725 26726 26727 var _ = this, 26728 26729 breakpoint, targetBreakpoint, respondToWidth, triggerBreakpoint = false; 26730 26731 var sliderWidth = _.$slider.width(); 26732 26733 var windowWidth = window.innerWidth || $(window).width(); 26734 26735 26736 26737 if (_.respondTo === 'window') { 26738 26739 respondToWidth = windowWidth; 26740 26741 } else if (_.respondTo === 'slider') { 26742 26743 respondToWidth = sliderWidth; 26744 26745 } else if (_.respondTo === 'min') { 26746 26747 respondToWidth = Math.min(windowWidth, sliderWidth); 26748 26749 } 26750 26751 26752 26753 if ( _.options.responsive && 26754 26755 _.options.responsive.length && 26756 26757 _.options.responsive !== null) { 26758 26759 26760 26761 targetBreakpoint = null; 26762 26763 26764 26765 for (breakpoint in _.breakpoints) { 26766 26767 if (_.breakpoints.hasOwnProperty(breakpoint)) { 26768 26769 if (_.originalSettings.mobileFirst === false) { 26770 26771 if (respondToWidth < _.breakpoints[breakpoint]) { 26772 26773 targetBreakpoint = _.breakpoints[breakpoint]; 26774 26775 } 26776 26777 } else { 26778 26779 if (respondToWidth > _.breakpoints[breakpoint]) { 26780 26781 targetBreakpoint = _.breakpoints[breakpoint]; 26782 26783 } 26784 26785 } 26786 26787 } 26788 26789 } 26790 26791 26792 26793 if (targetBreakpoint !== null) { 26794 26795 if (_.activeBreakpoint !== null) { 26796 26797 if (targetBreakpoint !== _.activeBreakpoint || forceUpdate) { 26798 26799 _.activeBreakpoint = 26800 26801 targetBreakpoint; 26802 26803 if (_.breakpointSettings[targetBreakpoint] === 'unslick') { 26804 26805 _.unslick(targetBreakpoint); 26806 26807 } else { 26808 26809 _.options = $.extend({}, _.originalSettings, 26810 26811 _.breakpointSettings[ 26812 26813 targetBreakpoint]); 26814 26815 if (initial === true) { 26816 26817 _.currentSlide = _.options.initialSlide; 26818 26819 } 26820 26821 _.refresh(initial); 26822 26823 } 26824 26825 triggerBreakpoint = targetBreakpoint; 26826 26827 } 26828 26829 } else { 26830 26831 _.activeBreakpoint = targetBreakpoint; 26832 26833 if (_.breakpointSettings[targetBreakpoint] === 'unslick') { 26834 26835 _.unslick(targetBreakpoint); 26836 26837 } else { 26838 26839 _.options = $.extend({}, _.originalSettings, 26840 26841 _.breakpointSettings[ 26842 26843 targetBreakpoint]); 26844 26845 if (initial === true) { 26846 26847 _.currentSlide = _.options.initialSlide; 26848 26849 } 26850 26851 _.refresh(initial); 26852 26853 } 26854 26855 triggerBreakpoint = targetBreakpoint; 26856 26857 } 26858 26859 } else { 26860 26861 if (_.activeBreakpoint !== null) { 26862 26863 _.activeBreakpoint = null; 26864 26865 _.options = _.originalSettings; 26866 26867 if (initial === true) { 26868 26869 _.currentSlide = _.options.initialSlide; 26870 26871 } 26872 26873 _.refresh(initial); 26874 26875 triggerBreakpoint = targetBreakpoint; 26876 26877 } 26878 26879 } 26880 26881 26882 26883 // only trigger breakpoints during an actual break. not on initialize. 26884 26885 if( !initial && triggerBreakpoint !== false ) { 26886 26887 _.$slider.trigger('breakpoint', [_, triggerBreakpoint]); 26888 26889 } 26890 26891 } 26892 26893 26894 26895 }; 26896 26897 26898 26899 Slick.prototype.changeSlide = function(event, dontAnimate) { 26900 26901 26902 26903 var _ = this, 26904 26905 $target = $(event.currentTarget), 26906 26907 indexOffset, slideOffset, unevenOffset; 26908 26909 26910 26911 // If target is a link, prevent default action. 26912 26913 if($target.is('a')) { 26914 26915 event.preventDefault(); 26916 26917 } 26918 26919 26920 26921 // If target is not the <li> element (ie: a child), find the <li>. 26922 26923 if(!$target.is('li')) { 26924 26925 $target = $target.closest('li'); 26926 26927 } 26928 26929 26930 26931 unevenOffset = (_.slideCount % _.options.slidesToScroll !== 0); 26932 26933 indexOffset = unevenOffset ? 0 : (_.slideCount - _.currentSlide) % _.options.slidesToScroll; 26934 26935 26936 26937 switch (event.data.message) { 26938 26939 26940 26941 case 'previous': 26942 26943 slideOffset = indexOffset === 0 ? _.options.slidesToScroll : _.options.slidesToShow - indexOffset; 26944 26945 if (_.slideCount > _.options.slidesToShow) { 26946 26947 _.slideHandler(_.currentSlide - slideOffset, false, dontAnimate); 26948 26949 } 26950 26951 break; 26952 26953 26954 26955 case 'next': 26956 26957 slideOffset = indexOffset === 0 ? _.options.slidesToScroll : indexOffset; 26958 26959 if (_.slideCount > _.options.slidesToShow) { 26960 26961 _.slideHandler(_.currentSlide + slideOffset, false, dontAnimate); 26962 26963 } 26964 26965 break; 26966 26967 26968 26969 case 'index': 26970 26971 var index = event.data.index === 0 ? 0 : 26972 26973 event.data.index || $target.index() * _.options.slidesToScroll; 26974 26975 26976 26977 _.slideHandler(_.checkNavigable(index), false, dontAnimate); 26978 26979 $target.children().trigger('focus'); 26980 26981 break; 26982 26983 26984 26985 default: 26986 26987 return; 26988 26989 } 26990 26991 26992 26993 }; 26994 26995 26996 26997 Slick.prototype.checkNavigable = function(index) { 26998 26999 27000 27001 var _ = this, 27002 27003 navigables, prevNavigable; 27004 27005 27006 27007 navigables = _.getNavigableIndexes(); 27008 27009 prevNavigable = 0; 27010 27011 if (index > navigables[navigables.length - 1]) { 27012 27013 index = navigables[navigables.length - 1]; 27014 27015 } else { 27016 27017 for (var n in navigables) { 27018 27019 if (index < navigables[n]) { 27020 27021 index = prevNavigable; 27022 27023 break; 27024 27025 } 27026 27027 prevNavigable = navigables[n]; 27028 27029 } 27030 27031 } 27032 27033 27034 27035 return index; 27036 27037 }; 27038 27039 27040 27041 Slick.prototype.cleanUpEvents = function() { 27042 27043 27044 27045 var _ = this; 27046 27047 27048 27049 if (_.options.dots && _.$dots !== null) { 27050 27051 27052 27053 $('li', _.$dots) 27054 27055 .off('click.slick', _.changeSlide) 27056 27057 .off('mouseenter.slick', $.proxy(_.interrupt, _, true)) 27058 27059 .off('mouseleave.slick', $.proxy(_.interrupt, _, false)); 27060 27061 27062 27063 if (_.options.accessibility === true) { 27064 27065 _.$dots.off('keydown.slick', _.keyHandler); 27066 27067 } 27068 27069 } 27070 27071 27072 27073 _.$slider.off('focus.slick blur.slick'); 27074 27075 27076 27077 if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { 27078 27079 _.$prevArrow && _.$prevArrow.off('click.slick', _.changeSlide); 27080 27081 _.$nextArrow && _.$nextArrow.off('click.slick', _.changeSlide); 27082 27083 27084 27085 if (_.options.accessibility === true) { 27086 27087 _.$prevArrow && _.$prevArrow.off('keydown.slick', _.keyHandler); 27088 27089 _.$nextArrow && _.$nextArrow.off('keydown.slick', _.keyHandler); 27090 27091 } 27092 27093 } 27094 27095 27096 27097 _.$list.off('touchstart.slick mousedown.slick', _.swipeHandler); 27098 27099 _.$list.off('touchmove.slick mousemove.slick', _.swipeHandler); 27100 27101 _.$list.off('touchend.slick mouseup.slick', _.swipeHandler); 27102 27103 _.$list.off('touchcancel.slick mouseleave.slick', _.swipeHandler); 27104 27105 27106 27107 _.$list.off('click.slick', _.clickHandler); 27108 27109 27110 27111 $(document).off(_.visibilityChange, _.visibility); 27112 27113 27114 27115 _.cleanUpSlideEvents(); 27116 27117 27118 27119 if (_.options.accessibility === true) { 27120 27121 _.$list.off('keydown.slick', _.keyHandler); 27122 27123 } 27124 27125 27126 27127 if (_.options.focusOnSelect === true) { 27128 27129 $(_.$slideTrack).children().off('click.slick', _.selectHandler); 27130 27131 } 27132 27133 27134 27135 $(window).off('orientationchange.slick.slick-' + _.instanceUid, _.orientationChange); 27136 27137 27138 27139 $(window).off('resize.slick.slick-' + _.instanceUid, _.resize); 27140 27141 27142 27143 $('[draggable!=true]', _.$slideTrack).off('dragstart', _.preventDefault); 27144 27145 27146 27147 $(window).off('load.slick.slick-' + _.instanceUid, _.setPosition); 27148 27149 27150 27151 }; 27152 27153 27154 27155 Slick.prototype.cleanUpSlideEvents = function() { 27156 27157 27158 27159 var _ = this; 27160 27161 27162 27163 _.$list.off('mouseenter.slick', $.proxy(_.interrupt, _, true)); 27164 27165 _.$list.off('mouseleave.slick', $.proxy(_.interrupt, _, false)); 27166 27167 27168 27169 }; 27170 27171 27172 27173 Slick.prototype.cleanUpRows = function() { 27174 27175 27176 27177 var _ = this, originalSlides; 27178 27179 27180 27181 if(_.options.rows > 0) { 27182 27183 originalSlides = _.$slides.children().children(); 27184 27185 originalSlides.removeAttr('style'); 27186 27187 _.$slider.empty().append(originalSlides); 27188 27189 } 27190 27191 27192 27193 }; 27194 27195 27196 27197 Slick.prototype.clickHandler = function(event) { 27198 27199 27200 27201 var _ = this; 27202 27203 27204 27205 if (_.shouldClick === false) { 27206 27207 event.stopImmediatePropagation(); 27208 27209 event.stopPropagation(); 27210 27211 event.preventDefault(); 27212 27213 } 27214 27215 27216 27217 }; 27218 27219 27220 27221 Slick.prototype.destroy = function(refresh) { 27222 27223 27224 27225 var _ = this; 27226 27227 27228 27229 _.autoPlayClear(); 27230 27231 27232 27233 _.touchObject = {}; 27234 27235 27236 27237 _.cleanUpEvents(); 27238 27239 27240 27241 $('.slick-cloned', _.$slider).detach(); 27242 27243 27244 27245 if (_.$dots) { 27246 27247 _.$dots.remove(); 27248 27249 } 27250 27251 27252 27253 if ( _.$prevArrow && _.$prevArrow.length ) { 27254 27255 27256 27257 _.$prevArrow 27258 27259 .removeClass('slick-disabled slick-arrow slick-hidden') 27260 27261 .removeAttr('aria-hidden aria-disabled tabindex') 27262 27263 .css('display',''); 27264 27265 27266 27267 if ( _.htmlExpr.test( _.options.prevArrow )) { 27268 27269 _.$prevArrow.remove(); 27270 27271 } 27272 27273 } 27274 27275 27276 27277 if ( _.$nextArrow && _.$nextArrow.length ) { 27278 27279 27280 27281 _.$nextArrow 27282 27283 .removeClass('slick-disabled slick-arrow slick-hidden') 27284 27285 .removeAttr('aria-hidden aria-disabled tabindex') 27286 27287 .css('display',''); 27288 27289 27290 27291 if ( _.htmlExpr.test( _.options.nextArrow )) { 27292 27293 _.$nextArrow.remove(); 27294 27295 } 27296 27297 } 27298 27299 27300 27301 27302 27303 if (_.$slides) { 27304 27305 27306 27307 _.$slides 27308 27309 .removeClass('slick-slide slick-active slick-center slick-visible slick-current') 27310 27311 .removeAttr('aria-hidden') 27312 27313 .removeAttr('data-slick-index') 27314 27315 .each(function(){ 27316 27317 $(this).attr('style', $(this).data('originalStyling')); 27318 27319 }); 27320 27321 27322 27323 _.$slideTrack.children(this.options.slide).detach(); 27324 27325 27326 27327 _.$slideTrack.detach(); 27328 27329 27330 27331 _.$list.detach(); 27332 27333 27334 27335 _.$slider.append(_.$slides); 27336 27337 } 27338 27339 27340 27341 _.cleanUpRows(); 27342 27343 27344 27345 _.$slider.removeClass('slick-slider'); 27346 27347 _.$slider.removeClass('slick-initialized'); 27348 27349 _.$slider.removeClass('slick-dotted'); 27350 27351 27352 27353 _.unslicked = true; 27354 27355 27356 27357 if(!refresh) { 27358 27359 _.$slider.trigger('destroy', [_]); 27360 27361 } 27362 27363 27364 27365 }; 27366 27367 27368 27369 Slick.prototype.disableTransition = function(slide) { 27370 27371 27372 27373 var _ = this, 27374 27375 transition = {}; 27376 27377 27378 27379 transition[_.transitionType] = ''; 27380 27381 27382 27383 if (_.options.fade === false) { 27384 27385 _.$slideTrack.css(transition); 27386 27387 } else { 27388 27389 _.$slides.eq(slide).css(transition); 27390 27391 } 27392 27393 27394 27395 }; 27396 27397 27398 27399 Slick.prototype.fadeSlide = function(slideIndex, callback) { 27400 27401 27402 27403 var _ = this; 27404 27405 27406 27407 if (_.cssTransitions === false) { 27408 27409 27410 27411 _.$slides.eq(slideIndex).css({ 27412 27413 zIndex: _.options.zIndex 27414 27415 }); 27416 27417 27418 27419 _.$slides.eq(slideIndex).animate({ 27420 27421 opacity: 1 27422 27423 }, _.options.speed, _.options.easing, callback); 27424 27425 27426 27427 } else { 27428 27429 27430 27431 _.applyTransition(slideIndex); 27432 27433 27434 27435 _.$slides.eq(slideIndex).css({ 27436 27437 opacity: 1, 27438 27439 zIndex: _.options.zIndex 27440 27441 }); 27442 27443 27444 27445 if (callback) { 27446 27447 setTimeout(function() { 27448 27449 27450 27451 _.disableTransition(slideIndex); 27452 27453 27454 27455 callback.call(); 27456 27457 }, _.options.speed); 27458 27459 } 27460 27461 27462 27463 } 27464 27465 27466 27467 }; 27468 27469 27470 27471 Slick.prototype.fadeSlideOut = function(slideIndex) { 27472 27473 27474 27475 var _ = this; 27476 27477 27478 27479 if (_.cssTransitions === false) { 27480 27481 27482 27483 _.$slides.eq(slideIndex).animate({ 27484 27485 opacity: 0, 27486 27487 zIndex: _.options.zIndex - 2 27488 27489 }, _.options.speed, _.options.easing); 27490 27491 27492 27493 } else { 27494 27495 27496 27497 _.applyTransition(slideIndex); 27498 27499 27500 27501 _.$slides.eq(slideIndex).css({ 27502 27503 opacity: 0, 27504 27505 zIndex: _.options.zIndex - 2 27506 27507 }); 27508 27509 27510 27511 } 27512 27513 27514 27515 }; 27516 27517 27518 27519 Slick.prototype.filterSlides = Slick.prototype.slickFilter = function(filter) { 27520 27521 27522 27523 var _ = this; 27524 27525 27526 27527 if (filter !== null) { 27528 27529 27530 27531 _.$slidesCache = _.$slides; 27532 27533 27534 27535 _.unload(); 27536 27537 27538 27539 _.$slideTrack.children(this.options.slide).detach(); 27540 27541 27542 27543 _.$slidesCache.filter(filter).appendTo(_.$slideTrack); 27544 27545 27546 27547 _.reinit(); 27548 27549 27550 27551 } 27552 27553 27554 27555 }; 27556 27557 27558 27559 Slick.prototype.focusHandler = function() { 27560 27561 27562 27563 var _ = this; 27564 27565 27566 27567 _.$slider 27568 27569 .off('focus.slick blur.slick') 27570 27571 .on('focus.slick blur.slick', '*', function(event) { 27572 27573 27574 27575 event.stopImmediatePropagation(); 27576 27577 var $sf = $(this); 27578 27579 27580 27581 setTimeout(function() { 27582 27583 27584 27585 if( _.options.pauseOnFocus ) { 27586 27587 _.focussed = $sf.is(':focus'); 27588 27589 _.autoPlay(); 27590 27591 } 27592 27593 27594 27595 }, 0); 27596 27597 27598 27599 }); 27600 27601 }; 27602 27603 27604 27605 Slick.prototype.getCurrent = Slick.prototype.slickCurrentSlide = function() { 27606 27607 27608 27609 var _ = this; 27610 27611 return _.currentSlide; 27612 27613 27614 27615 }; 27616 27617 27618 27619 Slick.prototype.getDotCount = function() { 27620 27621 27622 27623 var _ = this; 27624 27625 27626 27627 var breakPoint = 0; 27628 27629 var counter = 0; 27630 27631 var pagerQty = 0; 27632 27633 27634 27635 if (_.options.infinite === true) { 27636 27637 if (_.slideCount <= _.options.slidesToShow) { 27638 27639 ++pagerQty; 27640 27641 } else { 27642 27643 while (breakPoint < _.slideCount) { 27644 27645 ++pagerQty; 27646 27647 breakPoint = counter + _.options.slidesToScroll; 27648 27649 counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow; 27650 27651 } 27652 27653 } 27654 27655 } else if (_.options.centerMode === true) { 27656 27657 pagerQty = _.slideCount; 27658 27659 } else if(!_.options.asNavFor) { 27660 27661 pagerQty = 1 + Math.ceil((_.slideCount - _.options.slidesToShow) / _.options.slidesToScroll); 27662 27663 }else { 27664 27665 while (breakPoint < _.slideCount) { 27666 27667 ++pagerQty; 27668 27669 breakPoint = counter + _.options.slidesToScroll; 27670 27671 counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow; 27672 27673 } 27674 27675 } 27676 27677 27678 27679 return pagerQty - 1; 27680 27681 27682 27683 }; 27684 27685 27686 27687 Slick.prototype.getLeft = function(slideIndex) { 27688 27689 27690 27691 var _ = this, 27692 27693 targetLeft, 27694 27695 verticalHeight, 27696 27697 verticalOffset = 0, 27698 27699 targetSlide, 27700 27701 coef; 27702 27703 27704 27705 _.slideOffset = 0; 27706 27707 verticalHeight = _.$slides.first().outerHeight(true); 27708 27709 27710 27711 if (_.options.infinite === true) { 27712 27713 if (_.slideCount > _.options.slidesToShow) { 27714 27715 _.slideOffset = (_.slideWidth * _.options.slidesToShow) * -1; 27716 27717 coef = -1 27718 27719 27720 27721 if (_.options.vertical === true && _.options.centerMode === true) { 27722 27723 if (_.options.slidesToShow === 2) { 27724 27725 coef = -1.5; 27726 27727 } else if (_.options.slidesToShow === 1) { 27728 27729 coef = -2 27730 27731 } 27732 27733 } 27734 27735 verticalOffset = (verticalHeight * _.options.slidesToShow) * coef; 27736 27737 } 27738 27739 if (_.slideCount % _.options.slidesToScroll !== 0) { 27740 27741 if (slideIndex + _.options.slidesToScroll > _.slideCount && _.slideCount > _.options.slidesToShow) { 27742 27743 if (slideIndex > _.slideCount) { 27744 27745 _.slideOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * _.slideWidth) * -1; 27746 27747 verticalOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * verticalHeight) * -1; 27748 27749 } else { 27750 27751 _.slideOffset = ((_.slideCount % _.options.slidesToScroll) * _.slideWidth) * -1; 27752 27753 verticalOffset = ((_.slideCount % _.options.slidesToScroll) * verticalHeight) * -1; 27754 27755 } 27756 27757 } 27758 27759 } 27760 27761 } else { 27762 27763 if (slideIndex + _.options.slidesToShow > _.slideCount) { 27764 27765 _.slideOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * _.slideWidth; 27766 27767 verticalOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * verticalHeight; 27768 27769 } 27770 27771 } 27772 27773 27774 27775 if (_.slideCount <= _.options.slidesToShow) { 27776 27777 _.slideOffset = 0; 27778 27779 verticalOffset = 0; 27780 27781 } 27782 27783 27784 27785 if (_.options.centerMode === true && _.slideCount <= _.options.slidesToShow) { 27786 27787 _.slideOffset = ((_.slideWidth * Math.floor(_.options.slidesToShow)) / 2) - ((_.slideWidth * _.slideCount) / 2); 27788 27789 } else if (_.options.centerMode === true && _.options.infinite === true) { 27790 27791 _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2) - _.slideWidth; 27792 27793 } else if (_.options.centerMode === true) { 27794 27795 _.slideOffset = 0; 27796 27797 _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2); 27798 27799 } 27800 27801 27802 27803 if (_.options.vertical === false) { 27804 27805 targetLeft = ((slideIndex * _.slideWidth) * -1) + _.slideOffset; 27806 27807 } else { 27808 27809 targetLeft = ((slideIndex * verticalHeight) * -1) + verticalOffset; 27810 27811 } 27812 27813 27814 27815 if (_.options.variableWidth === true) { 27816 27817 27818 27819 if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) { 27820 27821 targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex); 27822 27823 } else { 27824 27825 targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow); 27826 27827 } 27828 27829 27830 27831 if (_.options.rtl === true) { 27832 27833 if (targetSlide[0]) { 27834 27835 targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1; 27836 27837 } else { 27838 27839 targetLeft = 0; 27840 27841 } 27842 27843 } else { 27844 27845 targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0; 27846 27847 } 27848 27849 27850 27851 if (_.options.centerMode === true) { 27852 27853 if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) { 27854 27855 targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex); 27856 27857 } else { 27858 27859 targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow + 1); 27860 27861 } 27862 27863 27864 27865 if (_.options.rtl === true) { 27866 27867 if (targetSlide[0]) { 27868 27869 targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1; 27870 27871 } else { 27872 27873 targetLeft = 0; 27874 27875 } 27876 27877 } else { 27878 27879 targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0; 27880 27881 } 27882 27883 27884 27885 targetLeft += (_.$list.width() - targetSlide.outerWidth()) / 2; 27886 27887 } 27888 27889 } 27890 27891 27892 27893 return targetLeft; 27894 27895 27896 27897 }; 27898 27899 27900 27901 Slick.prototype.getOption = Slick.prototype.slickGetOption = function(option) { 27902 27903 27904 27905 var _ = this; 27906 27907 27908 27909 return _.options[option]; 27910 27911 27912 27913 }; 27914 27915 27916 27917 Slick.prototype.getNavigableIndexes = function() { 27918 27919 27920 27921 var _ = this, 27922 27923 breakPoint = 0, 27924 27925 counter = 0, 27926 27927 indexes = [], 27928 27929 max; 27930 27931 27932 27933 if (_.options.infinite === false) { 27934 27935 max = _.slideCount; 27936 27937 } else { 27938 27939 breakPoint = _.options.slidesToScroll * -1; 27940 27941 counter = _.options.slidesToScroll * -1; 27942 27943 max = _.slideCount * 2; 27944 27945 } 27946 27947 27948 27949 while (breakPoint < max) { 27950 27951 indexes.push(breakPoint); 27952 27953 breakPoint = counter + _.options.slidesToScroll; 27954 27955 counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow; 27956 27957 } 27958 27959 27960 27961 return indexes; 27962 27963 27964 27965 }; 27966 27967 27968 27969 Slick.prototype.getSlick = function() { 27970 27971 27972 27973 return this; 27974 27975 27976 27977 }; 27978 27979 27980 27981 Slick.prototype.getSlideCount = function() { 27982 27983 27984 27985 var _ = this, 27986 27987 slidesTraversed, swipedSlide, centerOffset; 27988 27989 27990 27991 centerOffset = _.options.centerMode === true ? _.slideWidth * Math.floor(_.options.slidesToShow / 2) : 0; 27992 27993 27994 27995 if (_.options.swipeToSlide === true) { 27996 27997 _.$slideTrack.find('.slick-slide').each(function(index, slide) { 27998 27999 if (slide.offsetLeft - centerOffset + ($(slide).outerWidth() / 2) > (_.swipeLeft * -1)) { 28000 28001 swipedSlide = slide; 28002 28003 return false; 28004 28005 } 28006 28007 }); 28008 28009 28010 28011 slidesTraversed = Math.abs($(swipedSlide).attr('data-slick-index') - _.currentSlide) || 1; 28012 28013 28014 28015 return slidesTraversed; 28016 28017 28018 28019 } else { 28020 28021 return _.options.slidesToScroll; 28022 28023 } 28024 28025 28026 28027 }; 28028 28029 28030 28031 Slick.prototype.goTo = Slick.prototype.slickGoTo = function(slide, dontAnimate) { 28032 28033 28034 28035 var _ = this; 28036 28037 28038 28039 _.changeSlide({ 28040 28041 data: { 28042 28043 message: 'index', 28044 28045 index: parseInt(slide) 28046 28047 } 28048 28049 }, dontAnimate); 28050 28051 28052 28053 }; 28054 28055 28056 28057 Slick.prototype.init = function(creation) { 28058 28059 28060 28061 var _ = this; 28062 28063 28064 28065 if (!$(_.$slider).hasClass('slick-initialized')) { 28066 28067 28068 28069 $(_.$slider).addClass('slick-initialized'); 28070 28071 28072 28073 _.buildRows(); 28074 28075 _.buildOut(); 28076 28077 _.setProps(); 28078 28079 _.startLoad(); 28080 28081 _.loadSlider(); 28082 28083 _.initializeEvents(); 28084 28085 _.updateArrows(); 28086 28087 _.updateDots(); 28088 28089 _.checkResponsive(true); 28090 28091 _.focusHandler(); 28092 28093 28094 28095 } 28096 28097 28098 28099 if (creation) { 28100 28101 _.$slider.trigger('init', [_]); 28102 28103 } 28104 28105 28106 28107 if (_.options.accessibility === true) { 28108 28109 _.initADA(); 28110 28111 } 28112 28113 28114 28115 if ( _.options.autoplay ) { 28116 28117 28118 28119 _.paused = false; 28120 28121 _.autoPlay(); 28122 28123 28124 28125 } 28126 28127 28128 28129 }; 28130 28131 28132 28133 Slick.prototype.initADA = function() { 28134 28135 var _ = this, 28136 28137 numDotGroups = Math.ceil(_.slideCount / _.options.slidesToShow), 28138 28139 tabControlIndexes = _.getNavigableIndexes().filter(function(val) { 28140 28141 return (val >= 0) && (val < _.slideCount); 28142 28143 }); 28144 28145 28146 28147 _.$slides.add(_.$slideTrack.find('.slick-cloned')).attr({ 28148 28149 'aria-hidden': 'true', 28150 28151 'tabindex': '-1' 28152 28153 }).find('a, input, button, select').attr({ 28154 28155 'tabindex': '-1' 28156 28157 }); 28158 28159 28160 28161 if (_.$dots !== null) { 28162 28163 _.$slides.not(_.$slideTrack.find('.slick-cloned')).each(function(i) { 28164 28165 var slideControlIndex = tabControlIndexes.indexOf(i); 28166 28167 28168 28169 $(this).attr({ 28170 28171 'role': 'tabpanel', 28172 28173 'id': 'slick-slide' + _.instanceUid + i, 28174 28175 'tabindex': -1 28176 28177 }); 28178 28179 28180 28181 if (slideControlIndex !== -1) { 28182 28183 var ariaButtonControl = 'slick-slide-control' + _.instanceUid + slideControlIndex 28184 28185 if ($('#' + ariaButtonControl).length) { 28186 28187 $(this).attr({ 28188 28189 'aria-describedby': ariaButtonControl 28190 28191 }); 28192 28193 } 28194 28195 } 28196 28197 }); 28198 28199 28200 28201 _.$dots.attr('role', 'tablist').find('li').each(function(i) { 28202 28203 var mappedSlideIndex = tabControlIndexes[i]; 28204 28205 28206 28207 $(this).attr({ 28208 28209 'role': 'presentation' 28210 28211 }); 28212 28213 28214 28215 $(this).find('button').first().attr({ 28216 28217 'role': 'tab', 28218 28219 'id': 'slick-slide-control' + _.instanceUid + i, 28220 28221 'aria-controls': 'slick-slide' + _.instanceUid + mappedSlideIndex, 28222 28223 'aria-label': (i + 1) + ' of ' + numDotGroups, 28224 28225 'aria-selected': null, 28226 28227 'tabindex': '-1' 28228 28229 }); 28230 28231 28232 28233 }).eq(_.currentSlide).find('button').attr({ 28234 28235 'aria-selected': 'true', 28236 28237 'tabindex': '0' 28238 28239 }).end(); 28240 28241 } 28242 28243 28244 28245 for (var i=_.currentSlide, max=i+_.options.slidesToShow; i < max; i++) { 28246 28247 if (_.options.focusOnChange) { 28248 28249 _.$slides.eq(i).attr({'tabindex': '0'}); 28250 28251 } else { 28252 28253 _.$slides.eq(i).removeAttr('tabindex'); 28254 28255 } 28256 28257 } 28258 28259 28260 28261 _.activateADA(); 28262 28263 28264 28265 }; 28266 28267 28268 28269 Slick.prototype.initArrowEvents = function() { 28270 28271 28272 28273 var _ = this; 28274 28275 28276 28277 if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { 28278 28279 _.$prevArrow 28280 28281 .off('click.slick') 28282 28283 .on('click.slick', { 28284 28285 message: 'previous' 28286 28287 }, _.changeSlide); 28288 28289 _.$nextArrow 28290 28291 .off('click.slick') 28292 28293 .on('click.slick', { 28294 28295 message: 'next' 28296 28297 }, _.changeSlide); 28298 28299 28300 28301 if (_.options.accessibility === true) { 28302 28303 _.$prevArrow.on('keydown.slick', _.keyHandler); 28304 28305 _.$nextArrow.on('keydown.slick', _.keyHandler); 28306 28307 } 28308 28309 } 28310 28311 28312 28313 }; 28314 28315 28316 28317 Slick.prototype.initDotEvents = function() { 28318 28319 28320 28321 var _ = this; 28322 28323 28324 28325 if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { 28326 28327 $('li', _.$dots).on('click.slick', { 28328 28329 message: 'index' 28330 28331 }, _.changeSlide); 28332 28333 28334 28335 if (_.options.accessibility === true) { 28336 28337 _.$dots.on('keydown.slick', _.keyHandler); 28338 28339 } 28340 28341 } 28342 28343 28344 28345 if (_.options.dots === true && _.options.pauseOnDotsHover === true && _.slideCount > _.options.slidesToShow) { 28346 28347 28348 28349 $('li', _.$dots) 28350 28351 .on('mouseenter.slick', $.proxy(_.interrupt, _, true)) 28352 28353 .on('mouseleave.slick', $.proxy(_.interrupt, _, false)); 28354 28355 28356 28357 } 28358 28359 28360 28361 }; 28362 28363 28364 28365 Slick.prototype.initSlideEvents = function() { 28366 28367 28368 28369 var _ = this; 28370 28371 28372 28373 if ( _.options.pauseOnHover ) { 28374 28375 28376 28377 _.$list.on('mouseenter.slick', $.proxy(_.interrupt, _, true)); 28378 28379 _.$list.on('mouseleave.slick', $.proxy(_.interrupt, _, false)); 28380 28381 28382 28383 } 28384 28385 28386 28387 }; 28388 28389 28390 28391 Slick.prototype.initializeEvents = function() { 28392 28393 28394 28395 var _ = this; 28396 28397 28398 28399 _.initArrowEvents(); 28400 28401 28402 28403 _.initDotEvents(); 28404 28405 _.initSlideEvents(); 28406 28407 28408 28409 _.$list.on('touchstart.slick mousedown.slick', { 28410 28411 action: 'start' 28412 28413 }, _.swipeHandler); 28414 28415 _.$list.on('touchmove.slick mousemove.slick', { 28416 28417 action: 'move' 28418 28419 }, _.swipeHandler); 28420 28421 _.$list.on('touchend.slick mouseup.slick', { 28422 28423 action: 'end' 28424 28425 }, _.swipeHandler); 28426 28427 _.$list.on('touchcancel.slick mouseleave.slick', { 28428 28429 action: 'end' 28430 28431 }, _.swipeHandler); 28432 28433 28434 28435 _.$list.on('click.slick', _.clickHandler); 28436 28437 28438 28439 $(document).on(_.visibilityChange, $.proxy(_.visibility, _)); 28440 28441 28442 28443 if (_.options.accessibility === true) { 28444 28445 _.$list.on('keydown.slick', _.keyHandler); 28446 28447 } 28448 28449 28450 28451 if (_.options.focusOnSelect === true) { 28452 28453 $(_.$slideTrack).children().on('click.slick', _.selectHandler); 28454 28455 } 28456 28457 28458 28459 $(window).on('orientationchange.slick.slick-' + _.instanceUid, $.proxy(_.orientationChange, _)); 28460 28461 28462 28463 $(window).on('resize.slick.slick-' + _.instanceUid, $.proxy(_.resize, _)); 28464 28465 28466 28467 $('[draggable!=true]', _.$slideTrack).on('dragstart', _.preventDefault); 28468 28469 28470 28471 $(window).on('load.slick.slick-' + _.instanceUid, _.setPosition); 28472 28473 $(_.setPosition); 28474 28475 28476 28477 }; 28478 28479 28480 28481 Slick.prototype.initUI = function() { 28482 28483 28484 28485 var _ = this; 28486 28487 28488 28489 if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { 28490 28491 28492 28493 _.$prevArrow.show(); 28494 28495 _.$nextArrow.show(); 28496 28497 28498 28499 } 28500 28501 28502 28503 if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { 28504 28505 28506 28507 _.$dots.show(); 28508 28509 28510 28511 } 28512 28513 28514 28515 }; 28516 28517 28518 28519 Slick.prototype.keyHandler = function(event) { 28520 28521 28522 28523 var _ = this; 28524 28525 //Dont slide if the cursor is inside the form fields and arrow keys are pressed 28526 28527 if(!event.target.tagName.match('TEXTAREA|INPUT|SELECT')) { 28528 28529 if (event.keyCode === 37 && _.options.accessibility === true) { 28530 28531 _.changeSlide({ 28532 28533 data: { 28534 28535 message: _.options.rtl === true ? 'next' : 'previous' 28536 28537 } 28538 28539 }); 28540 28541 } else if (event.keyCode === 39 && _.options.accessibility === true) { 28542 28543 _.changeSlide({ 28544 28545 data: { 28546 28547 message: _.options.rtl === true ? 'previous' : 'next' 28548 28549 } 28550 28551 }); 28552 28553 } 28554 28555 } 28556 28557 28558 28559 }; 28560 28561 28562 28563 Slick.prototype.lazyLoad = function() { 28564 28565 28566 28567 var _ = this, 28568 28569 loadRange, cloneRange, rangeStart, rangeEnd; 28570 28571 28572 28573 function loadImages(imagesScope) { 28574 28575 28576 28577 $('img[data-lazy]', imagesScope).each(function() { 28578 28579 28580 28581 var image = $(this), 28582 28583 imageSource = $(this).attr('data-lazy'), 28584 28585 imageSrcSet = $(this).attr('data-srcset'), 28586 28587 imageSizes = $(this).attr('data-sizes') || _.$slider.attr('data-sizes'), 28588 28589 imageToLoad = document.createElement('img'); 28590 28591 28592 28593 imageToLoad.onload = function() { 28594 28595 28596 28597 image 28598 28599 .animate({ opacity: 0 }, 100, function() { 28600 28601 28602 28603 if (imageSrcSet) { 28604 28605 image 28606 28607 .attr('srcset', imageSrcSet ); 28608 28609 28610 28611 if (imageSizes) { 28612 28613 image 28614 28615 .attr('sizes', imageSizes ); 28616 28617 } 28618 28619 } 28620 28621 28622 28623 image 28624 28625 .attr('src', imageSource) 28626 28627 .animate({ opacity: 1 }, 200, function() { 28628 28629 image 28630 28631 .removeAttr('data-lazy data-srcset data-sizes') 28632 28633 .removeClass('slick-loading'); 28634 28635 }); 28636 28637 _.$slider.trigger('lazyLoaded', [_, image, imageSource]); 28638 28639 }); 28640 28641 28642 28643 }; 28644 28645 28646 28647 imageToLoad.onerror = function() { 28648 28649 28650 28651 image 28652 28653 .removeAttr( 'data-lazy' ) 28654 28655 .removeClass( 'slick-loading' ) 28656 28657 .addClass( 'slick-lazyload-error' ); 28658 28659 28660 28661 _.$slider.trigger('lazyLoadError', [ _, image, imageSource ]); 28662 28663 28664 28665 }; 28666 28667 28668 28669 imageToLoad.src = imageSource; 28670 28671 28672 28673 }); 28674 28675 28676 28677 } 28678 28679 28680 28681 if (_.options.centerMode === true) { 28682 28683 if (_.options.infinite === true) { 28684 28685 rangeStart = _.currentSlide + (_.options.slidesToShow / 2 + 1); 28686 28687 rangeEnd = rangeStart + _.options.slidesToShow + 2; 28688 28689 } else { 28690 28691 rangeStart = Math.max(0, _.currentSlide - (_.options.slidesToShow / 2 + 1)); 28692 28693 rangeEnd = 2 + (_.options.slidesToShow / 2 + 1) + _.currentSlide; 28694 28695 } 28696 28697 } else { 28698 28699 rangeStart = _.options.infinite ? _.options.slidesToShow + _.currentSlide : _.currentSlide; 28700 28701 rangeEnd = Math.ceil(rangeStart + _.options.slidesToShow); 28702 28703 if (_.options.fade === true) { 28704 28705 if (rangeStart > 0) rangeStart--; 28706 28707 if (rangeEnd <= _.slideCount) rangeEnd++; 28708 28709 } 28710 28711 } 28712 28713 28714 28715 loadRange = _.$slider.find('.slick-slide').slice(rangeStart, rangeEnd); 28716 28717 28718 28719 if (_.options.lazyLoad === 'anticipated') { 28720 28721 var prevSlide = rangeStart - 1, 28722 28723 nextSlide = rangeEnd, 28724 28725 $slides = _.$slider.find('.slick-slide'); 28726 28727 28728 28729 for (var i = 0; i < _.options.slidesToScroll; i++) { 28730 28731 if (prevSlide < 0) prevSlide = _.slideCount - 1; 28732 28733 loadRange = loadRange.add($slides.eq(prevSlide)); 28734 28735 loadRange = loadRange.add($slides.eq(nextSlide)); 28736 28737 prevSlide--; 28738 28739 nextSlide++; 28740 28741 } 28742 28743 } 28744 28745 28746 28747 loadImages(loadRange); 28748 28749 28750 28751 if (_.slideCount <= _.options.slidesToShow) { 28752 28753 cloneRange = _.$slider.find('.slick-slide'); 28754 28755 loadImages(cloneRange); 28756 28757 } else 28758 28759 if (_.currentSlide >= _.slideCount - _.options.slidesToShow) { 28760 28761 cloneRange = _.$slider.find('.slick-cloned').slice(0, _.options.slidesToShow); 28762 28763 loadImages(cloneRange); 28764 28765 } else if (_.currentSlide === 0) { 28766 28767 cloneRange = _.$slider.find('.slick-cloned').slice(_.options.slidesToShow * -1); 28768 28769 loadImages(cloneRange); 28770 28771 } 28772 28773 28774 28775 }; 28776 28777 28778 28779 Slick.prototype.loadSlider = function() { 28780 28781 28782 28783 var _ = this; 28784 28785 28786 28787 _.setPosition(); 28788 28789 28790 28791 _.$slideTrack.css({ 28792 28793 opacity: 1 28794 28795 }); 28796 28797 28798 28799 _.$slider.removeClass('slick-loading'); 28800 28801 28802 28803 _.initUI(); 28804 28805 28806 28807 if (_.options.lazyLoad === 'progressive') { 28808 28809 _.progressiveLazyLoad(); 28810 28811 } 28812 28813 28814 28815 }; 28816 28817 28818 28819 Slick.prototype.next = Slick.prototype.slickNext = function() { 28820 28821 28822 28823 var _ = this; 28824 28825 28826 28827 _.changeSlide({ 28828 28829 data: { 28830 28831 message: 'next' 28832 28833 } 28834 28835 }); 28836 28837 28838 28839 }; 28840 28841 28842 28843 Slick.prototype.orientationChange = function() { 28844 28845 28846 28847 var _ = this; 28848 28849 28850 28851 _.checkResponsive(); 28852 28853 _.setPosition(); 28854 28855 28856 28857 }; 28858 28859 28860 28861 Slick.prototype.pause = Slick.prototype.slickPause = function() { 28862 28863 28864 28865 var _ = this; 28866 28867 28868 28869 _.autoPlayClear(); 28870 28871 _.paused = true; 28872 28873 28874 28875 }; 28876 28877 28878 28879 Slick.prototype.play = Slick.prototype.slickPlay = function() { 28880 28881 28882 28883 var _ = this; 28884 28885 28886 28887 _.autoPlay(); 28888 28889 _.options.autoplay = true; 28890 28891 _.paused = false; 28892 28893 _.focussed = false; 28894 28895 _.interrupted = false; 28896 28897 28898 28899 }; 28900 28901 28902 28903 Slick.prototype.postSlide = function(index) { 28904 28905 28906 28907 var _ = this; 28908 28909 28910 28911 if( !_.unslicked ) { 28912 28913 28914 28915 _.$slider.trigger('afterChange', [_, index]); 28916 28917 28918 28919 _.animating = false; 28920 28921 28922 28923 if (_.slideCount > _.options.slidesToShow) { 28924 28925 _.setPosition(); 28926 28927 } 28928 28929 28930 28931 _.swipeLeft = null; 28932 28933 28934 28935 if ( _.options.autoplay ) { 28936 28937 _.autoPlay(); 28938 28939 } 28940 28941 28942 28943 if (_.options.accessibility === true) { 28944 28945 _.initADA(); 28946 28947 28948 28949 if (_.options.focusOnChange) { 28950 28951 var $currentSlide = $(_.$slides.get(_.currentSlide)); 28952 28953 $currentSlide.attr('tabindex', 0).focus(); 28954 28955 } 28956 28957 } 28958 28959 28960 28961 } 28962 28963 28964 28965 }; 28966 28967 28968 28969 Slick.prototype.prev = Slick.prototype.slickPrev = function() { 28970 28971 28972 28973 var _ = this; 28974 28975 28976 28977 _.changeSlide({ 28978 28979 data: { 28980 28981 message: 'previous' 28982 28983 } 28984 28985 }); 28986 28987 28988 28989 }; 28990 28991 28992 28993 Slick.prototype.preventDefault = function(event) { 28994 28995 28996 28997 event.preventDefault(); 28998 28999 29000 29001 }; 29002 29003 29004 29005 Slick.prototype.progressiveLazyLoad = function( tryCount ) { 29006 29007 29008 29009 tryCount = tryCount || 1; 29010 29011 29012 29013 var _ = this, 29014 29015 $imgsToLoad = $( 'img[data-lazy]', _.$slider ), 29016 29017 image, 29018 29019 imageSource, 29020 29021 imageSrcSet, 29022 29023 imageSizes, 29024 29025 imageToLoad; 29026 29027 29028 29029 if ( $imgsToLoad.length ) { 29030 29031 29032 29033 image = $imgsToLoad.first(); 29034 29035 imageSource = image.attr('data-lazy'); 29036 29037 imageSrcSet = image.attr('data-srcset'); 29038 29039 imageSizes = image.attr('data-sizes') || _.$slider.attr('data-sizes'); 29040 29041 imageToLoad = document.createElement('img'); 29042 29043 29044 29045 imageToLoad.onload = function() { 29046 29047 29048 29049 if (imageSrcSet) { 29050 29051 image 29052 29053 .attr('srcset', imageSrcSet ); 29054 29055 29056 29057 if (imageSizes) { 29058 29059 image 29060 29061 .attr('sizes', imageSizes ); 29062 29063 } 29064 29065 } 29066 29067 29068 29069 image 29070 29071 .attr( 'src', imageSource ) 29072 29073 .removeAttr('data-lazy data-srcset data-sizes') 29074 29075 .removeClass('slick-loading'); 29076 29077 29078 29079 if ( _.options.adaptiveHeight === true ) { 29080 29081 _.setPosition(); 29082 29083 } 29084 29085 29086 29087 _.$slider.trigger('lazyLoaded', [ _, image, imageSource ]); 29088 29089 _.progressiveLazyLoad(); 29090 29091 29092 29093 }; 29094 29095 29096 29097 imageToLoad.onerror = function() { 29098 29099 29100 29101 if ( tryCount < 3 ) { 29102 29103 29104 29105 /** 29106 29107 * try to load the image 3 times, 29108 29109 * leave a slight delay so we don't get 29110 29111 * servers blocking the request. 29112 29113 */ 29114 29115 setTimeout( function() { 29116 29117 _.progressiveLazyLoad( tryCount + 1 ); 29118 29119 }, 500 ); 29120 29121 29122 29123 } else { 29124 29125 29126 29127 image 29128 29129 .removeAttr( 'data-lazy' ) 29130 29131 .removeClass( 'slick-loading' ) 29132 29133 .addClass( 'slick-lazyload-error' ); 29134 29135 29136 29137 _.$slider.trigger('lazyLoadError', [ _, image, imageSource ]); 29138 29139 29140 29141 _.progressiveLazyLoad(); 29142 29143 29144 29145 } 29146 29147 29148 29149 }; 29150 29151 29152 29153 imageToLoad.src = imageSource; 29154 29155 29156 29157 } else { 29158 29159 29160 29161 _.$slider.trigger('allImagesLoaded', [ _ ]); 29162 29163 29164 29165 } 29166 29167 29168 29169 }; 29170 29171 29172 29173 Slick.prototype.refresh = function( initializing ) { 29174 29175 29176 29177 var _ = this, currentSlide, lastVisibleIndex; 29178 29179 29180 29181 lastVisibleIndex = _.slideCount - _.options.slidesToShow; 29182 29183 29184 29185 // in non-infinite sliders, we don't want to go past the 29186 29187 // last visible index. 29188 29189 if( !_.options.infinite && ( _.currentSlide > lastVisibleIndex )) { 29190 29191 _.currentSlide = lastVisibleIndex; 29192 29193 } 29194 29195 29196 29197 // if less slides than to show, go to start. 29198 29199 if ( _.slideCount <= _.options.slidesToShow ) { 29200 29201 _.currentSlide = 0; 29202 29203 29204 29205 } 29206 29207 29208 29209 currentSlide = _.currentSlide; 29210 29211 29212 29213 _.destroy(true); 29214 29215 29216 29217 $.extend(_, _.initials, { currentSlide: currentSlide }); 29218 29219 29220 29221 _.init(); 29222 29223 29224 29225 if( !initializing ) { 29226 29227 29228 29229 _.changeSlide({ 29230 29231 data: { 29232 29233 message: 'index', 29234 29235 index: currentSlide 29236 29237 } 29238 29239 }, false); 29240 29241 29242 29243 } 29244 29245 29246 29247 }; 29248 29249 29250 29251 Slick.prototype.registerBreakpoints = function() { 29252 29253 29254 29255 var _ = this, breakpoint, currentBreakpoint, l, 29256 29257 responsiveSettings = _.options.responsive || null; 29258 29259 29260 29261 if ( $.type(responsiveSettings) === 'array' && responsiveSettings.length ) { 29262 29263 29264 29265 _.respondTo = _.options.respondTo || 'window'; 29266 29267 29268 29269 for ( breakpoint in responsiveSettings ) { 29270 29271 29272 29273 l = _.breakpoints.length-1; 29274 29275 29276 29277 if (responsiveSettings.hasOwnProperty(breakpoint)) { 29278 29279 currentBreakpoint = responsiveSettings[breakpoint].breakpoint; 29280 29281 29282 29283 // loop through the breakpoints and cut out any existing 29284 29285 // ones with the same breakpoint number, we don't want dupes. 29286 29287 while( l >= 0 ) { 29288 29289 if( _.breakpoints[l] && _.breakpoints[l] === currentBreakpoint ) { 29290 29291 _.breakpoints.splice(l,1); 29292 29293 } 29294 29295 l--; 29296 29297 } 29298 29299 29300 29301 _.breakpoints.push(currentBreakpoint); 29302 29303 _.breakpointSettings[currentBreakpoint] = responsiveSettings[breakpoint].settings; 29304 29305 29306 29307 } 29308 29309 29310 29311 } 29312 29313 29314 29315 _.breakpoints.sort(function(a, b) { 29316 29317 return ( _.options.mobileFirst ) ? a-b : b-a; 29318 29319 }); 29320 29321 29322 29323 } 29324 29325 29326 29327 }; 29328 29329 29330 29331 Slick.prototype.reinit = function() { 29332 29333 29334 29335 var _ = this; 29336 29337 29338 29339 _.$slides = 29340 29341 _.$slideTrack 29342 29343 .children(_.options.slide) 29344 29345 .addClass('slick-slide'); 29346 29347 29348 29349 _.slideCount = _.$slides.length; 29350 29351 29352 29353 if (_.currentSlide >= _.slideCount && _.currentSlide !== 0) { 29354 29355 _.currentSlide = _.currentSlide - _.options.slidesToScroll; 29356 29357 } 29358 29359 29360 29361 if (_.slideCount <= _.options.slidesToShow) { 29362 29363 _.currentSlide = 0; 29364 29365 } 29366 29367 29368 29369 _.registerBreakpoints(); 29370 29371 29372 29373 _.setProps(); 29374 29375 _.setupInfinite(); 29376 29377 _.buildArrows(); 29378 29379 _.updateArrows(); 29380 29381 _.initArrowEvents(); 29382 29383 _.buildDots(); 29384 29385 _.updateDots(); 29386 29387 _.initDotEvents(); 29388 29389 _.cleanUpSlideEvents(); 29390 29391 _.initSlideEvents(); 29392 29393 29394 29395 _.checkResponsive(false, true); 29396 29397 29398 29399 if (_.options.focusOnSelect === true) { 29400 29401 $(_.$slideTrack).children().on('click.slick', _.selectHandler); 29402 29403 } 29404 29405 29406 29407 _.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0); 29408 29409 29410 29411 _.setPosition(); 29412 29413 _.focusHandler(); 29414 29415 29416 29417 _.paused = !_.options.autoplay; 29418 29419 _.autoPlay(); 29420 29421 29422 29423 _.$slider.trigger('reInit', [_]); 29424 29425 29426 29427 }; 29428 29429 29430 29431 Slick.prototype.resize = function() { 29432 29433 29434 29435 var _ = this; 29436 29437 29438 29439 if ($(window).width() !== _.windowWidth) { 29440 29441 clearTimeout(_.windowDelay); 29442 29443 _.windowDelay = window.setTimeout(function() { 29444 29445 _.windowWidth = $(window).width(); 29446 29447 _.checkResponsive(); 29448 29449 if( !_.unslicked ) { _.setPosition(); } 29450 29451 }, 50); 29452 29453 } 29454 29455 }; 29456 29457 29458 29459 Slick.prototype.removeSlide = Slick.prototype.slickRemove = function(index, removeBefore, removeAll) { 29460 29461 29462 29463 var _ = this; 29464 29465 29466 29467 if (typeof(index) === 'boolean') { 29468 29469 removeBefore = index; 29470 29471 index = removeBefore === true ? 0 : _.slideCount - 1; 29472 29473 } else { 29474 29475 index = removeBefore === true ? --index : index; 29476 29477 } 29478 29479 29480 29481 if (_.slideCount < 1 || index < 0 || index > _.slideCount - 1) { 29482 29483 return false; 29484 29485 } 29486 29487 29488 29489 _.unload(); 29490 29491 29492 29493 if (removeAll === true) { 29494 29495 _.$slideTrack.children().remove(); 29496 29497 } else { 29498 29499 _.$slideTrack.children(this.options.slide).eq(index).remove(); 29500 29501 } 29502 29503 29504 29505 _.$slides = _.$slideTrack.children(this.options.slide); 29506 29507 29508 29509 _.$slideTrack.children(this.options.slide).detach(); 29510 29511 29512 29513 _.$slideTrack.append(_.$slides); 29514 29515 29516 29517 _.$slidesCache = _.$slides; 29518 29519 29520 29521 _.reinit(); 29522 29523 29524 29525 }; 29526 29527 29528 29529 Slick.prototype.setCSS = function(position) { 29530 29531 29532 29533 var _ = this, 29534 29535 positionProps = {}, 29536 29537 x, y; 29538 29539 29540 29541 if (_.options.rtl === true) { 29542 29543 position = -position; 29544 29545 } 29546 29547 x = _.positionProp == 'left' ? Math.ceil(position) + 'px' : '0px'; 29548 29549 y = _.positionProp == 'top' ? Math.ceil(position) + 'px' : '0px'; 29550 29551 29552 29553 positionProps[_.positionProp] = position; 29554 29555 29556 29557 if (_.transformsEnabled === false) { 29558 29559 _.$slideTrack.css(positionProps); 29560 29561 } else { 29562 29563 positionProps = {}; 29564 29565 if (_.cssTransitions === false) { 29566 29567 positionProps[_.animType] = 'translate(' + x + ', ' + y + ')'; 29568 29569 _.$slideTrack.css(positionProps); 29570 29571 } else { 29572 29573 positionProps[_.animType] = 'translate3d(' + x + ', ' + y + ', 0px)'; 29574 29575 _.$slideTrack.css(positionProps); 29576 29577 } 29578 29579 } 29580 29581 29582 29583 }; 29584 29585 29586 29587 Slick.prototype.setDimensions = function() { 29588 29589 29590 29591 var _ = this; 29592 29593 29594 29595 if (_.options.vertical === false) { 29596 29597 if (_.options.centerMode === true) { 29598 29599 _.$list.css({ 29600 29601 padding: ('0px ' + _.options.centerPadding) 29602 29603 }); 29604 29605 } 29606 29607 } else { 29608 29609 _.$list.height(_.$slides.first().outerHeight(true) * _.options.slidesToShow); 29610 29611 if (_.options.centerMode === true) { 29612 29613 _.$list.css({ 29614 29615 padding: (_.options.centerPadding + ' 0px') 29616 29617 }); 29618 29619 } 29620 29621 } 29622 29623 29624 29625 _.listWidth = _.$list.width(); 29626 29627 _.listHeight = _.$list.height(); 29628 29629 29630 29631 29632 29633 if (_.options.vertical === false && _.options.variableWidth === false) { 29634 29635 _.slideWidth = Math.ceil(_.listWidth / _.options.slidesToShow); 29636 29637 _.$slideTrack.width(Math.ceil((_.slideWidth * _.$slideTrack.children('.slick-slide').length))); 29638 29639 29640 29641 } else if (_.options.variableWidth === true) { 29642 29643 _.$slideTrack.width(5000 * _.slideCount); 29644 29645 } else { 29646 29647 _.slideWidth = Math.ceil(_.listWidth); 29648 29649 _.$slideTrack.height(Math.ceil((_.$slides.first().outerHeight(true) * _.$slideTrack.children('.slick-slide').length))); 29650 29651 } 29652 29653 29654 29655 var offset = _.$slides.first().outerWidth(true) - _.$slides.first().width(); 29656 29657 if (_.options.variableWidth === false) _.$slideTrack.children('.slick-slide').width(_.slideWidth - offset); 29658 29659 29660 29661 }; 29662 29663 29664 29665 Slick.prototype.setFade = function() { 29666 29667 29668 29669 var _ = this, 29670 29671 targetLeft; 29672 29673 29674 29675 _.$slides.each(function(index, element) { 29676 29677 targetLeft = (_.slideWidth * index) * -1; 29678 29679 if (_.options.rtl === true) { 29680 29681 $(element).css({ 29682 29683 position: 'relative', 29684 29685 right: targetLeft, 29686 29687 top: 0, 29688 29689 zIndex: _.options.zIndex - 2, 29690 29691 opacity: 0 29692 29693 }); 29694 29695 } else { 29696 29697 $(element).css({ 29698 29699 position: 'relative', 29700 29701 left: targetLeft, 29702 29703 top: 0, 29704 29705 zIndex: _.options.zIndex - 2, 29706 29707 opacity: 0 29708 29709 }); 29710 29711 } 29712 29713 }); 29714 29715 29716 29717 _.$slides.eq(_.currentSlide).css({ 29718 29719 zIndex: _.options.zIndex - 1, 29720 29721 opacity: 1 29722 29723 }); 29724 29725 29726 29727 }; 29728 29729 29730 29731 Slick.prototype.setHeight = function() { 29732 29733 29734 29735 var _ = this; 29736 29737 29738 29739 if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) { 29740 29741 var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true); 29742 29743 _.$list.css('height', targetHeight); 29744 29745 } 29746 29747 29748 29749 }; 29750 29751 29752 29753 Slick.prototype.setOption = 29754 29755 Slick.prototype.slickSetOption = function() { 29756 29757 29758 29759 /** 29760 29761 * accepts arguments in format of: 29762 29763 * 29764 29765 * - for changing a single option's value: 29766 29767 * .slick("setOption", option, value, refresh ) 29768 29769 * 29770 29771 * - for changing a set of responsive options: 29772 29773 * .slick("setOption", 'responsive', [{}, ...], refresh ) 29774 29775 * 29776 29777 * - for updating multiple values at once (not responsive) 29778 29779 * .slick("setOption", { 'option': value, ... }, refresh ) 29780 29781 */ 29782 29783 29784 29785 var _ = this, l, item, option, value, refresh = false, type; 29786 29787 29788 29789 if( $.type( arguments[0] ) === 'object' ) { 29790 29791 29792 29793 option = arguments[0]; 29794 29795 refresh = arguments[1]; 29796 29797 type = 'multiple'; 29798 29799 29800 29801 } else if ( $.type( arguments[0] ) === 'string' ) { 29802 29803 29804 29805 option = arguments[0]; 29806 29807 value = arguments[1]; 29808 29809 refresh = arguments[2]; 29810 29811 29812 29813 if ( arguments[0] === 'responsive' && $.type( arguments[1] ) === 'array' ) { 29814 29815 29816 29817 type = 'responsive'; 29818 29819 29820 29821 } else if ( typeof arguments[1] !== 'undefined' ) { 29822 29823 29824 29825 type = 'single'; 29826 29827 29828 29829 } 29830 29831 29832 29833 } 29834 29835 29836 29837 if ( type === 'single' ) { 29838 29839 29840 29841 _.options[option] = value; 29842 29843 29844 29845 29846 29847 } else if ( type === 'multiple' ) { 29848 29849 29850 29851 $.each( option , function( opt, val ) { 29852 29853 29854 29855 _.options[opt] = val; 29856 29857 29858 29859 }); 29860 29861 29862 29863 29864 29865 } else if ( type === 'responsive' ) { 29866 29867 29868 29869 for ( item in value ) { 29870 29871 29872 29873 if( $.type( _.options.responsive ) !== 'array' ) { 29874 29875 29876 29877 _.options.responsive = [ value[item] ]; 29878 29879 29880 29881 } else { 29882 29883 29884 29885 l = _.options.responsive.length-1; 29886 29887 29888 29889 // loop through the responsive object and splice out duplicates. 29890 29891 while( l >= 0 ) { 29892 29893 29894 29895 if( _.options.responsive[l].breakpoint === value[item].breakpoint ) { 29896 29897 29898 29899 _.options.responsive.splice(l,1); 29900 29901 29902 29903 } 29904 29905 29906 29907 l--; 29908 29909 29910 29911 } 29912 29913 29914 29915 _.options.responsive.push( value[item] ); 29916 29917 29918 29919 } 29920 29921 29922 29923 } 29924 29925 29926 29927 } 29928 29929 29930 29931 if ( refresh ) { 29932 29933 29934 29935 _.unload(); 29936 29937 _.reinit(); 29938 29939 29940 29941 } 29942 29943 29944 29945 }; 29946 29947 29948 29949 Slick.prototype.setPosition = function() { 29950 29951 29952 29953 var _ = this; 29954 29955 29956 29957 _.setDimensions(); 29958 29959 29960 29961 _.setHeight(); 29962 29963 29964 29965 if (_.options.fade === false) { 29966 29967 _.setCSS(_.getLeft(_.currentSlide)); 29968 29969 } else { 29970 29971 _.setFade(); 29972 29973 } 29974 29975 29976 29977 _.$slider.trigger('setPosition', [_]); 29978 29979 29980 29981 }; 29982 29983 29984 29985 Slick.prototype.setProps = function() { 29986 29987 29988 29989 var _ = this, 29990 29991 bodyStyle = document.body.style; 29992 29993 29994 29995 _.positionProp = _.options.vertical === true ? 'top' : 'left'; 29996 29997 29998 29999 if (_.positionProp === 'top') { 30000 30001 _.$slider.addClass('slick-vertical'); 30002 30003 } else { 30004 30005 _.$slider.removeClass('slick-vertical'); 30006 30007 } 30008 30009 30010 30011 if (bodyStyle.WebkitTransition !== undefined || 30012 30013 bodyStyle.MozTransition !== undefined || 30014 30015 bodyStyle.msTransition !== undefined) { 30016 30017 if (_.options.useCSS === true) { 30018 30019 _.cssTransitions = true; 30020 30021 } 30022 30023 } 30024 30025 30026 30027 if ( _.options.fade ) { 30028 30029 if ( typeof _.options.zIndex === 'number' ) { 30030 30031 if( _.options.zIndex < 3 ) { 30032 30033 _.options.zIndex = 3; 30034 30035 } 30036 30037 } else { 30038 30039 _.options.zIndex = _.defaults.zIndex; 30040 30041 } 30042 30043 } 30044 30045 30046 30047 if (bodyStyle.OTransform !== undefined) { 30048 30049 _.animType = 'OTransform'; 30050 30051 _.transformType = '-o-transform'; 30052 30053 _.transitionType = 'OTransition'; 30054 30055 if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false; 30056 30057 } 30058 30059 if (bodyStyle.MozTransform !== undefined) { 30060 30061 _.animType = 'MozTransform'; 30062 30063 _.transformType = '-moz-transform'; 30064 30065 _.transitionType = 'MozTransition'; 30066 30067 if (bodyStyle.perspectiveProperty === undefined && bodyStyle.MozPerspective === undefined) _.animType = false; 30068 30069 } 30070 30071 if (bodyStyle.webkitTransform !== undefined) { 30072 30073 _.animType = 'webkitTransform'; 30074 30075 _.transformType = '-webkit-transform'; 30076 30077 _.transitionType = 'webkitTransition'; 30078 30079 if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false; 30080 30081 } 30082 30083 if (bodyStyle.msTransform !== undefined) { 30084 30085 _.animType = 'msTransform'; 30086 30087 _.transformType = '-ms-transform'; 30088 30089 _.transitionType = 'msTransition'; 30090 30091 if (bodyStyle.msTransform === undefined) _.animType = false; 30092 30093 } 30094 30095 if (bodyStyle.transform !== undefined && _.animType !== false) { 30096 30097 _.animType = 'transform'; 30098 30099 _.transformType = 'transform'; 30100 30101 _.transitionType = 'transition'; 30102 30103 } 30104 30105 _.transformsEnabled = _.options.useTransform && (_.animType !== null && _.animType !== false); 30106 30107 }; 30108 30109 30110 30111 30112 30113 Slick.prototype.setSlideClasses = function(index) { 30114 30115 30116 30117 var _ = this, 30118 30119 centerOffset, allSlides, indexOffset, remainder; 30120 30121 30122 30123 allSlides = _.$slider 30124 30125 .find('.slick-slide') 30126 30127 .removeClass('slick-active slick-center slick-current') 30128 30129 .attr('aria-hidden', 'true'); 30130 30131 30132 30133 _.$slides 30134 30135 .eq(index) 30136 30137 .addClass('slick-current'); 30138 30139 30140 30141 if (_.options.centerMode === true) { 30142 30143 30144 30145 var evenCoef = _.options.slidesToShow % 2 === 0 ? 1 : 0; 30146 30147 30148 30149 centerOffset = Math.floor(_.options.slidesToShow / 2); 30150 30151 30152 30153 if (_.options.infinite === true) { 30154 30155 30156 30157 if (index >= centerOffset && index <= (_.slideCount - 1) - centerOffset) { 30158 30159 _.$slides 30160 30161 .slice(index - centerOffset + evenCoef, index + centerOffset + 1) 30162 30163 .addClass('slick-active') 30164 30165 .attr('aria-hidden', 'false'); 30166 30167 30168 30169 } else { 30170 30171 30172 30173 indexOffset = _.options.slidesToShow + index; 30174 30175 allSlides 30176 30177 .slice(indexOffset - centerOffset + 1 + evenCoef, indexOffset + centerOffset + 2) 30178 30179 .addClass('slick-active') 30180 30181 .attr('aria-hidden', 'false'); 30182 30183 30184 30185 } 30186 30187 30188 30189 if (index === 0) { 30190 30191 30192 30193 allSlides 30194 30195 .eq(allSlides.length - 1 - _.options.slidesToShow) 30196 30197 .addClass('slick-center'); 30198 30199 30200 30201 } else if (index === _.slideCount - 1) { 30202 30203 30204 30205 allSlides 30206 30207 .eq(_.options.slidesToShow) 30208 30209 .addClass('slick-center'); 30210 30211 30212 30213 } 30214 30215 30216 30217 } 30218 30219 30220 30221 _.$slides 30222 30223 .eq(index) 30224 30225 .addClass('slick-center'); 30226 30227 30228 30229 } else { 30230 30231 30232 30233 if (index >= 0 && index <= (_.slideCount - _.options.slidesToShow)) { 30234 30235 30236 30237 _.$slides 30238 30239 .slice(index, index + _.options.slidesToShow) 30240 30241 .addClass('slick-active') 30242 30243 .attr('aria-hidden', 'false'); 30244 30245 30246 30247 } else if (allSlides.length <= _.options.slidesToShow) { 30248 30249 30250 30251 allSlides 30252 30253 .addClass('slick-active') 30254 30255 .attr('aria-hidden', 'false'); 30256 30257 30258 30259 } else { 30260 30261 30262 30263 remainder = _.slideCount % _.options.slidesToShow; 30264 30265 indexOffset = _.options.infinite === true ? _.options.slidesToShow + index : index; 30266 30267 30268 30269 if (_.options.slidesToShow == _.options.slidesToScroll && (_.slideCount - index) < _.options.slidesToShow) { 30270 30271 30272 30273 allSlides 30274 30275 .slice(indexOffset - (_.options.slidesToShow - remainder), indexOffset + remainder) 30276 30277 .addClass('slick-active') 30278 30279 .attr('aria-hidden', 'false'); 30280 30281 30282 30283 } else { 30284 30285 30286 30287 allSlides 30288 30289 .slice(indexOffset, indexOffset + _.options.slidesToShow) 30290 30291 .addClass('slick-active') 30292 30293 .attr('aria-hidden', 'false'); 30294 30295 30296 30297 } 30298 30299 30300 30301 } 30302 30303 30304 30305 } 30306 30307 30308 30309 if (_.options.lazyLoad === 'ondemand' || _.options.lazyLoad === 'anticipated') { 30310 30311 _.lazyLoad(); 30312 30313 } 30314 30315 }; 30316 30317 30318 30319 Slick.prototype.setupInfinite = function() { 30320 30321 30322 30323 var _ = this, 30324 30325 i, slideIndex, infiniteCount; 30326 30327 30328 30329 if (_.options.fade === true) { 30330 30331 _.options.centerMode = false; 30332 30333 } 30334 30335 30336 30337 if (_.options.infinite === true && _.options.fade === false) { 30338 30339 30340 30341 slideIndex = null; 30342 30343 30344 30345 if (_.slideCount > _.options.slidesToShow) { 30346 30347 30348 30349 if (_.options.centerMode === true) { 30350 30351 infiniteCount = _.options.slidesToShow + 1; 30352 30353 } else { 30354 30355 infiniteCount = _.options.slidesToShow; 30356 30357 } 30358 30359 30360 30361 for (i = _.slideCount; i > (_.slideCount - 30362 30363 infiniteCount); i -= 1) { 30364 30365 slideIndex = i - 1; 30366 30367 $(_.$slides[slideIndex]).clone(true).attr('id', '') 30368 30369 .attr('data-slick-index', slideIndex - _.slideCount) 30370 30371 .prependTo(_.$slideTrack).addClass('slick-cloned'); 30372 30373 } 30374 30375 for (i = 0; i < infiniteCount + _.slideCount; i += 1) { 30376 30377 slideIndex = i; 30378 30379 $(_.$slides[slideIndex]).clone(true).attr('id', '') 30380 30381 .attr('data-slick-index', slideIndex + _.slideCount) 30382 30383 .appendTo(_.$slideTrack).addClass('slick-cloned'); 30384 30385 } 30386 30387 _.$slideTrack.find('.slick-cloned').find('[id]').each(function() { 30388 30389 $(this).attr('id', ''); 30390 30391 }); 30392 30393 30394 30395 } 30396 30397 30398 30399 } 30400 30401 30402 30403 }; 30404 30405 30406 30407 Slick.prototype.interrupt = function( toggle ) { 30408 30409 30410 30411 var _ = this; 30412 30413 30414 30415 if( !toggle ) { 30416 30417 _.autoPlay(); 30418 30419 } 30420 30421 _.interrupted = toggle; 30422 30423 30424 30425 }; 30426 30427 30428 30429 Slick.prototype.selectHandler = function(event) { 30430 30431 30432 30433 var _ = this; 30434 30435 30436 30437 var targetElement = 30438 30439 $(event.target).is('.slick-slide') ? 30440 30441 $(event.target) : 30442 30443 $(event.target).parents('.slick-slide'); 30444 30445 30446 30447 var index = parseInt(targetElement.attr('data-slick-index')); 30448 30449 30450 30451 if (!index) index = 0; 30452 30453 30454 30455 if (_.slideCount <= _.options.slidesToShow) { 30456 30457 30458 30459 _.slideHandler(index, false, true); 30460 30461 return; 30462 30463 30464 30465 } 30466 30467 30468 30469 _.slideHandler(index); 30470 30471 30472 30473 }; 30474 30475 30476 30477 Slick.prototype.slideHandler = function(index, sync, dontAnimate) { 30478 30479 30480 30481 var targetSlide, animSlide, oldSlide, slideLeft, targetLeft = null, 30482 30483 _ = this, navTarget; 30484 30485 30486 30487 sync = sync || false; 30488 30489 30490 30491 if (_.animating === true && _.options.waitForAnimate === true) { 30492 30493 return; 30494 30495 } 30496 30497 30498 30499 if (_.options.fade === true && _.currentSlide === index) { 30500 30501 return; 30502 30503 } 30504 30505 30506 30507 if (sync === false) { 30508 30509 _.asNavFor(index); 30510 30511 } 30512 30513 30514 30515 targetSlide = index; 30516 30517 targetLeft = _.getLeft(targetSlide); 30518 30519 slideLeft = _.getLeft(_.currentSlide); 30520 30521 30522 30523 _.currentLeft = _.swipeLeft === null ? slideLeft : _.swipeLeft; 30524 30525 30526 30527 if (_.options.infinite === false && _.options.centerMode === false && (index < 0 || index > _.getDotCount() * _.options.slidesToScroll)) { 30528 30529 if (_.options.fade === false) { 30530 30531 targetSlide = _.currentSlide; 30532 30533 if (dontAnimate !== true && _.slideCount > _.options.slidesToShow) { 30534 30535 _.animateSlide(slideLeft, function() { 30536 30537 _.postSlide(targetSlide); 30538 30539 }); 30540 30541 } else { 30542 30543 _.postSlide(targetSlide); 30544 30545 } 30546 30547 } 30548 30549 return; 30550 30551 } else if (_.options.infinite === false && _.options.centerMode === true && (index < 0 || index > (_.slideCount - _.options.slidesToScroll))) { 30552 30553 if (_.options.fade === false) { 30554 30555 targetSlide = _.currentSlide; 30556 30557 if (dontAnimate !== true && _.slideCount > _.options.slidesToShow) { 30558 30559 _.animateSlide(slideLeft, function() { 30560 30561 _.postSlide(targetSlide); 30562 30563 }); 30564 30565 } else { 30566 30567 _.postSlide(targetSlide); 30568 30569 } 30570 30571 } 30572 30573 return; 30574 30575 } 30576 30577 30578 30579 if ( _.options.autoplay ) { 30580 30581 clearInterval(_.autoPlayTimer); 30582 30583 } 30584 30585 30586 30587 if (targetSlide < 0) { 30588 30589 if (_.slideCount % _.options.slidesToScroll !== 0) { 30590 30591 animSlide = _.slideCount - (_.slideCount % _.options.slidesToScroll); 30592 30593 } else { 30594 30595 animSlide = _.slideCount + targetSlide; 30596 30597 } 30598 30599 } else if (targetSlide >= _.slideCount) { 30600 30601 if (_.slideCount % _.options.slidesToScroll !== 0) { 30602 30603 animSlide = 0; 30604 30605 } else { 30606 30607 animSlide = targetSlide - _.slideCount; 30608 30609 } 30610 30611 } else { 30612 30613 animSlide = targetSlide; 30614 30615 } 30616 30617 30618 30619 _.animating = true; 30620 30621 30622 30623 _.$slider.trigger('beforeChange', [_, _.currentSlide, animSlide]); 30624 30625 30626 30627 oldSlide = _.currentSlide; 30628 30629 _.currentSlide = animSlide; 30630 30631 30632 30633 _.setSlideClasses(_.currentSlide); 30634 30635 30636 30637 if ( _.options.asNavFor ) { 30638 30639 30640 30641 navTarget = _.getNavTarget(); 30642 30643 navTarget = navTarget.slick('getSlick'); 30644 30645 30646 30647 if ( navTarget.slideCount <= navTarget.options.slidesToShow ) { 30648 30649 navTarget.setSlideClasses(_.currentSlide); 30650 30651 } 30652 30653 30654 30655 } 30656 30657 30658 30659 _.updateDots(); 30660 30661 _.updateArrows(); 30662 30663 30664 30665 if (_.options.fade === true) { 30666 30667 if (dontAnimate !== true) { 30668 30669 30670 30671 _.fadeSlideOut(oldSlide); 30672 30673 30674 30675 _.fadeSlide(animSlide, function() { 30676 30677 _.postSlide(animSlide); 30678 30679 }); 30680 30681 30682 30683 } else { 30684 30685 _.postSlide(animSlide); 30686 30687 } 30688 30689 _.animateHeight(); 30690 30691 return; 30692 30693 } 30694 30695 30696 30697 if (dontAnimate !== true && _.slideCount > _.options.slidesToShow) { 30698 30699 _.animateSlide(targetLeft, function() { 30700 30701 _.postSlide(animSlide); 30702 30703 }); 30704 30705 } else { 30706 30707 _.postSlide(animSlide); 30708 30709 } 30710 30711 30712 30713 }; 30714 30715 30716 30717 Slick.prototype.startLoad = function() { 30718 30719 30720 30721 var _ = this; 30722 30723 30724 30725 if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { 30726 30727 30728 30729 _.$prevArrow.hide(); 30730 30731 _.$nextArrow.hide(); 30732 30733 30734 30735 } 30736 30737 30738 30739 if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { 30740 30741 30742 30743 _.$dots.hide(); 30744 30745 30746 30747 } 30748 30749 30750 30751 _.$slider.addClass('slick-loading'); 30752 30753 30754 30755 }; 30756 30757 30758 30759 Slick.prototype.swipeDirection = function() { 30760 30761 30762 30763 var xDist, yDist, r, swipeAngle, _ = this; 30764 30765 30766 30767 xDist = _.touchObject.startX - _.touchObject.curX; 30768 30769 yDist = _.touchObject.startY - _.touchObject.curY; 30770 30771 r = Math.atan2(yDist, xDist); 30772 30773 30774 30775 swipeAngle = Math.round(r * 180 / Math.PI); 30776 30777 if (swipeAngle < 0) { 30778 30779 swipeAngle = 360 - Math.abs(swipeAngle); 30780 30781 } 30782 30783 30784 30785 if ((swipeAngle <= 45) && (swipeAngle >= 0)) { 30786 30787 return (_.options.rtl === false ? 'left' : 'right'); 30788 30789 } 30790 30791 if ((swipeAngle <= 360) && (swipeAngle >= 315)) { 30792 30793 return (_.options.rtl === false ? 'left' : 'right'); 30794 30795 } 30796 30797 if ((swipeAngle >= 135) && (swipeAngle <= 225)) { 30798 30799 return (_.options.rtl === false ? 'right' : 'left'); 30800 30801 } 30802 30803 if (_.options.verticalSwiping === true) { 30804 30805 if ((swipeAngle >= 35) && (swipeAngle <= 135)) { 30806 30807 return 'down'; 30808 30809 } else { 30810 30811 return 'up'; 30812 30813 } 30814 30815 } 30816 30817 30818 30819 return 'vertical'; 30820 30821 30822 30823 }; 30824 30825 30826 30827 Slick.prototype.swipeEnd = function(event) { 30828 30829 30830 30831 var _ = this, 30832 30833 slideCount, 30834 30835 direction; 30836 30837 30838 30839 _.dragging = false; 30840 30841 _.swiping = false; 30842 30843 30844 30845 if (_.scrolling) { 30846 30847 _.scrolling = false; 30848 30849 return false; 30850 30851 } 30852 30853 30854 30855 _.interrupted = false; 30856 30857 _.shouldClick = ( _.touchObject.swipeLength > 10 ) ? false : true; 30858 30859 30860 30861 if ( _.touchObject.curX === undefined ) { 30862 30863 return false; 30864 30865 } 30866 30867 30868 30869 if ( _.touchObject.edgeHit === true ) { 30870 30871 _.$slider.trigger('edge', [_, _.swipeDirection() ]); 30872 30873 } 30874 30875 30876 30877 if ( _.touchObject.swipeLength >= _.touchObject.minSwipe ) { 30878 30879 30880 30881 direction = _.swipeDirection(); 30882 30883 30884 30885 switch ( direction ) { 30886 30887 30888 30889 case 'left': 30890 30891 case 'down': 30892 30893 30894 30895 slideCount = 30896 30897 _.options.swipeToSlide ? 30898 30899 _.checkNavigable( _.currentSlide + _.getSlideCount() ) : 30900 30901 _.currentSlide + _.getSlideCount(); 30902 30903 30904 30905 _.currentDirection = 0; 30906 30907 30908 30909 break; 30910 30911 30912 30913 case 'right': 30914 30915 case 'up': 30916 30917 30918 30919 slideCount = 30920 30921 _.options.swipeToSlide ? 30922 30923 _.checkNavigable( _.currentSlide - _.getSlideCount() ) : 30924 30925 _.currentSlide - _.getSlideCount(); 30926 30927 30928 30929 _.currentDirection = 1; 30930 30931 30932 30933 break; 30934 30935 30936 30937 default: 30938 30939 30940 30941 30942 30943 } 30944 30945 30946 30947 if( direction != 'vertical' ) { 30948 30949 30950 30951 _.slideHandler( slideCount ); 30952 30953 _.touchObject = {}; 30954 30955 _.$slider.trigger('swipe', [_, direction ]); 30956 30957 30958 30959 } 30960 30961 30962 30963 } else { 30964 30965 30966 30967 if ( _.touchObject.startX !== _.touchObject.curX ) { 30968 30969 30970 30971 _.slideHandler( _.currentSlide ); 30972 30973 _.touchObject = {}; 30974 30975 30976 30977 } 30978 30979 30980 30981 } 30982 30983 30984 30985 }; 30986 30987 30988 30989 Slick.prototype.swipeHandler = function(event) { 30990 30991 30992 30993 var _ = this; 30994 30995 30996 30997 if ((_.options.swipe === false) || ('ontouchend' in document && _.options.swipe === false)) { 30998 30999 return; 31000 31001 } else if (_.options.draggable === false && event.type.indexOf('mouse') !== -1) { 31002 31003 return; 31004 31005 } 31006 31007 31008 31009 _.touchObject.fingerCount = event.originalEvent && event.originalEvent.touches !== undefined ? 31010 31011 event.originalEvent.touches.length : 1; 31012 31013 31014 31015 _.touchObject.minSwipe = _.listWidth / _.options 31016 31017 .touchThreshold; 31018 31019 31020 31021 if (_.options.verticalSwiping === true) { 31022 31023 _.touchObject.minSwipe = _.listHeight / _.options 31024 31025 .touchThreshold; 31026 31027 } 31028 31029 31030 31031 switch (event.data.action) { 31032 31033 31034 31035 case 'start': 31036 31037 _.swipeStart(event); 31038 31039 break; 31040 31041 31042 31043 case 'move': 31044 31045 _.swipeMove(event); 31046 31047 break; 31048 31049 31050 31051 case 'end': 31052 31053 _.swipeEnd(event); 31054 31055 break; 31056 31057 31058 31059 } 31060 31061 31062 31063 }; 31064 31065 31066 31067 Slick.prototype.swipeMove = function(event) { 31068 31069 31070 31071 var _ = this, 31072 31073 edgeWasHit = false, 31074 31075 curLeft, swipeDirection, swipeLength, positionOffset, touches, verticalSwipeLength; 31076 31077 31078 31079 touches = event.originalEvent !== undefined ? event.originalEvent.touches : null; 31080 31081 31082 31083 if (!_.dragging || _.scrolling || touches && touches.length !== 1) { 31084 31085 return false; 31086 31087 } 31088 31089 31090 31091 curLeft = _.getLeft(_.currentSlide); 31092 31093 31094 31095 _.touchObject.curX = touches !== undefined ? touches[0].pageX : event.clientX; 31096 31097 _.touchObject.curY = touches !== undefined ? touches[0].pageY : event.clientY; 31098 31099 31100 31101 _.touchObject.swipeLength = Math.round(Math.sqrt( 31102 31103 Math.pow(_.touchObject.curX - _.touchObject.startX, 2))); 31104 31105 31106 31107 verticalSwipeLength = Math.round(Math.sqrt( 31108 31109 Math.pow(_.touchObject.curY - _.touchObject.startY, 2))); 31110 31111 31112 31113 if (!_.options.verticalSwiping && !_.swiping && verticalSwipeLength > 4) { 31114 31115 _.scrolling = true; 31116 31117 return false; 31118 31119 } 31120 31121 31122 31123 if (_.options.verticalSwiping === true) { 31124 31125 _.touchObject.swipeLength = verticalSwipeLength; 31126 31127 } 31128 31129 31130 31131 swipeDirection = _.swipeDirection(); 31132 31133 31134 31135 if (event.originalEvent !== undefined && _.touchObject.swipeLength > 4) { 31136 31137 _.swiping = true; 31138 31139 event.preventDefault(); 31140 31141 } 31142 31143 31144 31145 positionOffset = (_.options.rtl === false ? 1 : -1) * (_.touchObject.curX > _.touchObject.startX ? 1 : -1); 31146 31147 if (_.options.verticalSwiping === true) { 31148 31149 positionOffset = _.touchObject.curY > _.touchObject.startY ? 1 : -1; 31150 31151 } 31152 31153 31154 31155 31156 31157 swipeLength = _.touchObject.swipeLength; 31158 31159 31160 31161 _.touchObject.edgeHit = false; 31162 31163 31164 31165 if (_.options.infinite === false) { 31166 31167 if ((_.currentSlide === 0 && swipeDirection === 'right') || (_.currentSlide >= _.getDotCount() && swipeDirection === 'left')) { 31168 31169 swipeLength = _.touchObject.swipeLength * _.options.edgeFriction; 31170 31171 _.touchObject.edgeHit = true; 31172 31173 } 31174 31175 } 31176 31177 31178 31179 if (_.options.vertical === false) { 31180 31181 _.swipeLeft = curLeft + swipeLength * positionOffset; 31182 31183 } else { 31184 31185 _.swipeLeft = curLeft + (swipeLength * (_.$list.height() / _.listWidth)) * positionOffset; 31186 31187 } 31188 31189 if (_.options.verticalSwiping === true) { 31190 31191 _.swipeLeft = curLeft + swipeLength * positionOffset; 31192 31193 } 31194 31195 31196 31197 if (_.options.fade === true || _.options.touchMove === false) { 31198 31199 return false;
31200 31201 } 31202 31203 31204 31205 if (_.animating === true) { 31206 31207 _.swipeLeft = null; 31208 31209 return false; 31210 31211 } 31212 31213 31214 31215 _.setCSS(_.swipeLeft); 31216 31217 31218 31219 }; 31220 31221 31222 31223 Slick.prototype.swipeStart = function(event) { 31224 31225 31226 31227 var _ = this, 31228 31229 touches; 31230 31231 31232 31233 _.interrupted = true; 31234 31235 31236 31237 if (_.touchObject.fingerCount !== 1 || _.slideCount <= _.options.slidesToShow) { 31238 31239 _.touchObject = {}; 31240 31241 return false; 31242 31243 } 31244 31245 31246 31247 if (event.originalEvent !== undefined && event.originalEvent.touches !== undefined) { 31248 31249 touches = event.originalEvent.touches[0]; 31250 31251 } 31252 31253 31254 31255 _.touchObject.startX = _.touchObject.curX = touches !== undefined ? touches.pageX : event.clientX; 31256 31257 _.touchObject.startY = _.touchObject.curY = touches !== undefined ? touches.pageY : event.clientY; 31258 31259 31260 31261 _.dragging = true; 31262 31263 31264 31265 }; 31266 31267 31268 31269 Slick.prototype.unfilterSlides = Slick.prototype.slickUnfilter = function() { 31270 31271 31272 31273 var _ = this; 31274 31275 31276 31277 if (_.$slidesCache !== null) { 31278 31279 31280 31281 _.unload(); 31282 31283 31284 31285 _.$slideTrack.children(this.options.slide).detach(); 31286 31287 31288 31289 _.$slidesCache.appendTo(_.$slideTrack); 31290 31291 31292 31293 _.reinit(); 31294 31295 31296 31297 } 31298 31299 31300 31301 }; 31302 31303 31304 31305 Slick.prototype.unload = function() { 31306 31307 31308 31309 var _ = this; 31310 31311 31312 31313 $('.slick-cloned', _.$slider).remove(); 31314 31315 31316 31317 if (_.$dots) { 31318 31319 _.$dots.remove(); 31320 31321 } 31322 31323 31324 31325 if (_.$prevArrow && _.htmlExpr.test(_.options.prevArrow)) { 31326 31327 _.$prevArrow.remove(); 31328 31329 } 31330 31331 31332 31333 if (_.$nextArrow && _.htmlExpr.test(_.options.nextArrow)) { 31334 31335 _.$nextArrow.remove(); 31336 31337 } 31338 31339 31340 31341 _.$slides 31342 31343 .removeClass('slick-slide slick-active slick-visible slick-current') 31344 31345 .attr('aria-hidden', 'true') 31346 31347 .css('width', ''); 31348 31349 31350 31351 }; 31352 31353 31354 31355 Slick.prototype.unslick = function(fromBreakpoint) { 31356 31357 31358 31359 var _ = this; 31360 31361 _.$slider.trigger('unslick', [_, fromBreakpoint]); 31362 31363 _.destroy(); 31364 31365 31366 31367 }; 31368 31369 31370 31371 Slick.prototype.updateArrows = function() { 31372 31373 31374 31375 var _ = this, 31376 31377 centerOffset; 31378 31379 31380 31381 centerOffset = Math.floor(_.options.slidesToShow / 2); 31382 31383 31384 31385 if ( _.options.arrows === true && 31386 31387 _.slideCount > _.options.slidesToShow && 31388 31389 !_.options.infinite ) { 31390 31391 31392 31393 _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 31394 31395 _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 31396 31397 31398 31399 if (_.currentSlide === 0) { 31400 31401 31402 31403 _.$prevArrow.addClass('slick-disabled').attr('aria-disabled', 'true'); 31404 31405 _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 31406 31407 31408 31409 } else if (_.currentSlide >= _.slideCount - _.options.slidesToShow && _.options.centerMode === false) { 31410 31411 31412 31413 _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true'); 31414 31415 _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 31416 31417 31418 31419 } else if (_.currentSlide >= _.slideCount - 1 && _.options.centerMode === true) { 31420 31421 31422 31423 _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true'); 31424 31425 _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 31426 31427 31428 31429 } 31430 31431 31432 31433 } 31434 31435 31436 31437 }; 31438 31439 31440 31441 Slick.prototype.updateDots = function() { 31442 31443 31444 31445 var _ = this; 31446 31447 31448 31449 if (_.$dots !== null) { 31450 31451 31452 31453 _.$dots 31454 31455 .find('li') 31456 31457 .removeClass('slick-active') 31458 31459 .end(); 31460 31461 31462 31463 _.$dots 31464 31465 .find('li') 31466 31467 .eq(Math.floor(_.currentSlide / _.options.slidesToScroll)) 31468 31469 .addClass('slick-active'); 31470 31471 31472 31473 } 31474 31475 31476 31477 }; 31478 31479 31480 31481 Slick.prototype.visibility = function() { 31482 31483 31484 31485 var _ = this; 31486 31487 31488 31489 if ( _.options.autoplay ) { 31490 31491 31492 31493 if ( document[_.hidden] ) { 31494 31495 31496 31497 _.interrupted = true; 31498 31499 31500 31501 } else { 31502 31503 31504 31505 _.interrupted = false; 31506 31507 31508 31509 } 31510 31511 31512 31513 } 31514 31515 31516 31517 }; 31518 31519 31520 31521 $.fn.slick = function() { 31522 31523 var _ = this, 31524 31525 opt = arguments[0], 31526 31527 args = Array.prototype.slice.call(arguments, 1), 31528 31529 l = _.length, 31530 31531 i, 31532 31533 ret; 31534 31535 for (i = 0; i < l; i++) { 31536 31537 if (typeof opt == 'object' || typeof opt == 'undefined') 31538 31539 _[i].slick = new Slick(_[i], opt); 31540 31541 else 31542 31543 ret = _[i].slick[opt].apply(_[i].slick, args); 31544 31545 if (typeof ret != 'undefined') return ret; 31546 31547 } 31548 31549 return _; 31550 31551 }; 31552 31553 31554 31555})); 31556 31557 31558var YHA = YHA || {INIT_FUNC:{},RESPON_FUNC:{}}; 31559 31560 31561 31562(function($) { 31563 31564 //responsive 31565 31566 var window_height = 0; 31567 31568 var window_width = 0; 31569 31570 var responsive_timeout = null; 31571 31572 var get_screen_size = function() { 31573 31574 var t = $("body").css("top"); 31575 31576 if (t == "-2px") 31577 31578 return "small"; 31579 31580 else if (t == "-1px") 31581 31582 return "medium"; 31583 31584 else 31585 31586 return "large"; 31587 31588 }; 31589 31590 31591 31592 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 31593 31594 YHA.RESPON_FUNC = YHA.RESPON_FUNC || {}; 31595 31596 YHA.RESPON_NO_DELAY_FUNC = YHA.RESPON_NO_DELAY_FUNC || {}; 31597 31598 YHA.INIT_FUNC['default'] = {}; 31599 31600 YHA.RESPON_FUNC['default'] = {}; 31601 31602 YHA.RESPON_NO_DELAY_FUNC['default'] = {}; 31603 31604 YHA.SCREEN_SIZE = get_screen_size(); 31605 31606 31607 31608 //INIT 31609 31610 YHA.INIT_FUNC['default']['search'] = function(){ 31611 31612 var $top_menu = $("#top-menubar"); 31613 31614 var $searchbar = $("#top-search"); 31615 31616 if($searchbar.length){ 31617 31618 $("#btn-searchbar").bind("click",function(){ 31619 31620 var $btn = $(this); 31621 31622 if($btn.hasClass('active')){ 31623 31624 $btn.removeClass('active'); 31625 31626 $searchbar.removeClass("respon-show"); 31627 31628 }else{ 31629 31630 $("#top-control-bar .btn").removeClass('active'); 31631 31632 $btn.addClass('active'); 31633 31634 $searchbar.addClass("respon-show"); 31635 31636 $top_menu.removeClass("respon-show"); 31637 31638 } 31639 31640 }); 31641 31642 } 31643 31644 }; 31645 31646 31647 31648 YHA.RESPON_NO_DELAY_FUNC['default']['topmenu'] = function() { 31649 31650 var current_screen_size = YHA.SCREEN_SIZE; 31651 31652 YHA.SCREEN_SIZE = get_screen_size(); 31653 31654 31655 31656 if (current_screen_size !== YHA.SCREEN_SIZE) { 31657 31658 // Screen size changed 31659 31660 if (YHA.SCREEN_SIZE === "large") 31661 31662 $("#menu-top .hover").removeClass("hover"); 31663 31664 31665 31666 if (YHA.SCREEN_SIZE === "medium" && current_screen_size === "large") { 31667 31668 $("#btn-menu").removeClass("active"); 31669 31670 $("#top-menubar").removeClass("respon-show"); 31671 31672 } 31673 31674 } 31675 31676 }; 31677 31678 31679 31680 YHA.INIT_FUNC['default']['topmenu'] = function() { 31681 31682 var $top_menu = $("#top-menubar"); 31683 31684 var $searchbar = $("#top-search"); 31685 31686 if($top_menu.length){ 31687 31688 $("#btn-menu").bind("click",function(){ 31689 31690 var $btn = $(this); 31691 31692 if($btn.hasClass('active')){ 31693 31694 $btn.removeClass('active'); 31695 31696 $top_menu.removeClass("respon-show"); 31697 31698 }else{ 31699 31700 $("#top-control-bar .btn").removeClass('active'); 31701 31702 $btn.addClass('active'); 31703 31704 $top_menu.addClass("respon-show"); 31705 31706 $searchbar.removeClass("respon-show"); 31707 31708 } 31709 31710 }); 31711 31712 $("#menu-top >nav > ul >li").each(function(){ 31713 31714 var $menu = $(this), 31715 31716 $menus = $("#menu-top >nav >ul >li"), 31717 31718 $btn = $('> a',$menu); 31719 31720 $btn.bind('click',function(e){ 31721 31722 if (Modernizr.mq('(max-width: 980px)')) { 31723 31724 e.stopPropagation(); 31725 31726 e.preventDefault(); 31727 31728 } 31729 31730 if($menu.find(".submenu").length){ 31731 31732 if($menu.hasClass('hover')){ 31733 31734 $menus.removeClass('hover'); 31735 31736 }else{ 31737 31738 $menus.removeClass('hover'); 31739 31740 if (YHA.SCREEN_SIZE !== "large") 31741 31742 $menu.addClass('hover'); 31743 31744 } 31745 31746 } 31747 31748 }); 31749 31750// $btn.bind('mouseout',function(){ 31751 31752// $menu.removeClass('hover'); 31753 31754// }); 31755 31756 }); 31757 31758 } 31759 31760 }; 31761 31762 31763 31764 YHA.INIT_FUNC['default']['banner'] = function(){ 31765 31766 var $banners = $('.banner'); 31767 31768 var $slidershow = $('#home-slidershow'); 31769 31770 if($banners.length){ 31771 31772 var success = 0; 31773 31774 var images = []; 31775 31776 var length = $banners.length; 31777 31778 31779 31780 $banners.each(function(index){ 31781 31782 var $banner = $(this); 31783 31784 var image = document.createElement('img'); 31785 31786 image.src = $banner.attr("yha-bg"); 31787 31788 $(image).load(function(){ 31789 31790 success++; 31791 31792 images[index] = { 31793
31794 width: this.naturalWidth, 31795 31796 height: this.naturalHeight 31797 31798 }; 31799 31800 $banner.css('backgroundImage','url('+this.src+')'); 31801 31802 if(success == length){ 31803 31804 // YHA.RESPON_FUNC['default'].slider = function(callback){ 31805 31806 // if($banners.length && $(window).width() > 1024){ 31807 31808 // var window_width = $(window).outerWidth(true); 31809 31810 // var max_height = 0; 31811 31812 // for(var i = 0; i < length; ++i){ 31813 31814 // var slide_height = images[i].height * window_width/images[i].width; 31815 31816 // max_height = max_height < slide_height ? slide_height : max_height; 31817 31818 // } 31819 31820 // $('.banner').css({'height':max_height}); 31821 31822 // }else{ 31823 31824 // $('.banner').css({'height':'auto'}); 31825 31826 // } 31827 31828 // }; 31829 31830 31831 31832 if($slidershow.length){ 31833 31834 if($slidershow.slick){ 31835 31836 $slidershow.on('init', function(slick){ 31837 31838 $slidershow.delay(500).fadeIn(1, function() { 31839 31840 $slidershow.addClass("slider_loaded"); 31841 31842 }); 31843 31844 }); 31845 31846 var slider = $slidershow.slick({ 31847 31848 dots: true, 31849 31850 infinite: true, 31851 31852 autoplay: true, 31853 31854 arrows: false, 31855 31856 pauseOnHover : false, 31857 31858 autoplaySpeed: 5000, 31859 31860 customPaging: function(slider, i) { 31861 31862 return '<a class="btn font-rs" data-role="none" role="button" tabindex="0">0' + (i + 1) + '</a>'; 31863 31864 }, 31865 31866 responsive: [ 31867 31868 { 31869 31870 breakpoint: 540, 31871 31872 settings: { 31873 31874 dots: false, 31875 31876 } 31877 31878 } 31879 31880 ] 31881 31882 }); 31883 31884 $('#slidershow-wrapper .btn-play-pause').click(function() { 31885 31886 console.log($(this).attr('data-status')); 31887 31888 if($(this).attr('data-status') == 'playing') { 31889 31890 console.log('pausing'); 31891 31892 $slidershow.slick('slickPause'); 31893 31894 $(this).attr('data-status', 'paused'); 31895 31896 } else { 31897 31898 console.log('playing'); 31899 31900 $slidershow.slick('slickPlay'); 31901 31902 $(this).attr('data-status', 'playing'); 31903 31904 } 31905 31906 }); 31907 31908 /* 31909 31910 console.log($slidershow); 31911 31912 $slidershow.on('init',function(slick){ 31913 31914 alert("init2"); 31915 31916 $slidershow.css({opacity: 1}); 31917 31918 //YHA.RESPON_FUNC['default'].slider(); 31919 31920 }); 31921 31922 */ 31923 31924 } 31925 31926 }else{ 31927 31928 // YHA.RESPON_FUNC['default'].slider(); 31929 31930 } 31931 31932 } 31933 31934 }); 31935 31936 }); 31937 31938 } 31939 31940 }; 31941 31942 31943 31944 31945 31946 YHA.INIT_FUNC['default']['langs_switcher'] = function(){ 31947 31948 var $switcher = $('#font-size-switcher'); 31949 31950 if($switcher.length){ 31951 31952 YHA.common.fontSize = Cookies.get('font-size')?Cookies.get('font-size'):'font-m'; 31953 31954 fontSizeSwitch(YHA.common.fontSize); 31955 31956 $('.btn',$switcher).bind('click',function(){ 31957 31958 var $btn = $(this); 31959 31960 var key = $btn.parent().attr('id'); 31961 31962 if(!$btn.hasClass('active')){ 31963 31964 $('.btn',$switcher).removeClass('active'); 31965 31966 fontSizeSwitch(key); 31967 31968 } 31969 31970 return false; 31971 31972 }); 31973 31974 } 31975 31976 function fontSizeSwitch(key){ 31977 31978 var class_name = 'page-'+key; 31979 31980 Cookies.set('font-size', key, { expires: 365 }); 31981 31982 $('body').attr('class',function(){ 31983 31984 var className = $(this).attr("class"); 31985 31986 if(/page-font-[a-zA-Z0-9_-]*/.test(className)) { 31987 31988 className = className.replace(/page-font-[a-zA-Z0-9_-]*/, class_name); 31989 31990 }else{ 31991 31992 className += " "+class_name; 31993 31994 } 31995 31996 return className; 31997 31998 }); 31999 32000 $('#'+key+' .btn').addClass('active'); 32001 32002 YHA.common.fontSize = key; 32003 32004 } 32005 32006 }; 32007 32008 32009 32010 YHA.INIT_FUNC['default']['back-to-top'] = function(){ 32011 32012 var $btn = $('#btn-scrolltop'); 32013 32014 if($btn.length){ 32015 32016 $btn.bind('click',function(){ 32017 32018 $("html, body").animate({scrollTop: 0}, 1000); 32019 32020 }); 32021 32022 } 32023 32024 }; 32025 32026 32027 32028 YHA.INIT_FUNC['default']['slidershow'] = function(){ 32029 32030 var $sliershows = $('.slidershow'); 32031 32032 if($sliershows.length){ 32033 32034 $sliershows.slick({ 32035 32036 autoplay: true, 32037 32038 autoplaySpeed: 5000, 32039 32040 dots: true, 32041 32042 infinite: true, 32043
32044 arrows: false, 32045 32046 }); 32047 32048 } 32049 32050 }; 32051 32052 32053 32054 32055 32056 YHA.INIT_FUNC['default']['map'] = function(){ 32057 32058 var $maps = $('.acf-map'); 32059 32060 var maps = []; 32061 32062 if($maps.length){ 32063 32064 32065 32066 /* 32067 32068 * new_map 32069 32070 * 32071 32072 * This function will render a Google Map onto the selected jQuery element 32073 32074 * 32075 32076 * @type function 32077 32078 * @date 8/11/2013 32079 32080 * @since 4.3.0 32081 32082 * 32083 32084 * @param $el (jQuery element) 32085 32086 * @return n/a 32087 32088 */ 32089 32090 function new_map( $el ) { 32091 32092 // var 32093 32094 var $markers = $el.find('.marker'); 32095 32096 // vars 32097 32098 var args = { 32099 32100 zoom : 16, 32101 32102 center : new google.maps.LatLng(0, 0), 32103 32104 mapTypeId : google.maps.MapTypeId.ROADMAP 32105 32106 }; 32107 32108 // create map 32109 32110 var map = new google.maps.Map( $el[0], args); 32111 32112 // add a markers reference 32113 32114 map.markers = []; 32115 32116 32117 32118 // add markers 32119 32120 $markers.each(function(){ 32121 32122 32123 32124 add_marker( $(this), map ); 32125 32126 32127 32128 }); 32129 32130 // center map 32131 32132 center_map( map ); 32133 32134 // return 32135 32136 return map; 32137 32138 32139 32140 } 32141 32142 32143 32144 /* 32145 32146 * add_marker 32147 32148 * 32149 32150 * This function will add a marker to the selected Google Map 32151 32152 * 32153 32154 * @type function 32155 32156 * @date 8/11/2013 32157 32158 * @since 4.3.0 32159 32160 * 32161 32162 * @param $marker (jQuery element) 32163 32164 * @param map (Google Map object) 32165 32166 * @return n/a 32167 32168 */ 32169 32170 32171 32172 function add_marker( $marker, map ) { 32173 32174 32175 32176 // var 32177 32178 var latlng = new google.maps.LatLng( $marker.attr('data-lat'), $marker.attr('data-lng') ); 32179 32180 32181 32182 // create marker 32183 32184 var marker = new google.maps.Marker({ 32185 32186 position : latlng, 32187 32188 map : map 32189 32190 }); 32191 32192 32193 32194 // add to array 32195 32196 map.markers.push( marker ); 32197 32198 32199 32200 // if marker contains HTML, add it to an infoWindow 32201 32202 if( $marker.html() ) 32203 32204 { 32205 32206 // create info window 32207 32208 var infowindow = new google.maps.InfoWindow({ 32209 32210 content : $marker.html() 32211 32212 }); 32213 32214 32215 32216 // show info window when marker is clicked 32217 32218 google.maps.event.addListener(marker, 'click', function() { 32219 32220 32221 32222 infowindow.open( map, marker ); 32223 32224 32225 32226 }); 32227 32228 } 32229 32230 } 32231 32232 32233 32234 /* 32235 32236 * center_map 32237 32238 * 32239 32240 * This function will center the map, showing all markers attached to this map 32241 32242 * 32243 32244 * @type function 32245 32246 * @date 8/11/2013 32247 32248 * @since 4.3.0 32249 32250 * 32251 32252 * @param map (Google Map object) 32253 32254 * @return n/a 32255 32256 */ 32257 32258 32259 32260 function center_map( map ) { 32261 32262 // vars 32263 32264 var bounds = new google.maps.LatLngBounds(); 32265 32266 32267 32268 // loop through all markers and create bounds 32269 32270 $.each( map.markers, function( i, marker ){ 32271 32272 var latlng = new google.maps.LatLng( marker.position.lat(), marker.position.lng() ); 32273 32274 bounds.extend( latlng ); 32275 32276 }); 32277 32278 32279 32280 // only 1 marker? 32281 32282 if( map.markers.length == 1 ) 32283 32284 { 32285 32286 // set center of map 32287 32288 map.setCenter( bounds.getCenter() ); 32289 32290 map.setZoom( 16 ); 32291 32292 } 32293 32294 else 32295 32296 { 32297 32298 // fit to bounds 32299 32300 map.fitBounds( bounds ); 32301 32302 } 32303 32304 } 32305 32306 32307 32308 $('.acf-map').each(function(index){ 32309 32310 var $map = $(this); 32311 32312 var toggled = false; 32313 32314 var $tab = $map.parents('[role=tabpanel]').eq(0); 32315 32316 if($tab.length && !$tab.hasClass('active')){ 32317 32318 var id = $tab.attr('id'); 32319 32320 $("#"+id).on('toggled', function (event, tab) { 32321 32322 if(!toggled){ 32323 32324 initMap(); 32325 32326 toggled = true; 32327 32328 } 32329 32330 }); 32331 32332 }else{ 32333 32334 initMap(); 32335 32336 toggled = true; 32337 32338 } 32339 32340 function initMap(){ 32341 32342 maps[index] = new_map($map); 32343 32344 }; 32345 32346 }); 32347 32348 YHA.RESPON_FUNC['default']['map'] = function(){ 32349 32350 var length = maps.length; 32351 32352 for(var i=0; i < length; ++i){ 32353 32354 if(maps[i]){ 32355 32356 google.maps.event.trigger(maps[i], 'resize'); 32357 32358 } 32359 32360 } 32361 32362 }; 32363 32364 } 32365 32366 }; 32367 32368 32369 32370 YHA.INIT_FUNC['default']['fieldset'] = function(){ 32371 32372 var $fieldsets = $('fieldset'); 32373 32374 if($fieldsets.length){ 32375 32376 $fieldsets.each(function(){ 32377 32378 var $fieldset = $(this); 32379 32380 var $tab = $fieldset.parents('[role=tabpanel]').eq(0); 32381 32382 var toggled = false; 32383 32384 $('legend',$fieldset).bind("click",function(){ 32385 32386 if ($fieldset.hasClass("opened")) 32387 32388 $fieldset.removeClass("opened").find(".fieldset-content").stop(true,false).slideUp(300); 32389 32390 else 32391 32392 $fieldset.addClass("opened").find(".fieldset-content").stop(true,fal
32392se).slideDown(300); 32393 32394 }); 32395 32396 }); 32397 32398 32399 32400 } 32401 32402 }; 32403 32404 32405 32406 YHA.INIT_FUNC['default']['fieldset-list'] = function(){ 32407 32408 var $fieldset_lists = $('.fieldset-list'); 32409 32410 if($fieldset_lists.length){ 32411 32412 $fieldset_lists.each(function(){ 32413 32414 var $fieldset_list = $(this); 32415 32416 $('fieldset',$fieldset_list).each(function(index){ 32417 32418 var $legend = $("legend",this); 32419 32420 var text = $legend.text(); 32421 32422 32423 32424 if ($fieldset_list.hasClass("wo-num")) 32425 32426 $legend.html(text+'<i class="fa"></i>'); 32427 32428 else 32429 32430 $legend.html('<span>'+(index+1)+'</span>'+text+'<i class="fa"></i>'); 32431 32432 }); 32433 32434 }); 32435 32436 32437 32438 } 32439 32440 }; 32441 32442 32443 32444 YHA.INIT_FUNC['default']['tab-selecter'] = function(){ 32445 32446 var $tab_selecters = $('.tabs-selecter'); 32447 32448 if($tab_selecters.length){ 32449 32450 $tab_selecters.each(function(){ 32451 32452 var $tabs = $('.tabs',this); 32453 32454 var $selecter = $('select',this); 32455 32456 if($("[role=tabpanel].active",$tab_selecters).length){ 32457 32458 var id = $("[role=tabpanel].active",$tab_selecters).attr('id'); 32459
32460 if($selecter.val() != id){ 32461 32462 $selecter.val(id); 32463 32464 } 32465 32466 } 32467 32468 $("[role=tabpanel]",$tab_selecters).on('toggled', function (event, tab) { 32469 32470 var id = $(this).attr('id'); 32471 32472 if($selecter.val() != id){ 32473 32474 $selecter.val(id); 32475 32476 } 32477 32478 }); 32479 32480 32481 32482 $selecter.bind('change',function(){ 32483 32484 var value = $(this).val(); 32485 32486 var $tab = $('[role=tab][href=#'+value+']'); 32487 32488 $tab.click(); 32489 32490 }); 32491 32492 }); 32493 32494 } 32495 32496 }; 32497 32498 32499 32500 YHA.INIT_FUNC['default']['slidebar-icon-link'] = function(){ 32501 32502 var $slidebar_icons = $(".slidebar-icon[href]"); 32503 32504 if($slidebar_icons.length){ 32505 32506 $slidebar_icons.each(function(){ 32507 32508 var $btn = $(this); 32509 32510 var id = $btn.attr('href'); 32511 32512 $btn.bind("click",function(){ 32513 32514 $('[role=tab][href='+id+']').click(); 32515 32516 return false; 32517 32518 }); 32519 32520 }); 32521 32522 } 32523 32524 }; 32525 32526 32527 32528 YHA.INIT_FUNC['default']['highlighted-articles'] = function(){ 32529 32530 $('.masonryAreaWrapper').masonry({ 32531 32532 itemSelector: '.article', 32533 32534 percentPosition: true 32535 32536 }); 32537 32538 }; 32539 32540 32541 32542 $( document ).ready(function() { 32543 32544 NProgress.configure({ parent: 'header' }); 32545 32546 NProgress.start(); 32547 32548 $(document).foundation(); 32549 32550 $(document).waitForImages(function() { 32551 32552 for (var selector in YHA.INIT_FUNC) { 32553 32554 if(YHA.INIT_FUNC[selector] && (selector == 'default' || $(selector).length)){ 32555 32556 for(var fun_key in YHA.INIT_FUNC[selector]){ 32557 32558 if ( typeof YHA.INIT_FUNC[selector][fun_key] === 'function') { 32559 32560 YHA.INIT_FUNC[selector][fun_key].call(this); 32561 32562 } 32563 32564 } 32565 32566 } 32567 32568 } 32569 32570 setTimeout(function(){ 32571 32572 NProgress.done(); 32573 32574 // $('#nprogress').removeAttr(); 32575 32576 $('header').append('<div id="nprogress"><div class="bar"></div></div>'); 32577 32578 // console.log('test4'); 32579 32580 },500); 32581 32582 }); 32583 32584 32585 32586 var fbShare = function(url, winWidth, winHeight) { 32587 32588 var winTop = (screen.height / 2) - (winHeight / 2); 32589 32590 var winLeft = (screen.width / 2) - (winWidth / 2); 32591 32592 //window.open('http://www.facebook.com/sharer.php?s=100&p[title]=' + title + '&p[summary]=' + descr + '&p[url]=' + url + '&p[images][0]=' + image, 'sharer', 'top=' + winTop + ',left=' + winLeft + ',toolbar=0,status=0,width=' + winWidth + ',height=' + winHeight); 32593 32594 window.open("https://www.facebook.com/dialog/share?app_id=1661737634114011&display=popup&href=" + url, '_blank', 'top=' + winTop + ',left=' + winLeft + ',toolbar=0,status=0,width=' + winWidth + ',height=' + winHeight); 32595 32596 }; 32597 32598 32599 32600 $("#sharefb").on("click", function(e) { 32601 32602 e.preventDefault(); 32603 32604 //window.open("http://www.facebook.com/sharer/sharer.php?u=" + window.url + "", "_blank"); 32605 32606 32607 32608 fbShare(window.url, 520,350); 32609 32610 32611 32612 /* 32613 32614 FB.ui({ 32615 32616 method: 'share', 32617 32618 href: window.url, 32619 32620 }, function(response){ 32621 32622 console.log(response); 32623 32624 32625 32626 }); 32627 32628 */ 32629 32630 }); 32631 32632 }); 32633 32634 YHA.INIT_FUNC['default']['announcement'] = function(){ 32635 32636 $('#announcements .announcement .close').click(function() { 32637 32638 Cookies.set('announcement_' + $(this).parents('.announcement').attr('data-id') + '_closed', true); 32639 32640 }); 32641 32642 }; 32643 32644 $(window).resize(function() { 32645 32646 if (responsive_timeout) { 32647 32648 clearTimeout(responsive_timeout); 32649 32650 responsive_timeout = null; 32651 32652 } 32653 32654 responsive_timeout = setTimeout(function() { 32655 32656 if (window_width !== $(window).width() || window_height !== $(window).height()) { 32657 32658 window_width = $(window).width(); 32659 32660 window_height = $(window).height(); 32661 32662 for (var selector in YHA.RESPON_FUNC) { 32663 32664 if(YHA.RESPON_FUNC[selector] && (selector == 'default' || $(selector).length)){ 32665 32666 for(var fun_key in YHA.RESPON_FUNC[selector]){ 32667 32668 if ( typeof YHA.RESPON_FUNC[selector][fun_key] === 'function') { 32669 32670 YHA.RESPON_FUNC[selector][fun_key].call(this); 32671 32672 } 32673 32674 } 32675 32676 } 32677 32678 } 32679 32680 } 32681 32682 }, 1000); 32683 32684 32685 32686 for (var selector in YHA.RESPON_NO_DELAY_FUNC) { 32687 32688 if(YHA.RESPON_NO_DELAY_FUNC[selector] && (selector == 'default' || $(selector).length)){ 32689 32690 for(var fun_key in YHA.RESPON_NO_DELAY_FUNC[selector]){ 32691 32692 if ( typeof YHA.RESPON_NO_DELAY_FUNC[selector][fun_key] === 'function') { 32693 32694 YHA.RESPON_NO_DELAY_FUNC[selector][fun_key].call(this); 32695 32696 } 32697 32698 } 32699 32700 } 32701 32702 } 32703 32704 }); 32705 32706})(jQuery); 32707var YHA = YHA || {}; 32708 32709 32710 32711(function($) { 32712 32713 var body_selector = ".page-gallery-detail", 32714 32715 $body_selector = $(body_selector), 32716 32717 $masonry = $body_selector.find(".masonryAreaWrapper"), 32718 32719 $loadMore = $body_selector.find(".loadWrapper .btn"); 32720 32721 32722 32723 var page = 1, count = 4; 32724 32725 //INIT 32726 32727 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 32728 32729 YHA.RESPON_FUNC = YHA.RESPON_FUNC || {}; 32730 32731 YHA.INIT_FUNC[body_selector] = {}; 32732 32733 YHA.RESPON_FUNC[body_selector] = {}; 32734 32735 32736 32737 function initPopup() { 32738 32739 $masonry.magnificPopup({ 32740 32741 delegate: 'div > a', 32742 32743 type: 'inline', 32744 32745 mainClass: 'mfp-img-mobile', 32746 32747 showCloseBtn: false, 32748 32749 gallery: { 32750 32751 enabled: true, // set to true to enable gallery 32752 32753 navigateByImgClick: true, 32754 32755 arrowMarkup: '', // markup of an arrow button 32756 32757 }, 32758 32759 image: { 32760 32761 tError: '<a href="%url%">The image #%curr%</a> could not be loaded.', 32762 32763 titleSrc: function(item) { 32764 32765 return item.el.attr('title') + '<small>by Marsel Van Oosten</small>'; 32766 32767 } 32768 32769 } 32770 32771 }) 32772 32773 } 32774 32775 32776 32777 function refreshPopup() { 32778 32779 $masonry.off('click.magnificpopup'); 32780 32781 $masonry.removeData('magnificPopup'); 32782 32783 initPopup(); 32784 32785 } 32786 32787 //INIT 32788 32789 YHA.INIT_FUNC[body_selector]['init'] = function(){ 32790 32791 initPopup(); 32792 32793 $loadMore.on("click", function(e) { 32794 32795 e.preventDefault(); 32796 32797 var $hiddenArticles = $masonry.find('.hidden-article').slice(0, count); 32798 32799 if($hiddenArticles.length > 0) { 32800 32801 $hiddenArticles.each(function(index, item){ 32802 32803 var newBlock = $(item); 32804 32805 newBlock.removeClass('hidden-article').addClass('article'); 32806 32807 //$masonry.find('.article').last().after(newBlock); 32808 32809 $masonry.masonry("appended", newBlock); 32810 32811 newBlock.find('img').load(function() { 32812 32813 $masonry.masonry('layout'); 32814 32815 }); 32816 32817 //$(item).remove(); 32818 32819 }); 32820 32821 $masonry.masonry('layout'); 32822 32823 //refreshPopup(); 32824 32825 } 32826 32827 32828 32829 if($hiddenArticles.length == 0 || $hiddenArticles.length < count) { 32830 32831 $(this).hide(); 32832 32833 } 32834 32835 }); 32836 32837 $body_selector.find('.arrow-left').click(function(){ 32838 32839 $.magnificPopup.instance.prev(); 32840 32841 }); 32842 32843 $body_selector.find('.arrow-right').click(function(){ 32844 32845 $.magnificPopup.instance.next(); 32846 32847 }); 32848 32849 }; 32850 32851 32852 32853 32854 32855})(jQuery); 32856var YHA = YHA || {INIT_FUNC:{},RESPON_FUNC:{}}; 32857 32858 32859 32860(function($) { 32861 32862 var body_selector = ".page-hostel-booking-enquiry"; 32863 32864 var loading = false, 32865 32866 $submitBtn = $("#btn-enter"), 32867 32868 txt1 = $submitBtn.html(), 32869 32870 txt2 = $submitBtn.attr("data-txt"); 32871 32872 function updateBookingSummary(booking_data) { 32873 32874 console.log('updateBookingSummary 11111') 32875 32876 var $bookin_summary = $('#booking-summary'); 32877 32878 $bookin_summary.find('.summary-hostel-name').text(booking_data['hostel_name']); 32879 32880 $bookin_summary.find('.summary-room-title').text(booking_data['room_type']); 32881 32882 $bookin_summary.find('.summary-rate-title').text(booking_data['rate_plan_name']); 32883 32884 $bookin_summary.find('.summary-checkin').text(moment(booking_data['checkin']).format('dddd, MMM DD, YYYY')); 32885 32886 $bookin_summary.find('.summary-checkout').text(moment(booking_data['checkout']).format('dddd, MMM DD, YYYY')); 32887 32888 $bookin_summary.find('.summary-rooms').text(booking_data['rooms']); 32889 32890 $bookin_summary.find('.summary-guests').text(booking_data['guests']); 32891 32892 $bookin_summary.find('.summary-nights').text(booking_data['nights']); 32893 32894 $bookin_summary.find('.summary-ref-id').text(booking_data['ref_id']); 32895 32896 $bookin_summary.find('.summary-total-price').text(booking_data['amount']); 32897 32898 $bookin_summary.find('.summary-guest').text(booking_data['guest_name']); 32899 32900 console.log(booking_data['hostel_rules_and_regulations']); 32901 32902 $('#hostel-rules').attr('src', booking_data['hostel_rules_and_regulations']); 32903 32904 $(document).foundation(); 32905 32906 } 32907 32908 //INIT 32909 32910 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 32911 32912 YHA.INIT_FUNC[body_selector] = {}; 32913 32914 32915 32916 YHA.INIT_FUNC[body_selector]['init'] = function(){ 32917 32918 if(window.booking_summary && window.booking_enquiry_ref_id) { 32919 32920 $('#summary-section').show(); 32921 32922 updateBookingSummary(window.booking_summary); 32923 32924 } else { 32925 32926 $('#form-section').show(); 32927 32928 } 32929 32930 $submitBtn.click(function() { 32931 32932 if(!loading) { 32933 32934 loading = true; 32935 32936 $submitBtn.html('<span><i class="fa"></i><p><i>' + txt2 + '</i></p></span>'); 32937 32938 var $enquiryForm = $('#enquiry-form'); 32939 32940 $enquiryForm.ajaxSubmit({ 32941 32942 url : YHA.common.base_url + "/api/hostel/enquiry_form_login", 32943 32944 success: function(response) { 32945 32946 loading = false;
32947 32948 $submitBtn.html(txt1); 32949 32950 if(response.status) { 32951 32952 $('#form-section').hide(); 32953 32954 $('#summary-section').show(); 32955 32956 updateBookingSummary(response['booking']); 32957 32958 // redirectToPaymentGateway(response); 32959 32960 } else { 32961 32962 var errorData = response.errors; 32963 32964 var allError = ""; 32965 32966 for(var i in errorData) { 32967 32968 allError = errorData[0]['msg']+'<br>'; 32969 32970 break; 32971 32972 } 32973 32974 YHA.common.popupError(allError); 32975 32976 } 32977 32978 }, 32979 32980 error: function() { 32981 32982 loading = false; 32983 32984 $submitBtn.html(txt1); 32985 32986 YHA.common.popupError('Network error'); 32987 32988 } 32989 32990 }); 32991 32992 } 32993 32994 }); 32995 32996 var $requestSubmitBtn = $('#btn-request-submit'); 32997 32998 var originalText = $requestSubmitBtn.html(); 32999 33000 $requestSubmitBtn.click(function() 33001 33002 { 33003 33004 if(!loading) { 33005 33006 var content = $("#request-content").val(); 33007 33008 var enquiry = $( "#request-type option:selected" ).text(); 33009 33010 loading = true; 33011 33012 $requestSubmitBtn.html(txt2); 33013 33014 $.post(YHA.common.base_url + "/api/hostel/enquiry_form", 33015 33016 { 33017 33018 'content' : content, 33019 33020 'enquiry' : enquiry, 33021 33022 'ref_id' : window.booking_enquiry_ref_id?window.booking_enquiry_ref_id:$('#order-confirmation-number').val() 33023 33024 },(function(response) 33025 33026 { 33027 33028 $requestSubmitBtn.html(originalText); 33029 33030 loading = false; 33031 33032 if(response.status) 33033 33034 { 33035 33036 YHA.common.popupError(response.msg); 33037 33038 }else 33039 33040 { 33041 33042 var allError =""; 33043 33044 var errorData = response.errors; 33045 33046 for(var i in errorData){ 33047 33048 allError = errorData[0]['msg']+'<br>'; 33049 33050 break; 33051 33052 } 33053 33054 YHA.common.popupError(allError); 33055 33056 } 33057 33058 33059 33060 }), 'json'); 33061 33062 } 33063 33064 }); 33065 33066 $('#btn-reset').click(function() { 33067 33068 $('#enquiry-form')[0].reset(); 33069 33070 }); 33071 33072 $('.btn-download').click(function() { 33073 33074 if($('#download-form').val()) { 33075 33076 window.open($('#download-form').val()); 33077 33078 } 33079 33080 }); 33081 33082 $('.btn-send').click(function() { 33083 33084 // var $this = $(this); 33085 33086 $.post(YHA.common.base_url + "/api/hostel/resendConfirmationEmail", { 'email' : $('#email-address').val(), 'ref_id' : window.booking_enquiry_ref_id?window.booking_enquiry_ref_id:$('#order-confirmation-number').val() }, function(response) { 33087 33088 if(response.status) { 33089 33090 YHA.common.popupError(response.message); 33091 33092 } else { 33093 33094 var errorData = response.errors; 33095 33096 var allError = ""; 33097 33098 for (var i in errorData) { 33099 33100 allError = errorData[0]['msg'] + '<br>'; 33101 33102 break; 33103 33104 } 33105 33106 YHA.common.popupError(allError); 33107 33108 } 33109 33110 }); 33111 33112 }); 33113 33114 }; 33115 33116})(jQuery); 33117var YHA = YHA || {INIT_FUNC: {}, RESPON_FUNC: {}}; 33118 33119 33120 33121(function ($) { 33122 33123 var body_selector = ".page-hostel-booking-detail"; 33124 33125 var loading = false, 33126 33127 $submitBtn = $("#btn-continuous"), 33128 33129 txt1 = $submitBtn.html(), 33130 33131 txt2 = $submitBtn.attr("data-txt"); 33132 33133 33134 33135 var guest_number_index = 0; 33136 33137 var roomData = []; 33138 33139 var searchingData = { 33140 33141 'hostel_id': $('#hostel-id').val() 33142 33143 }; 33144 33145 33146 33147 var lang = 'en'; 33148 33149 var booking_lang = 'eng'; 33150 33151 var booking_date_error_msg = ''; 33152 33153 var booking_guest_error_msg = ''; 33154 33155 var booking_rooms_error_msg = ''; 33156 33157 switch (YHA.common.lang) { 33158 33159 case 'zh': 33160 33161 lang = 'zh-TW'; 33162 33163 break; 33164 33165 case 'sc': 33166 33167 lang = 'zh-CN'; 33168 33169 break; 33170 33171 default: 33172 33173 lang = 'en'; 33174 33175 } 33176 33177 moment.locale(lang); 33178 33179 33180 33181 function redirectToPaymentGateway(response) { 33182 33183 window.onbeforeunload = null; 33184 33185 var hiddenForm = response.html; 33186 33187 $('#form-section').hide(); 33188 33189 $('#payment-processing').show(); 33190 33191 window.scrollTo(0, 0); 33192 33193 $(body_selector + ' .hidden-section').html(hiddenForm); 33194 33195 } 33196 33197 33198 33199 function numberWithCommas(price) { 33200 33201 return price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 33202 33203 } 33204 33205 33206 33207 function setSearchingData(key, value) { 33208 33209 searchingData[key] = value; 33210 33211 } 33212 33213 33214 33215 function showDetailPopup() { 33216 33217 $('.see-details').magnificPopup({ 33218 33219 type: 'ajax', 33220 33221 alignTop: true, 33222 33223 overflowY: 'scroll' // as we know that popup content is tall we set scroll overflow by default to avoid jump 33224 33225 }); 33226 33227 } 33228 33229 33230 33231 function insertGuestInfoTemplate(guest_number) { 33232 33233 var $html_template = $('#html-template'); 33234 33235 var $guestinfo_template = $html_template.find('#template-guest-info').html(); 33236 33237 $guestinfo_template = $guestinfo_template.replace(/{{guest_number}}/g, guest_number); 33238 33239 $('#guest-list').append('<li class="guest-info">' + $guestinfo_template + '</li>'); 33240 33241 } 33242 33243 33244 33245 function getAvaiableRooms() { 33246 33247 // var hostel_id = $('#hostel-id').val(); 33248 33249 // console.log(searchingData); 33250 33251 $('#room-type-list').empty(); 33252 33253 $('.loading-layer').css({'display': 'table'}); 33254 33255 $.get(YHA.common.base_url + '/api/hostel/searchRooms/', searchingData, function (response) { 33256 33257 $('.loading-layer').hide(); 33258 33259 if (response.data && response.data.length > 0) { 33260 33261 updateSearchResult(response.data); 33262 33263 } else { 33264 33265 $('#room-type-list').html('<span class="error">' + response.message + '</span>'); 33266 33267 } 33268 33269 }); 33270 33271 } 33272 33273 33274 33275 function showSection(page) { 33276 33277 if (page === '') { 33278 33279 return; 33280 33281 } 33282 33283 $('.contentWrapper').fadeOut(); 33284 33285 switch (page) { 33286 33287 case 'room-search' : 33288 33289 $('#room-search-section').show(); 33290 33291 break; 33292 33293 case 'form' : 33294 33295 $('#form-section').show(); 33296 33297 break; 33298 33299 } 33300 33301 $('html, body').animate({'scrollTop': $('#breadcrumb-section').offset().top}, 0); 33302 33303 } 33304 33305 33306 33307 function sortSearchResult(data) { 33308 33309 var sorting_key = $('select[name="sort-by"]').val(); 33310 33311 var result = data; 33312 33313 switch (sorting_key) { 33314 33315 case "room-rate-per-night": 33316 33317 result = data.sort(function (a, b) { 33318 33319 return a.lowest_price_non_formatted - b.lowest_price_non_formatted; 33320 33321 }); 33322 33323 break; 33324 33325 case "room-left": 33326 33327 result = data.sort(function (a, b) { 33328 33329 return b.rooms - a.rooms; 33330 33331 }); 33332 33333 break; 33334 33335 default: 33336 33337 result = data.sort(function (a, b) { 33338 33339 return a.lowest_price_non_formatted - b.lowest_price_non_formatted; 33340 33341 }); 33342 33343 } 33344 33345 33346 33347 var sold_out_list = []; 33348 33349 for (var i = 0; i < result.length; i++) { 33350 33351 if (result[i]['rooms'] == 0) { 33352 33353 sold_out_list.push(result[i]); 33354 33355 result.splice(i, 1); 33356 33357 } 33358 33359 } 33360 33361 console.log('Sorting'); 33362 33363 // console.log(sold_out_list); 33364 33365 return result.concat(sold_out_list); 33366 33367 } 33368 33369 33370 33371 function updateSearchResult(data) { 33372 33373 roomData = data; 33374 33375 sortSearchResult(data); 33376 33377 var $room_type_template = $('#template-room-type .room-type').clone(); 33378 33379 var $room_type_list = $('#room-type-list'); 33380 33381 $room_type_list.empty(); 33382 33383 // console.log(data.length); 33384 33385 for (var i = 0; i < data.length; i++) { 33386 33387 var newRoom = $room_type_template.clone(); 33388 33389 newRoom.find('.title').html(data[i]['title']); 33390 33391 newRoom.find('.description').html(data[i]['description']); 33392 33393 newRoom.find('.rooms-left').html(data[i]['room_left']); 33394 33395 newRoom.find('.price-wrap .lowest-price-by-room-type').html(data[i]['lowest_price']); 33396 33397 newRoom.find('.feature-image').html('<img src="' + data[i]['featured_image'] + '" />'); 33398 33399 newRoom.find('.see-details').attr('data-gallery', JSON.stringify(data[i]['gallery'])); 33400 33401 newRoom.find('.see-details').attr('data-facilities', JSON.stringify(data[i]['facilities'])); 33402 33403 newRoom.find('.type-text').text(data[i]['type_text']); 33404 33405 var $room_select = newRoom.find('select.rooms-select'); 33406 33407 $room_select.append('<option>' + data[i]['type_text'] + '</option>'); 33408 33409 for (var j = 1; j <= Math.min(data[i]['rooms'], 8); j++) { 33410 33411 if (j < data[i]['booking_quantity']) { 33412 33413 $room_select.append('<option data-status="disabled" value="' + j + '">' + j + '</option>'); 33414 33415 } else { 33416 33417 $room_select.append('<option value="' + j + '">' + j + '</option>'); 33418 33419 } 33420 33421 } 33422 33423 newRoom.attr('data-is-room', data[i]['is_room']); 33424 33425 newRoom.attr('data-booking-quantity', data[i]['booking_quantity']); 33426 33427 if (data[i]['rooms'] == 0) { 33428 33429 newRoom.find('.price-wrap').remove(); 33430 33431 newRoom.find('.btn-reserve').remove(); 33432 33433 } 33434
33435 var $room_rate_template = newRoom.find('.room-rate:first-child').clone(); 33436 33437 newRoom.find('.room-rates').empty(); 33438 33439 for (var rate_plan_id in data[i]['rate_plans']) { 33440 33441 var room_rate = data[i]['rate_plans'][rate_plan_id]; 33442 33443 var newRate = $room_rate_template.clone(); 33444 33445 newRate.find('.price').html(room_rate['average_price']); 33446 33447 newRate.find('.price').attr('data-total', room_rate['total_price']); 33448 33449 newRate.find('.type-text').text(data[i]['type_text']); 33450 33451 newRate.attr('data-hash', room_rate['hash']); 33452 33453 newRate.attr('data-type', room_rate['type']); 33454 33455 33456 33457 var type_of_room_rate = newRate.attr('data-type'); 33458 33459 var select_type = $('input[name="room-rate"]:checked').val(); 33460 33461 if (select_type !== undefined && type_of_room_rate != select_type) { 33462 33463 console.log('Adding Hide'); 33464 33465 newRate.addClass('hide'); 33466 33467 } 33468 33469 33470 33471 newRate.find('.room-rate-title').html(room_rate['title']); 33472 33473 if (room_rate['features']) { 33474 33475 newRate.find('.room-features').empty(); 33476 33477 for (var j = 0; j < room_rate['features'].length; j++) { 33478 33479 var $html = '<li class="room-feature" style=" background: url(' + room_rate['features'][j]['icon'] + ') no-repeat center left; background-size:20px 20px; ">' + room_rate['features'][j]['description'] + '</li>'; 33480 33481 newRate.find('.room-features').append($html); 33482 33483 } 33484 33485 } 33486 33487 // newRate.find('.room-feature-wifi').html(room_rate['wifi']); 33488 33489 // newRate.find('.room-feature-breakfast').html(room_rate['breakfast']); 33490 33491 // newRate.find('.room-feature-beverage').html(room_rate['beverage']); 33492 33493 newRoom.find('.room-rates').append(newRate); 33494 33495 } 33496 33497 $room_type_list.append(newRoom); 33498 33499 } 33500 33501 } 33502 33503 33504 33505 function showPoup(msg) { 33506 33507 $.magnificPopup.open({ 33508 33509 items: { 33510 33511 src: '<div class="error-popup popup-content">' + 33512 33513 '<div class="table error-content">' + 33514 33515 '<div class="table-cell">' + 33516 33517 msg + 33518 33519 '</div>' + 33520 33521 '</div>' + 33522 33523 '<div class="btn btn-cricle btn-close" onclick="$.magnificPopup.close();">' + 33524 33525 '<div class="table">' + 33526 33527 '<div class="table-cell">' + 33528 33529 'OK' + 33530 33531 '</div>' + 33532 33533 '</div>' + 33534 33535 '</div>' + 33536 33537 '</div>', 33538 33539 type: 'inline' 33540 33541 }, 33542 33543 fixedContentPos: true, 33544 33545 callbacks: { 33546 33547 close: function () { 33548 33549 // window.location.replace(YHA.common.base_url); 33550 33551 } 33552 33553 } 33554 33555 }); 33556 33557 } 33558 33559 33560 33561 function updateBookingSummary($room_type, $room_rate) { 33562 33563 console.log('updateBookingSummary 22222') 33564 33565 var $bookin_summary = $('#booking-summary'); 33566 33567 $bookin_summary.find('.summary-room-title').text($room_type.find('.title').text()); 33568 33569 $bookin_summary.find('.summary-rate-title').text($room_rate.find('.room-rate-title').text()); 33570 33571 $bookin_summary.find('.summary-checkin').text(moment(searchingData['checkin']).format('dddd, MMM DD, YYYY')); 33572 33573 $bookin_summary.find('.summary-checkout').text(moment(searchingData['checkout']).format('dddd, MMM DD, YYYY')); 33574 33575 $bookin_summary.find('.summary-rooms').text(searchingData['rooms']); 33576 33577 $bookin_summary.find('.summary-guests').text(searchingData['guests']); 33578 33579 $bookin_summary.find('.summary-nights').text(moment(searchingData['checkout']).diff(moment(searchingData['checkin']), 'days')); 33580 33581 var price = $room_rate.find('.price').attr('data-total') * searchingData['rooms']; 33582 33583 var formatted_price = numberWithCommas(price); 33584 33585 $bookin_summary.find('#total-price .price').text(formatted_price); 33586 33587 $bookin_summary.find('#total-price .price').attr('data-price', price); 33588 33589 var total_guest = searchingData['guests']; 33590 33591 guest_number_index = total_guest; 33592 33593 if ($('#guest-list').is(':empty')) { 33594 33595 insertGuestInfoTemplate(1); 33596 33597 // for(var i = 0; i < total_guest; i++) { 33598 33599 // insertGuestInfoTemplate(i+1); 33600 33601 // } 33602 33603 } 33604 33605 //Check Member Title 33606 33607 // Fix the check logic 20250526 // 33608
33609 //if ($room_rate.find('.room-rate-title').text() == 'Member Rate' || $room_rate.find('.room-rate-title').text() == 'æå¡å¹æ ¼' || $room_rate.find('.room-rate-title').text() == 'ä¼åä»·æ ¼') 33610 //{ 33611 33612 const rateTitle = $room_rate.find('.room-rate-title').text().toLowerCase(); 33613 33614 if (rateTitle.includes('non member rate') || 33615 rateTitle.includes('éæå¡å¹') || 33616 rateTitle.includes('éä¼åä»·')) 33617 { 33618 $('#yha-member-1-of-guest-1').attr('disabled', 'disabled'); 33619 $('#yha-member-2-of-guest-1').attr('checked', 'checked'); 33620 } 33621 else if (rateTitle.includes('member rate') || 33622 rateTitle.includes('æå¡å¹') || 33623 rateTitle.includes('ä¼åä»·')) 33624 { 33625 $('#yha-member-1-of-guest-1').attr('checked', 'checked'); 33626 $('#yha-member-2-of-guest-1').attr('disabled', 'disabled'); 33627 } 33628 33629 // End -Fix the check logic 20250526 // 33630 33631 // $bookin_summary.find('').moment(searchingData['checkout']).diff(moment(searchingData['checkin']), 'days') 33632 33633 } 33634 33635 33636 33637 function initSeeDetailPopup() { 33638 33639 var toggled = false; 33640 33641 var $sliershow_for = $('#slidershow-for'); 33642 33643 var $sliershow_nav = $('#slidershow-nav'); 33644 33645 var slider_for = null; 33646 33647 var slider_nav = null; 33648 33649 if ($sliershow_for.length 33650 33651 && $sliershow_nav.length) { 33652 33653 slider_for = $sliershow_for.slick({ 33654 33655 slidesToShow: 1, 33656 33657 slidesToScroll: 1, 33658 33659 fade: true, 33660 33661 asNavFor: '#slidershow-nav', 33662 33663 // adaptiveHeight: true, 33664 33665 responsive: [ 33666 33667 { 33668 33669 breakpoint: 768, 33670 33671 settings: { 33672 33673 arrows: true, 33674 33675 fade: false, 33676 33677 } 33678 33679 } 33680 33681 ] 33682 33683 }); 33684 33685 slider_nav = $sliershow_nav.slick({ 33686 33687 arrows: false, 33688 33689 slidesToShow: 4, 33690 33691 slidesToScroll: 1, 33692 33693 asNavFor: '#slidershow-for', 33694 33695 focusOnSelect: true 33696 33697 }); 33698 33699 slider_nav.on('afterChange', function (event, slick, currentSlide, nextSlide) { 33700 33701 $('#slide-count .current-number').html(currentSlide + 1); 33702 33703 }); 33704 33705 $("#general").unbind('toggled').on('toggled', function (event, tab) { 33706 33707 if (!toggled) { 33708 33709 slider_for.slick('setPosition'); 33710 33711 slider_nav.slick('setPosition'); 33712 33713 toggled = true; 33714 33715 } 33716 33717 }); 33718 33719 } 33720 33721 } 33722 33723 33724 33725 function destroySeeDetailPopup() { 33726 33727 $('#slidershow-for').slick('unslick'); 33728 33729 $('#slidershow-nav').slick('unslick'); 33730 33731 } 33732 33733 33734 33735 function updatePriceByCoupon(coupon) { 33736 33737 if (coupon.type === 'amount') { 33738 33739 $('#total-price .price').text(numberWithCommas(Math.max(0, parseInt($('#total-price .price').attr('data-price')) - coupon.discount))); 33740 33741 $('.promotion-name').text(coupon.name); 33742 33743 } else if (coupon.type === 'percentage') { 33744 33745 $('#total-price .price').text(numberWithCommas(parseFloat(($('#total-price .price').attr('data-price')) * (1 - coupon.discount / 100)).toFixed(2))); 33746 33747 $('.promotion-name').text(coupon.name); 33748 33749 } else { 33750 33751 $('#total-price .price').text(numberWithCommas($('#total-price .price').attr('data-price'))); 33752 33753 $('.promotion-name').text(''); 33754 33755 } 33756 33757 } 33758 33759 33760 33761 function applyPromotionCode(promotion_code) { 33762 33763 $('.loading-layer').css({'display': 'table'}); 33764 33765 $.get(YHA.common.base_url + '/api/hostel/checkCoupon/', { 33766 33767 'code': promotion_code, 33768 33769 'hash': searchingData['hash'], 33770 33771 'checkin': $('input[name=checkin]').val(), 33772 33773 'checkout': $('input[name=checkout]').val(), 33774 33775 }, function (response) { 33776 33777 $('.loading-layer').hide(); 33778 33779 if (response.status) { 33780 33781 updatePriceByCoupon(response.coupon); 33782 33783 } else { 33784 33785 showPoup(response.error); 33786 33787 } 33788 33789 }); 33790 33791 } 33792 33793 33794 33795 function initPage() { 33796 33797 showSection('room-search'); 33798 33799 // showSection('form'); 33800 33801 setSearchingData('checkin', $('input[name="checkin"]').val()); 33802 33803 setSearchingData('checkout', $('input[name="checkout"]').val()); 33804 33805 setSearchingData('rooms', 0); 33806 33807 setSearchingData('guests', 1); 33808 33809 getAvaiableRooms(); 33810 33811 // $('.search-bar .btn-search').click(); 33812 33813 } 33814 33815 33816 33817 function switchRatePlan($room_type, $room_rate) { 33818 33819 updateBookingSummary($room_type, $room_rate); 33820 33821 setSearchingData('hash', $room_rate.attr('data-hash')); 33822 33823 } 33824 33825 33826 33827 function switchRatePlanByType(type) { 33828 33829 console.log("switchRatePlanByType"); 33830 33831 var $room_type = $('.room-rate[data-status="selected"]').parents('.room
33831-type'); 33832 33833 var $room_rate = $room_type.find('.room-rate[data-type="' + type + '"]'); 33834 33835 33836 33837 console.log($($room_rate[$room_rate.length-1])); 33838 33839 33840 33841 if ($room_rate[0]) { 33842 33843 console.log("yes yes"); 33844 33845 console.log($room_type) 33846 console.log($room_rate) 33847 33848 //switchRatePlan($room_type, $room_rate); 33849 33850 // switchRatePlan($room_type, $($room_rate[$room_rate.length-1]));//2018-07-12 Samson-find the last one since client will add more than one type of member price. 33851 switchRatePlan($room_type, $($room_rate[0]));//ä¸é¢æåä¿åªå»æ¶? 33852 33853 if ($('#promotion-code').val() !== '') { 33854 33855 applyPromotionCode($('#promotion-code').val()); 33856 33857 } 33858 33859 } 33860 33861 } 33862 33863 33864 33865 //INIT 33866 33867 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 33868 33869 YHA.INIT_FUNC[body_selector] = {}; 33870 33871 33872 33873 YHA.INIT_FUNC[body_selector]['init'] = function () { 33874 33875 switch (YHA.common.lang) { 33876 33877 case 'zh': 33878 33879 lang = 'zh-TW'; 33880 33881 booking_lang = 'cht'; 33882 33883 booking_date_error_msg = 'æå¤å¯é¸' + maxConsecutiveNights ? maxConsecutiveNights : 14 + 'æ'; 33884 33885 booking_guest_error_msg = 'è«é¸ææ 客人æ¸'; 33886 33887 booking_rooms_error_msg = 'è«é¸ææ¸ç®'; 33888 33889 booking_rooms_error_msg_2 = 'ä½ æé¸æä¹æ 客人æ¸å·²è¶ éæ¿é/åºä½/é²ççå¯å ¥ä½æ¸é'; 33890 33891 break; 33892 33893 case 'sc': 33894 33895 lang = 'zh-CN'; 33896 33897 booking_lang = 'chs'; 33898 33899 booking_date_error_msg = 'æå¤å¯é' + maxConsecutiveNights ? maxConsecutiveNights : 14 + 'æ'; 33900 33901 booking_guest_error_msg = 'è¯·éæ©æ 客人æ°'; 33902 33903 booking_rooms_error_msg = 'è¯·éæ©æ°ç®'; 33904 33905 booking_rooms_error_msg_2 = 'ä½ æéæ©ä¹æ 客人æ°å·²è¶ è¿æ¿é´/åºä½/é²è¥çå¯å ¥ä½æ°é'; 33906 33907 break; 33908 33909 default: 33910 33911 lang = 'en'; 33912 33913 booking_lang = 'eng'; 33914 33915 booking_date_error_msg = 'Maximum reservation period is ' + maxConsecutiveNights ? maxConsecutiveNights : 14 + ' nights'; 33916 33917 booking_guest_error_msg = 'Please select no. of guests'; 33918 33919 booking_rooms_error_msg = 'Please select no. of Rooms/Dorms/Tents'; 33920 33921 booking_rooms_error_msg_2 = 'The number of guests exceeding the maximum accommodation quantity of the Room/Dorm Bed/Tent.'; 33922 33923 } 33924 33925 $(document).on('click', '.see-details', function () { 33926 33927 var $room_type = $(this).parents('.room-type'); 33928 33929 var room_title = $room_type.find('.title').html(); 33930 33931 var room_description = $room_type.find('.description').html(); 33932 33933 var gallery = JSON.parse($(this).attr('data-gallery')); 33934 33935 var facilities = JSON.parse($(this).attr('data-facilities')); 33936 33937 $.magnificPopup.open({ 33938 33939 items: { 33940 33941 src: '#popup-see-details', 33942 33943 type: 'inline' 33944 33945 }, 33946 33947 fixedContentPos: true, 33948 33949 modal: false, 33950 33951 callbacks: { 33952 33953 beforeOpen: function () { 33954 33955 var $popup = this; 33956 33957 // $.get(window.base_url + '/api/hostel/test', function(response) { 33958 33959 var $popupContent = $popup.contentContainer; 33960 33961 $('#popup-see-details').find('.room-detail .room-title').html(room_title); 33962 33963 $('#popup-see-details').find('.room-detail .room-description').html(room_description); 33964 33965 $('#slidershow-for').empty(); 33966 33967 $('#slidershow-nav').empty(); 33968 33969 for (var i = 0; i < gallery.length; i++) { 33970 33971 var html = '<li>' + 33972 33973 '<div class="item-img">' + 33974 33975 '<img src="' + gallery[i]['url'] + '" title="' + gallery[i]['title'] + '" alt="' + gallery[i]['alt'] + '"/>' + 33976 33977 '</div>' + 33978 33979 '</li>'; 33980 33981 $('#slidershow-for').append(html); 33982 33983 $('#slidershow-nav').append(html); 33984 33985 } 33986 33987 $('#popup-see-details .facilities').empty(); 33988 33989 for (var i = 0; i < facilities.length; i++) { 33990 33991 var html = '<li class="facility">' + 33992 33993 '<i class="fa fa-check">' + facilities[i] + '</i></li>'; 33994 33995 $('#popup-see-details .facilities').append(html); 33996 33997 } 33998 33999 $('#popup-see-details').find('.total-number').html(gallery.length); 34000 34001 // }); 34002 34003 }, 34004 34005 open: function () { 34006
34007 initSeeDetailPopup(); 34008 34009 $(window).trigger('resize'); 34010 34011 }, 34012 34013 close: function () { 34014 34015 destroySeeDetailPopup(); 34016 34017 } 34018 34019 } 34020 34021 }); 34022 34023 }); 34024 34025 34026 34027 // implementation of disabled form fields 34028 34029 var $homeBookingBar = $('.search-bar'); 34030 34031 // var nowTemp = new Date(); 34032 34033 // var now = new Date(nowTemp.getFullYear(), nowTemp.getMonth(), nowTemp.getDate(), 0, 0, 0, 0); 34034 34035 // var initialCheckIn = moment().format('YYYY-MM-DD'); 34036 34037 34038 34039 var checkin = $homeBookingBar.find('input[name=checkin]').fdatepicker({ 34040 34041 format: 'yyyy-mm-dd', 34042 34043 language: lang, 34044 34045 onRender: function (date) { 34046 34047 return date.valueOf() < moment().startOf('day').valueOf() ? 'disabled' : ''; 34048 34049 } 34050 34051 }).on('changeDate', function (ev) { 34052 34053 if (ev.date.valueOf() >= checkout.date.valueOf()) { 34054 34055 var newDate = new Date(ev.date); 34056 34057 newDate.setDate(newDate.getDate() + 1); 34058 34059 checkout.update(newDate); 34060 34061 } 34062 34063 checkin.hide(); 34064 34065 // setSearchingData('checkin', moment(ev.date).format('YYYY-MM-DD')); 34066 34067 $homeBookingBar.find('input[name=checkout]')[0].focus(); 34068 34069 }).data('datepicker'); 34070 34071 // var today = new Date(); 34072 34073 // console.log(today); 34074 34075 // console.log(today.setDate(today.getDate() + 1)); 34076 34077 // var initialCheckOut = moment(new Date()).add(1,'days').format('YYYY-MM-DD'); 34078 34079 // 34080 34081 var checkout = $homeBookingBar.find('input[name=checkout]').fdatepicker({ 34082 34083 // initialDate: initialCheckOut, 34084 34085 format: 'yyyy-mm-dd', 34086 34087 language: lang, 34088 34089 onRender: function (date) { 34090 34091 return (date.valueOf() <= checkin.date.valueOf() || date.valueOf() - checkin.date.valueOf() > +maxConsecutiveNights * 24 * 60 * 60 * 1000) ? 'disabled' : ''; 34092 34093 } 34094 34095 }).on('changeDate', function (ev) { 34096 34097 checkout.hide(); 34098 34099 // setSearchingData('checkout', moment(ev.date).format('YYYY-MM-DD')); 34100 34101 }).data('datepicker'); 34102 34103 $homeBookingBar.find('.icon-calendar').click(function () { 34104 34105 if ($(this).attr('data-input-target') == 'checkin') { 34106 34107 checkin.show(); 34108 34109 checkout.hide(); 34110 34111 } else { 34112 34113 checkin.hide(); 34114 34115 checkout.show(); 34116 34117 } 34118 34119 }); 34120 34121 if (inputCheckIn && inputCheckOut) { 34122 34123 var initialCheckIn = moment(inputCheckIn).format('YYYY-MM-DD'); 34124 34125 var initialCheckOut = moment(inputCheckOut).format('YYYY-MM-DD'); 34126 34127 } else { 34128 34129 var initialCheckIn = moment().format('YYYY-MM-DD'); 34130 34131 var initialCheckOut = moment(new Date()).add(1, 'days').format('YYYY-MM-DD'); 34132 34133 } 34134 34135 // console.log(initialCheckOut); 34136 34137 checkin.update(initialCheckIn); 34138 34139 checkout.update(initialCheckOut); 34140 34141 setSearchingData('checkin', initialCheckIn); 34142 34143 setSearchingData('checkout', initialCheckOut); 34144 34145 $('.search-bar .btn-search').click(function () { 34146 34147 setSearchingData('checkin', $('input[name="checkin"]').val()); 34148 34149 setSearchingData('checkout', $('input[name="checkout"]').val()); 34150 34151 setSearchingData('rooms', Math.max($('select[name="rooms"] option:selected').val(), 0)); 34152 34153 var no_of_guests = $('select[name="guests"] option:selected').val(); 34154 34155 if (no_of_guests >= 1) { 34156 34157 setSearchingData('guests', no_of_guests); 34158 34159 getAvaiableRooms() 34160 34161 } else { 34162 34163 YHA.common.popupError(booking_guest_error_msg); 34164 34165 } 34166 34167 }); 34168 34169 $(document).on('click', '.btn-book', function () { 34170 34171 var rooms = $(this).siblings('select[name="rooms"]').val(); 34172 34173 var room_select_status = $(this).siblings('select[name="rooms"]').find('option:selected').attr('data-status'); 34174 34175 if (room_select_status !== 'disabled') { 34176 34177 if (rooms > 0) { 34178
34179 var $room_type = $(this).parents('.room-type'); 34180 34181 var $room_rate = $(this).parents('.room-rate'); 34182 34183 $room_rate.attr('data-status', 'selected'); 34184 34185 setSearchingData('rooms', rooms); 34186 34187 switchRatePlan($room_type, $room_rate); 34188 34189 if (!$('#form-section').is(':visible')) { 34190 34191 showSection('form'); 34192 34193 } 34194 34195 } else { 34196 34197 YHA.common.popupError(booking_rooms_error_msg); 34198 34199 } 34200 34201 } else { 34202 34203 YHA.common.popupError(booking_rooms_error_msg_2); 34204 34205 } 34206 34207 }); 34208 34209 $('.field-filter').change(function () { 34210 34211 var $box = $(this); 34212 34213 if ($box.is(":checked")) { 34214 34215 // the name of the box is retrieved using the .attr() method 34216 34217 // as it is assumed and expected to be immutable 34218 34219 var group = "input:checkbox[name='" + $box.attr("name") + "']"; 34220 34221 // the checked state of the group/box on the other hand will change 34222 34223 // and the current value is retrieved using .prop() method 34224 34225 $(group).prop("checked", false); 34226 34227 $box.prop("checked", true); 34228 34229 } else { 34230 34231 $box.prop("checked", false); 34232 34233 } 34234 34235 if ($box.prop('checked')) { 34236 34237 setSearchingData($(this).attr('name'), $(this).val()); 34238 34239 } else { 34240 34241 setSearchingData($(this).attr('name'), ''); 34242 34243 } 34244 34245 if ($(this).attr('name') === 'room-rate') { 34246 34247 if ($box.prop('checked')) { 34248 34249 $('#room-type-list .room-rate').each(function () { 34250 34251 if ($(this).attr('data-type') != $('input[name="room-rate"]:checked').val()) { 34252 34253 $(this).addClass('hide'); 34254 34255 } else { 34256 34257 $(this).removeClass('hide'); 34258 34259 } 34260 34261 }); 34262 34263 } else { 34264 34265 $('.room-rate').each(function () { 34266 34267 $(this).removeClass('hide'); 34268 34269 }); 34270 34271 } 34272 34273 34274 34275 } else { 34276 34277 getAvaiableRooms(); 34278 34279 } 34280 34281 }); 34282 34283 $(document).on('change', '.rooms-select', function () { 34284 34285 var room_select_status = $(this).find('option:selected').attr('data-status'); 34286 34287 console.log(room_select_status); 34288 34289 if (room_select_status === 'disabled') { 34290 34291 YHA.common.popupError(booking_rooms_error_msg_2); 34292 34293 } 34294 34295 }); 34296 34297 $(document).on('change', '.field-member', function () { 34298 34299 34300 34301 /*2018-07-06 Samson- ifè³½é¦¬ææ©æå¶ºéå¹´æ è 808,ç½æ®ç賽馬æéå¹´æ è 816,æåªæ´ç¶æ¯éå¹´æ è 831, disable switchRatePlanByType function */ 34302 34303 if (($('#hostel-id').val() != '808') && ($('#hostel-id').val() != '816') && ($('#hostel-id').val() != '831')) { 34304 34305 console.log('clicking'); 34306 34307 var is_member = false; 34308 34309 $('#guest-list .guest-info').each(function (index) { 34310 34311 if ($('#yha-member-1-of-guest-' + (index + 1)).is(':checked') || $('#apply-on-site-of-guest-' + (index + 1)).is(':checked')) { 34312 34313 is_member = true; 34314 34315 return false; 34316 34317 } 34318 34319 }); 34320 34321 if (is_member) { 34322 34323 console.log('is member'); 34324 switchRatePlanByType('member'); 34325 34326 } else { 34327 console.log('non member'); 34328 switchRatePlanByType('non_member'); 34329 34330 } 34331 34332 if ($(this).attr('type') === 'radio') { 34333 34334 if ($(this).val() == '1') { 34335 34336 $(this).parents('.guest-info').find('.field-apply-on-site').attr('disabled', true).prop('checked', false); 34337 34338 } else { 34339 34340 $(this).parents('.guest-info').find('.field-apply-on-site').attr('disabled', false); 34341 34342 // $(this).parents('.guest-info').find('.field-apply-on-site').attr('checked', false); 34343 34344 } 34345 34346 } 34347 34348 } 34349 34350 }); 34351 34352 $('select[name="sort-by"]').change(function () { 34353 34354 sortSearchResult(roomData); 34355 34356 }); 34357 34358 $(document).on('click', '.btn-reserve', function () { 34359
34360 var $roomType = $(this).parents('.room-type'); 34361 34362 if ($roomType.find('.room-rates').is(":hidden")) { 34363 34364 $roomType.find('.room-rates').slideDown(); 34365 34366 } else { 34367 34368 $roomType.find('.room-rates').slideUp(); 34369 34370 } 34371 34372 }); 34373 34374 $('.mobile-sidebar-menu li').click(function (e) { 34375 34376 $('.mobile-sidebar-menu li').removeClass('active'); 34377 34378 $(this).addClass('active'); 34379 34380 var index = $(this).index(); 34381 34382 $('.slidebar-boxes').removeClass('active'); 34383 34384 $('.slidebar-boxes').eq(index).addClass('active'); 34385 34386 }); 34387 34388 initPage(); 34389 34390 }; 34391 34392 YHA.INIT_FUNC[body_selector]['form'] = function () { 34393 34394 $('input[data-target-input]').change(function () { 34395 34396 var targetInput = $(this).attr('data-target-input'); 34397 34398 if ($(this).is(':checked')) { 34399 34400 $(targetInput).attr('disabled', false).focus(); 34401 34402 } else { 34403 34404 $(targetInput).attr('disabled', true); 34405 34406 } 34407 34408 }); 34409 34410 $('#btn-back').click(function () { 34411 34412 showSection('room-search'); 34413 34414 }); 34415 34416 $(document).on('change', '.age-selector', function () { 34417 34418 console.log($(this).val()); 34419 34420 if ($(this).val() == 'child') { 34421 34422 YHA.common.popupError($(this).attr('data-notice')); 34423 34424 } 34425 34426 }); 34427 34428 $submitBtn.click(function () { 34429 34430 if (!loading) { 34431 34432 loading = true; 34433 34434 $submitBtn.html('<span><i class="fa"></i><p><i>' + txt2 + '</i></p></span>'); 34435 34436 var $bookingForm = $('#booking-form'); 34437 34438 var postData = searchingData; 34439 34440 postData['promotion_code'] = $('#promotion-code').val(); 34441 34442 $bookingForm.ajaxSubmit({ 34443 34444 url: YHA.common.base_url + "/api/hostel/submit_form", 34445 34446 data: postData, 34447 34448 success: function (response) { 34449 34450 loading = false; 34451 34452 $submitBtn.html(txt1); 34453 34454 if (response.status) { 34455 34456 redirectToPaymentGateway(response); 34457 34458 } else { 34459 34460 var errorData = response.errors; 34461 34462 var allError = ""; 34463 34464 for (var i in errorData) { 34465 34466 allError = errorData[0]['msg'] + '<br>'; 34467 34468 break; 34469 34470 } 34471 34472 YHA.common.popupError(allError); 34473 34474 } 34475 34476 }, 34477 34478 error: function () { 34479 34480 loading = false; 34481 34482 $submitBtn.html(txt1); 34483 34484 YHA.common.popupError('Network error'); 34485 34486 } 34487 34488 }); 34489 34490 } 34491 34492 }); 34493 34494 $('.btn-add-guest').click(function (e) { 34495 34496 var $room_type = $('.room-rate[data-status="selected"]').parents('.room-type'); 34497 34498 var $room_rate = $room_type.find('.room-rate[data-type="member"]'); 34499 34500 switchRatePlan($room_type, $room_rate); 34501 34502 e.preventDefault(); 34503 34504 e.stopPropagation(); 34505 34506 // var total_guest = searchingData['guests']; 34507 34508 // if(guest_number_index >= total_guest) { 34509 34510 // return; 34511 34512 // } 34513 34514 // insertGuestInfoTemplate(guest_number_index++); 34515 34516 }); 34517 34518 $('#promotion-code').blur(function () { 34519 34520 if ($(this).val() === '') { 34521 34522 $('#total-price .price').text($('#total-price .price').attr('data-price')); 34523 34524 $('.promotion-name').text(''); 34525 34526 } else { 34527 34528 applyPromotionCode($(this).val()); 34529 34530 } 34531 34532 }); 34533 34534 window.onbeforeunload = function () { 34535 34536 return "Are you sure you want to navigate away?"; 34537 34538 } 34539 34540 }; 34541 34542})(jQuery); 34543var YHA = YHA || {INIT_FUNC:{},RESPON_FUNC:{}}; 34544 34545 34546 34547(function($) { 34548 34549 var body_selector = ".page-hostel-rating-detail"; 34550 34551 var loading = false;
34552 34553 34554 34555 function showPoup(msg) { 34556 34557 $.magnificPopup.open({ 34558 34559 items: { 34560 34561 src: '<div class="error-popup popup-content">' + 34562 34563 '<div class="table error-content">' + 34564 34565 '<div class="table-cell">' + 34566 34567 msg + 34568 34569 '</div>' + 34570 34571 '</div>' + 34572 34573 '<div class="btn btn-cricle btn-close" onclick="$.magnificPopup.close();">' + 34574 34575 '<div class="table">' + 34576 34577 '<div class="table-cell">' + 34578 34579 'OK' + 34580 34581 '</div>' + 34582 34583 '</div>' + 34584 34585 '</div>' + 34586 34587 '</div>', 34588 34589 type: 'inline' 34590 34591 }, 34592 34593 fixedContentPos: true, 34594 34595 callbacks: { 34596 34597 close: function() { 34598 34599 window.location.replace(YHA.common.base_url); 34600 34601 } 34602 34603 } 34604 34605 }); 34606 34607 } 34608 34609 //INIT 34610 34611 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 34612 34613 YHA.INIT_FUNC[body_selector] = {}; 34614 34615 34616 34617 YHA.INIT_FUNC[body_selector]['init'] = function(){ 34618 34619 var $ratingForm = $('#review-form'); 34620 34621 $ratingForm.find('.btn-reset').click(function() { 34622 34623 $ratingForm.find('.rating-option ul li a').each(function(){ 34624 34625 $(this).removeClass('active'); 34626 34627 $(this).parents('.rating-option').find('input[type=hidden]').val(''); 34628 34629 }); 34630 34631 }); 34632 34633 $ratingForm.find('.rating-option ul li a').click(function() { 34634 34635 $(this).parent().siblings().find('a').removeClass('active'); 34636 34637 $(this).addClass('active'); 34638 34639 $(this).parents('.rating-option').find('input[type=hidden]').val($(this).attr('data-value')); 34640 34641 }); 34642 34643 $ratingForm.find('.btn-submit').click(function() { 34644 34645 if(!loading) { 34646 34647 var $submitBtn = $(this); 34648 34649 var original_text = $submitBtn.val(); 34650 34651 $submitBtn.val($submitBtn.attr('data-loading-text')); 34652 34653 loading = true; 34654 34655 $ratingForm.ajaxSubmit({ 34656 34657 url : YHA.common.base_url + "/api/review/submit_form", 34658 34659 success: function(response) { 34660 34661 loading = false; 34662 34663 $submitBtn.val(original_text); 34664 34665 if(response.status) { 34666 34667 showPoup(response.msg); 34668 34669 } else { 34670 34671 var errorData = response.errors; 34672 34673 var allError = ""; 34674 34675 for(var i in errorData) 34676 34677 { 34678 34679 allError = errorData[0]['msg']+'<br>'; 34680 34681 break; 34682 34683 } 34684 34685 YHA.common.popupError(allError); 34686 34687 } 34688 34689 } 34690 34691 }); 34692 34693 } 34694 34695 }); 34696 34697 }; 34698 34699 34700 34701})(jQuery); 34702var YHA = YHA || {INIT_FUNC:{},RESPON_FUNC:{}}; 34703 34704 34705 34706(function($) { 34707 34708 var body_selector = ".page-hostel-detail", 34709 34710 $body_selector = $(body_selector), 34711 34712 $no_record = $body_selector.find(".no_record"), 34713 34714 $loadMore = $body_selector.find(".loadWrapper .btn"), 34715 34716 txt1 = $loadMore.text(), 34717 34718 txt2 = $loadMore.attr("data-txt"), 34719 34720 loading = false, 34721 34722 xhr; 34723 34724 34725 34726 var page = 1, count = 5; 34727 34728 34729 34730 //INIT 34731 34732 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 34733 34734 YHA.RESPON_FUNC = YHA.RESPON_FUNC || {}; 34735 34736 YHA.INIT_FUNC[body_selector] = {}; 34737 34738 YHA.RESPON_FUNC[body_selector] = {}; 34739 34740 34741 34742 34743 34744 function getComments(hostel_id) { 34745 34746 loading = true; 34747 34748 34749 34750 $loadMore.html('<i class="fa fa-refresh fa-spin"></i> ' + txt2); 34751 34752 34753 34754 xhr = $.ajax({ 34755 34756 url: YHA.common.base_url + "/api/review/get_reviews_by_hostel_id/", 34757 34758 method: "GET", 34759 34760 dataType: "json", 34761 34762 data: { 34763 34764 'hostel_id' : hostel_id, 34765 34766 'page' : page?page:1, 34767 34768 'count' : count?count:10 34769 34770 }, 34771 34772 success:function(response){ 34773 34774 $loadMore.text(txt1); 34775 34776 loading = false; 34777 34778 xhr = (function() {return;})(); 34779 34780 34781 34782 if(response.status == true) { 34783 34784 if(response.comments.length <= 0 || response.comments < count) 34785 34786 $loadMore.hide(); 34787 34788 else { 34789 34790 var $commentContainer = $('#hostel-comments'); 34791 34792 var commentHtml = ''; 34793 34794 34795 34796 $.each(response.comments, function() { 34797 34798 commentHtml = $commentContainer.find('ul > li:first-child').clone(); 34799 34800 commentHtml.find('.comment .rating').html('<span>' + this.rating + '%</span>').addClass(this.rating>50?'rate-smile':'rate-sad'); 34801 34802 commentHtml.find('.comment .author').text(this.name); 34803 34804 commentHtml.find('.comment .date').text(this.comment_date); 34805 34806 commentHtml.find('.comment .content').html(this.content); 34807 34808 if(this.reply) { 34809 34810 commentHtml.find('.reply .content').html(this.reply); 34811 34812 } else { 34813 34814 commentHtml.find('.reply').remove(); 34815 34816 } 34817 34818 $commentContainer.find('ul').append(commentHtml); 34819 34820 }) 34821 34822 } 34823 34824 } 34825 34826 } 34827 34828 }); 34829 34830 } 34831 34832 34833 34834 function loadMore(hostel_id) { 34835 34836 page++; 34837 34838 getComments(hostel_id); 34839 34840 } 34841 34842 34843 34844 YHA.INIT_FUNC[body_selector]['tab-generate'] = function(){ 34845 34846 var toggled = false;
34847 34848 var $sliershow_for = $('#slidershow-for'); 34849 34850 var $sliershow_nav = $('#slidershow-nav'); 34851 34852 var slider_for = null; 34853 34854 var slider_nav = null; 34855 34856 if($sliershow_for.length 34857 34858 && $sliershow_nav.length){ 34859 34860 slider_for = $sliershow_for.slick({ 34861 34862 slidesToShow: 1, 34863 34864 slidesToScroll: 1, 34865 34866 arrows: false, 34867 34868 fade: true, 34869 34870 asNavFor: '#slidershow-nav', 34871 34872 responsive : [ 34873 34874 { 34875 34876 breakpoint: 768, 34877 34878 settings: { 34879 34880 arrows: true, 34881 34882 fade: false, 34883 34884 } 34885 34886 } 34887 34888 ] 34889 34890 }); 34891 34892 slider_nav = $sliershow_nav.slick({ 34893 34894 slidesToShow: 4, 34895 34896 slidesToScroll: 1, 34897 34898 asNavFor: '#slidershow-for', 34899 34900 focusOnSelect: true 34901 34902 }); 34903 34904 $("#general").on('toggled', function (event, tab) { 34905 34906 if(!toggled){ 34907 34908 slider_for.slick('setPosition'); 34909 34910 slider_nav.slick('setPosition'); 34911 34912 toggled = true; 34913 34914 } 34915 34916 }); 34917 34918 } 34919 34920 }; 34921 34922 34923 34924 YHA.INIT_FUNC[body_selector]['review-section'] = function(){ 34925 34926 $loadMore.on("click", function(e) { 34927 34928 e.preventDefault(); 34929 34930 if(!loading) { 34931 34932 loadMore($(this).attr('data-hostel-id')); 34933 34934 } 34935 34936 }); 34937 34938 }; 34939 34940 34941 34942})(jQuery); 34943var YHA = YHA || {INIT_FUNC:{},RESPON_FUNC:{}}; 34944 34945 34946 34947(function($) { 34948 34949 var body_selector = ".page-donation"; 34950 34951 var $submitBtn = $("#btn-continuous"), 34952 34953 txt1 = $submitBtn.html(), 34954 34955 txt2 = $submitBtn.attr("data-txt"), 34956 34957 loading = false; 34958 34959 //INIT 34960 34961 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 34962 34963 YHA.INIT_FUNC[body_selector] = {}; 34964 34965 34966 34967 var windowScroll = function(str) 34968 34969 { 34970 34971 $('html, body').stop().animate({ 34972 34973 scrollTop: $(str).offset().top 34974 34975 }, 500); 34976 34977 34978 34979 }; 34980 34981 YHA.INIT_FUNC[body_selector]['init'] = function(){ 34982 34983 34984 34985 $( "#other_amount" ).focus(function() 34986 34987 { 34988 34989 $("input[name=amount][value='other']","#amount_choice").prop("checked",true); 34990 34991 }); 34992 34993 34994 34995 $('#donation-list ul li:first-child a').click(function(e){ 34996 34997 e.preventDefault(); 34998 34999 e.stopPropagation(); 35000 35001 windowScroll('#form-content'); 35002 35003 }); 35004 35005 $("#btn-continuous").click(function() 35006 35007 { 35008 35009 if(!loading) { 35010
35011 var sur_name_chi = $("#sur_name_chi_input").val(); 35012 35013 var given_name_chi = $("#given_name_chi_input").val(); 35014 35015 var sur_name_eng = $("#sur_name_eng_input").val(); 35016 35017 var given_name_eng = $("#given_name_eng_input").val(); 35018 35019 var group_name = $("#group_name_input").val(); 35020 35021 35022 35023 35024 35025 var address_1 = $("#address-1").val(); 35026 35027 var address_2 = $("#address-2").val(); 35028 35029 var address_3 = $("#address-3").val(); 35030 35031 var contact = $("#contact_input").val(); 35032 35033 var email = $("#email_input").val(); 35034 35035 var fax = $("#fax_input").val(); 35036 35037 35038 35039 35040 35041 35042 35043 var amount = $('input[name=amount]:checked', '#amount_choice').val(); 35044 35045 var receipt = $('input[name=receipt]:checked', '#receipt_choice').val(); 35046 35047 var appel = $('input[name=appel]:checked', '#appel_choice').val(); 35048 35049 // var district = $('input[name=district]:checked', '#district_choice').val(); 35050 35051 var receive = $('input[name=receive]:checked', '#receive_choice').val(); 35052 35053 35054 35055 35056 35057 if(amount=="other") 35058 35059 { 35060 35061 amount = $("#other_amount").val(); 35062 35063 } 35064 35065 35066 35067 if(receive==undefined ||receive=="undefined") 35068 35069 { 35070 35071 receive = ""; 35072 35073 } 35074 35075 35076 35077 if(amount==undefined ||amount=="undefined") 35078 35079 { 35080 35081 amount = ""; 35082 35083 } 35084 35085 35086 35087 if(receipt==undefined ||receipt=="undefined") 35088 35089 { 35090 35091 receipt = ""; 35092 35093 } 35094 35095 35096 35097 if(appel==undefined ||appel=="undefined") 35098 35099 { 35100 35101 appel = ""; 35102 35103 } 35104 35105 35106 35107 //console.log("-------------------------------"); 35108 35109 // console.log('data:'+sur_name_chi+"|"+given_name_chi+"|"+sur_name_eng+"|"+given_name_eng+"|"+group_name+"|"+flat+"|"+floor+"|"+block+"|"+building+"|"+street+"|"+contact+"|"+email+"|"+fax+"|"+amount+"|"+receipt+"|"+appel+"|"+district+"|"+receive+"////////////"); 35110 35111 35112 35113 loading = true; 35114 35115 $submitBtn.html('<span><i class="fa"></i><p><i>' + txt2 + '</i></p></span>'); 35116 35117 $.post(YHA.common.base_url + "/api/donation/submit_form", 35118 35119 { 35120 35121 sur_name_chi:sur_name_chi, 35122 35123 given_name_chi:given_name_chi, 35124 35125 sur_name_eng:sur_name_eng, 35126 35127 given_name_eng:given_name_eng, 35128 35129 group_name:group_name, 35130 35131 address_1:address_1, 35132 35133 address_2:address_2, 35134 35135 address_3:address_3, 35136 35137 contact:contact, 35138 35139 email:email, 35140 35141 fax:fax, 35142 35143 amount:amount, 35144 35145 receipt:receipt, 35146 35147 appel:appel, 35148 35149 receive:receive, 35150 35151 35152 35153 },(function(response) 35154 35155 { 35156 35157 $submitBtn.html(txt1); 35158 35159 loading = false; 35160 35161 if(response.status) 35162 35163 { 35164 35165 var hiddenForm = response.html; 35166 35167 $('#donation-page-content').hide(); 35168 35169 $('#payment-processing').show(); 35170 35171 window.scrollTo(0,0); 35172 35173 $(body_selector + ' .hidden-section').html(hiddenForm); 35174 35175 }else 35176 35177 { 35178 35179 35180 35181 var allError =""; 35182 35183 35184 35185 var errorData = response.errors; 35186 35187 35188 35189 for(var i in errorData){ 35190 35191 allError+= errorData[i]['msg']+'\n'; 35192 35193 break; 35194 35195 } 35196 35197 YHA.common.popupError(allError); 35198 35199 35200 35201 } 35202 35203 35204 35205 }), 'json'); 35206 35207 } 35208 35209 }); 35210 35211 }; 35212 35213 35214 35215})(jQuery); 35216var YHA = YHA || {INIT_FUNC:{},RESPON_FUNC:{}}; 35217 35218 35219 35220(function($) { 35221 35222 var body_selector = ".page-home"; 35223 35224 var loading = false; 35225 35226 // function toDate(date) { 35227 35228 // var from = date.split("-"); 35229 35230 // return new Date(from[2], from[1] - 1, from[0]); 35231 35232 // } 35233 35234 35235 35236 //INIT 35237 35238 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 35239 35240 YHA.RESPON_FUNC = YHA.RESPON_FUNC || {}; 35241 35242 YHA.INIT_FUNC[body_selector] = {}; 35243 35244 YHA.RESPON_FUNC[body_selector] = {}; 35245 35246 35247 35248 YHA.INIT_FUNC[body_selector]['home-booking-bar'] = function(){ 35249 35250 var $homeBookingBar = $('#home-booking-bar'); 35251 35252 $(".tab-title").bind("click",function(){ 35253 35254 var $tab = $(this); 35255 35256 var id = $tab.find('a').eq(0).attr('aria-controls'); 35257 35258 var $content = $("#"+id); 35259 35260 if(!$content.hasClass('open')){ 35261 35262 $(".open").removeClass('open'); 35263 35264 $(".tabs-content").addClass('open'); 35265 35266 $content.addClass('open'); 35267 35268 }else{ 35269 35270 $(".open").removeClass('open'); 35271 35272 } 35273 35274 }); 35275 35276 $homeBookingBar.find('select[name="hostel_name"]').change(function(){ 35277 35278 var booking_method = $('option:selected', this).attr('data-booking-method'); 35279 35280 if(booking_method == 'email') { 35281 35282 $('#book-by-email').show(); 35283 35284 $('#book-by-link').hide(); 35285 35286 } else { 35287 35288 $('#book-by-link').show(); 35289 35290 $('#book-by-email').hide(); 35291 35292 } 35293 35294 }); 35295 35296 35297 35298 35299 35300 35301 35302 var lang = 'en'; 35303 35304 var booking_lang = 'eng'; 35305 35306 var booking_date_error_msg = ''; 35307 35308 switch(YHA.common.lang) { 35309 35310 case 'zh': 35311 35312 lang = 'zh-TW'; 35313 35314 booking_lang = 'cht'; 35315 35316 booking_date_error_msg = 'æå¤å¯é¸14æ'; 35317 35318 break; 35319 35320 case 'sc': 35321 35322 lang = 'zh-CN'; 35323 35324 booking_lang = 'chs'; 35325 35326 booking_date_error_msg = 'æå¤å¯é14æ'; 35327 35328 break; 35329 35330 default: 35331 35332 lang = 'en'; 35333 35334 booking_lang = 'eng'; 35335 35336 booking_date_error_msg = 'Maximum reservation period is 14 nights'; 35337 35338 } 35339 35340 35341 35342 $homeBookingBar.find('#hkHostels .btn-submit-booking').click(function(e){ 35343 35344 var value = $homeBookingBar.find('select[name="hostel_name"]').val(); 35345 35346 var booking_method = $homeBookingBar.find('select[name="hostel_name"] o
35346ption:selected').attr('data-booking-method'); 35347 35348 var booking_variable = $homeBookingBar.find('select[name="hostel_name"] option:selected').attr('data-booking-variable'); 35349 35350 console.log(value); 35351 35352 if(value != '') { 35353 35354 if(booking_method == 'email') { 35355 35356 e.preventDefault(); 35357 35358 window.location = booking_variable; 35359 35360 } else { 35361 35362 e.preventDefault(); 35363 35364 // var hostel_name = $homeBookingBar.find('select[name=hostel_name]').val(); 35365 35366 var checkin_value = $homeBookingBar.find('input[name=checkin]').val(); 35367 35368 var checkout_value = $homeBookingBar.find('input[name=checkout]').val(); 35369 35370 // var adult = $homeBookingBar.find('select[name=adult]').val(); 35371 35372 // var children = $homeBookingBar.find('select[name=children]').val(); 35373 35374 // var room = $homeBookingBar.find('select[name=room]').val(); 35375 35376 var booking_url = $(this).attr('data-booking-link'); 35377 35378 // var booking_lang = 'eng'; 35379 35380 // console.log(checkin_value); 35381 35382 // console.log(checkout_value); 35383 35384 if(checkin_value && checkout_value) { 35385 35386 var checkin_date = moment(checkin_value); 35387 35388 var checkout_date = moment(checkout_value); 35389 35390 // var timeDiff = checkout_date.getTime() - checkin_date.getTime(); 35391 35392 // console.log(checkin_date); 35393 35394 // console.log(checkout_date); 35395 35396 var diffDays = checkout_date.diff(checkin_date, 'days'); 35397 35398 console.log(diffDays); 35399 35400 if(diffDays <= 14 && diffDays > 0) { 35401 35402 var params = { 35403 35404 checkin : checkin_value, 35405 35406 checkout : checkout_value, 35407 35408 id : value 35409 35410 }; 35411 35412 var url = booking_url + '?' + $.param(params); 35413 35414 // console.log(url); 35415 35416 top.location.href = url; 35417 35418 } else { 35419 35420 alert(booking_date_error_msg); 35421 35422 } 35423 35424 } 35425 35426 } 35427 35428 } 35429 35430 }); 35431 35432 $homeBookingBar.find('#myBooking .btn-submit-booking').click(function(e){ 35433 35434 if(!loading) { 35435 35436 console.log('Loading'); 35437 35438 var $enquiryForm = $('#enquiry-form'); 35439 35440 $enquiryForm.ajaxSubmit({ 35441 35442 url : YHA.common.base_url + "/api/hostel/enquiry_form_login", 35443 35444 success: function(response) { 35445 35446 loading = false; 35447 35448 if(response.status) { 35449 35450 top.location.href = YHA.common.base_url + '/hostels/my-booking'; 35451 35452 } else { 35453 35454 var errorData = response.errors; 35455 35456 var allError = ""; 35457 35458 for(var i in errorData) { 35459 35460 allError = errorData[0]['msg']+'<br>'; 35461 35462 break; 35463 35464 } 35465 35466 YHA.common.popupError(allError); 35467 35468 } 35469 35470 }, 35471 35472 error: function() { 35473 35474 loading = false; 35475 35476 YHA.common.popupError('Network error'); 35477 35478 } 35479 35480 }); 35481 35482 } 35483 35484 }); 35485 35486 // implementation of disabled form fields 35487 35488 35489 35490 var nowTemp = new Date(); 35491 35492 var now = new Date(nowTemp.getFullYear(), nowTemp.getMonth(), nowTemp.getDate(), 0, 0, 0, 0); 35493 35494 var checkin = $homeBookingBar.find('input[name=checkin]').fdatepicker({ 35495 35496 format : 'yyyy-mm-dd', 35497 35498 language: lang, 35499 35500 onRender: function (date) { 35501 35502 return date.valueOf() < now.valueOf() ? 'disabled' : ''; 35503 35504 } 35505 35506 }).on('changeDate', function (ev) { 35507 35508 if (ev.date.valueOf() >= checkout.date.valueOf()) { 35509 35510 var newDate = new Date(ev.date); 35511 35512 newDate.setDate(newDate.getDate() + 1); 35513 35514 checkout.update(newDate); 35515 35516 } 35517 35518 checkin.hide(); 35519 35520 $homeBookingBar.find('input[name=checkout]')[0].focus(); 35521 35522 }).data('datepicker'); 35523 35524 var checkout = $homeBookingBar.find('input[name=checkout]').fdatepicker({ 35525 35526 format : 'yyyy-mm-dd', 35527 35528 language: lang, 35529 35530 onRender: function (date) { 35531 35532 return (date.valueOf() <= checkin.date.valueOf() || date.valueOf() - checkin.date.valueOf() > 14*24*60*60*1000) ? 'disabled' : ''; 35533 35534 } 35535 35536 }).on('changeDate', function (ev) { 35537 35538 checkout.hide(); 35539 35540 }).data('datepicker'); 35541 35542 $homeBookingBar.find('.icon-calendar').click(function(){ 35543 35544 if($(this).attr('data-input-target') == 'checkin') { 35545 35546 checkin.show(); 35547 35548 checkout.hide(); 35549 35550 } else { 35551 35552 checkin.hide(); 35553 35554 checkout.show(); 35555 35556 } 35557 35558 }); 35559 35560 }; 35561 35562 35563 35564 YHA.INIT_FUNC[body_selector]['home-find-out'] = function(){ 35565 35566 var $wrapper = $("#home-find-out"); 35567 35568 var $slider = $(".slidershow",$wrapper); 35569 35570 if($wrapper.length && $slider.length){ 35571 35572 $slider.on('setPosition', function(slick){ 35573 35574 // console.log('set position'); 35575 35576 var height = $(".slick-current .item-img",$wrapper).height(); 35577 35578 $(".slick-dots",$wrapper).css('top',parseInt(height)-22); 35579 35580 }); 35581 35582 } 35583 35584 }; 35585 35586 35587 35588}
35588)(jQuery); 35589var YHA = YHA || {INIT_FUNC:{},RESPON_FUNC:{}}; 35590 35591 35592 35593(function($) { 35594 35595 var body_selector = ".page-association"; 35596 35597 35598 35599 var currentwidth = 0; 35600 35601 var stickyActive = false; 35602 35603 //INIT 35604 35605 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 35606 35607 YHA.INIT_FUNC[body_selector] = {}; 35608 35609 35610 35611 YHA.INIT_FUNC[body_selector]['init'] = function() 35612 35613 { 35614 35615 35616 35617 var checkWinWidth = function() 35618 35619 { 35620 35621 if(currentwidth != $(window).width()) 35622 35623 { 35624 35625 currentwidth = $(window).width(); 35626 35627 35628 35629 if($("#side-menu").css('padding-left')=="0px") 35630 35631 { 35632 35633 $("#side-menu .content").unstick(); 35634 35635 stickyActive = false; 35636 35637 }else{ 35638 35639 if(!stickyActive) { 35640 35641 $("#side-menu .content").sticky({ 35642 35643 topSpacing: 40 35644 35645 }); 35646 35647 $("#side-menu .content").on('sticky-start', function(){ 35648 35649 var $sideMenu = $("#side-menu"); 35650 35651 var left = $sideMenu.offset().left + parseInt($sideMenu.css('padding-left')); 35652 35653 $(this).css({ 35654 35655 'left' : left 35656 35657 }); 35658 35659 }); 35660 35661 stickyActive = true; 35662 35663 } 35664 35665 35666 35667 } 35668 35669 } 35670 35671 } 35672 35673 35674 35675 checkWinWidth(); 35676 35677 35678 35679 35680 35681 35682 35683 $( window ).resize(function() 35684 35685 { 35686 35687 checkWinWidth(); 35688 35689 35690 35691 }); 35692 35693 35694 35695 var windowScroll = function(str) 35696 35697 { 35698 35699 $('html, body').stop().animate({ 35700 35701 scrollTop: $(str).offset().top 35702 35703 }, 500); 35704 35705 35706 35707 }; 35708 35709 35710 35711 35712 35713 $("#side-menu").find("li").each(function(index) 35714 35715 { 35716 35717 $(this).click(function() 35718 35719 { 35720 35721 if(index==0) 35722 35723 { 35724 35725 windowScroll(".mission"); 35726 35727 } 35728 35729 35730 35731 if(index==1) 35732 35733 { 35734 35735 windowScroll(".milestone"); 35736 35737 } 35738 35739 35740 35741 if(index==2) 35742 35743 { 35744 35745 windowScroll(".organisation"); 35746 35747 } 35748 35749 35750 35751 if(index==3) 35752 35753 { 35754 35755 windowScroll(".awards"); 35756 35757 } 35758 35759 35760 35761 }); 35762 35763 35764 35765 35766 35767 }); 35768 35769 35770 35771 35772 35773 35774 35775 35776 35777 35778 35779 35780 35781 }; 35782 35783 35784 35785})(jQuery); 35786var YHA = YHA || {INIT_FUNC:{},RESPON_FUNC:{}}; 35787 35788 35789 35790(function($) { 35791 35792 var body_selector = ".page-become-member", 35793 35794 $submitBtn = $("#btn-continuous"), 35795 35796 txt1 = $submitBtn.html(), 35797 35798 txt2 = $submitBtn.attr("data-txt"), 35799 35800 submitting = false; 35801 35802 //INIT 35803 35804 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 35805 35806 YHA.INIT_FUNC[body_selector] = {}; 35807 35808 35809 35810 YHA.INIT_FUNC[body_selector]['init'] = function(){ 35811 35812 35813 35814 $( "#act_7_txt_input" ).focus(function() 35815 35816 { 35817 35818 $("input[name=act][value='other']","#activities_choice").prop("checked",true); 35819 35820 }); 35821 35822 $("#btn-continuous").click(function() 35823 35824 { 35825 35826 if (!submitting) { 35827 35828 submitting = true; 35829 35830 $submitBtn.html('<span><i class="fa"></i><p><i>' + txt2 + '</i></p></span>'); 35831 35832 var captcha = grecaptcha.getResponse(); 35833 35834 35835 35836 //console.log("response:"+captcha); 35837 35838 35839 35840 var name_cht = $("#name_cht_input").val(); 35841 35842 var name_eng = $("#name_eng_input").val(); 35843 35844 var birthplace = $("#hometown_input").val(); 35845 35846 var professional = $("#occupation_input").val(); 35847 35848 var address = $("#address_input").val(); 35849 35850 var tel = $("#home_phone_input").val(); 35851 35852 var phone = $("#mobile_input").val(); 35853 35854 var email = $("#email_input").val(); 35855 35856 var fax = $("#fax_input").val(); 35857 35858 var old_address = $("#former_address_input").val(); 35859 35860 var year = $("#por_input").val(); 35861 35862 35863 35864 // var work_other = $('input[name=act]:checked', '#activities_choice').val(); 35865 35866 35867 35868 // if(work_other == undefined || work_other == "undefined") 35869 35870 // { 35871 35872 // work_other = ""; 35873 35874 // } 35875 35876 35877 35878 // if(work_other=="other") 35879 35880 // { 35881 35882 // work_other = $("#act_7_txt_input").val(); 35883 35884 // } 35885 35886 35887 35888 35889 35890 35891 35892 var guided_tour = false, 35893 35894 research = false, 35895 35896 museum_administration = false, 35897 35898 artifacts_handling = false, 35899 35900 oral_history = false, 35901 35902 story_sharing = false, 35903 35904 work_other = false, 35905 35906 receive_promotion = 0; 35907 35908 35909 35910 35911 35912 if($("#act_1").is(':checked')) 35913 35914 { 35915 35916 guided_tour = 1; 35917 35918 }; 35919 35920 if($('#act_2').is(':checked')) 35921 35922 { 35923 35924 research = 1; 35925 35926 }; 35927 35928 if($('#act_3').is(':checked')) 35929 35930 { 35931 35932 museum_administration = 1; 35933 35934 }; 35935 35936 if($('#act_4').is(':checked')) 35937 35938 { 35939 35940 artifacts_handling = 1; 35941 35942 }; 35943 35944 if($('#act_5').is(':checked')) 35945 35946 { 35947 35948 oral_history = 1; 35949 35950 }; 35951 35952 if($('#act_6').is(':checked')) 35953 35954 { 35955 35956 story_sharing = 1; 35957 35958 }; 35959 35960 if($('#act_7').is(':checked')) 35961 35962 { 35963 35964 work_other = $("#act_7_txt_input").val(); 35965 35966 }; 35967 35968 35969 35970 if($('input[name="receive_promotion"]').is(':checked')) 35971 35972 { 35973 35974 receive_promotion = 1; 35975 35976 } 35977 35978 35979 35980 var gender = $('input[name=gender]:checked', '#gender_choice').val(); 35981 35982 35983 35984 35985 35986 if(gender == undefined || gender == "undefined") 35987 35988 { 35989 35990 gender = ""; 35991 35992 } 35993 35994 35995 35996 var age = $('input[name=age]:checked', '#age_choice').val(); 35997 35998 35999 36000 36001 36002 if(age == undefined || age == "undefined") 36003 36004 { 36005 36006 age = ""; 36007 36008 } 36009 36010 36011 36012 //console.log("-------------------------------"); 36013 36014 //console.log('guided_tour:'+guided_tour+"|"+research+"|"+museum_administration+"|"+artifacts_handling+"|"+oral_history+"|"+story_sharing+"|"+work_other); 36015 36016 36017 36018 $.post(YHA.common.base_url + "/api/alumni_network/submit_form", 36019 36020 { 36021 36022 name_cht:name_cht, 36023 36024 name_eng:name_eng, 36025 36026 gender:gender, 36027 36028 birthplace:birthplace, 36029 36030 professional: professional, 36031 36032 age:age, 36033 36034 address:address, 36035 36036 tel:tel, 36037 36038 phone:phone, 36039 36040 email:email, 36041 36042 fax:fax, 36043 36044 old_address:old_address, 36045 36046 year:year, 36047 36048 work_other:work_other, 36049 36050 guided_tour:guided_tour, 36051 36052 museum_administration:museum_administration, 36053 36054 oral_history:oral_history, 36055 36056 research:research, 36057 36058 artifacts_handling:artifacts_handling, 36059 36060 story_sharing:story_sharing, 36061 36062 receive_promotion:receive_promotion, 36063 36064 captcha:captcha 36065 36066 36067 36068 },(function(response) 36069 36070 { 36071 36072 submitting = false;
36073 36074 $submitBtn.html(txt1); 36075 36076 if(response.status) { 36077 36078 YHA.common.popupError(response.msg); 36079 36080 } else { 36081 36082 grecaptcha.reset(); 36083 36084 var allError =""; 36085 36086 var errorData = response.errors; 36087 36088 for(var i in errorData){ 36089 36090 allError = errorData[0]['msg']+'<br>'; 36091 36092 break; 36093 36094 } 36095 36096 YHA.common.popupError(allError); 36097 36098 } 36099 36100 36101 36102 }), 'json'); 36103 36104 } 36105 36106 }); 36107 36108 36109 36110 }; 36111 36112 36113 36114})(jQuery); 36115var YHA = YHA || {INIT_FUNC:{},RESPON_FUNC:{}}; 36116 36117 36118 36119(function($) { 36120 36121 var body_selector = ".page-contactus"; 36122 36123 var $submitBtn = $("#btn-continuous"), 36124 36125 txt1 = $submitBtn.html(), 36126 36127 txt2 = $submitBtn.attr("data-txt"), 36128 36129 loading = false; 36130 36131 36132 36133 function resetForm() { 36134 36135 $("#surname_input").val(''); 36136 36137 $("#given_name_input").val(''); 36138 36139 $("#email_input").val(''); 36140 36141 $("#contact_num_input").val(''); 36142 36143 $("#address_input").val(''); 36144 36145 $("#fax_input").val(''); 36146 36147 $("#content_input").val(''); 36148 36149 } 36150 36151 //INIT 36152 36153 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 36154 36155 YHA.INIT_FUNC[body_selector] = {}; 36156 36157 36158 36159 YHA.INIT_FUNC[body_selector]['init'] = function(){ 36160 36161 36162 36163 $("#btn-continuous").click(function() 36164 36165 { 36166 36167 if(!loading) { 36168 36169 var surname = $("#surname_input").val(); 36170 36171 var given_name = $("#given_name_input").val(); 36172 36173 var email = $("#email_input").val(); 36174 36175 var contact = $("#contact_num_input").val(); 36176 36177 var address = $("#address_input").val(); 36178 36179 var fax = $("#fax_input").val(); 36180 36181 var content = $("#content_input").val(); 36182 36183 var enquiry = $( "#enquiry option:selected" ).text(); 36184 36185 var hostel_id = $( "#hostel_id option:selected" ).val(); 36186 36187 var appel = $('input[name=appel]:checked', '#appel_choice').val(); 36188 36189 var recaptcha = $('#g-recaptcha-response').val(); 36190 36191 36192 36193 if(appel == undefined || appel == "undefined") 36194 36195 { 36196 36197 appel = ""; 36198 36199 } 36200 36201 36202 36203 //console.log("-------------------------------"); 36204 36205 //console.log('data:'+surname+"|"+given_name+"|"+email+"|"+contact+"|"+address+"|"+fax+"|"+content+"|"+enquiry); 36206 36207 36208 36209 loading = true; 36210 36211 $submitBtn.html('<span><i class="fa"></i><p><i>' + txt2 + '</i></p></span>'); 36212 36213 36214 36215 $.post(YHA.common.base_url + "/api/contactus/submit_form", 36216 36217 { 36218 36219 surname:surname, 36220 36221 given_name:given_name, 36222 36223 email:email, 36224 36225 contact: contact, 36226 36227 appellation:appel, 36228 36229 address:address, 36230 36231 fax:fax, 36232 36233 content:content, 36234 36235 enquiry:enquiry, 36236 36237 hostel_id: hostel_id, 36238 36239 'g-recaptcha-response' :recaptcha 36240 36241 },(function(response) 36242 36243 { 36244 36245 $submitBtn.html(txt1); 36246 36247 loading = false; 36248 36249 if(response.status) 36250 36251 { 36252 36253 resetForm(); 36254 36255 YHA.common.popupError(response.msg); 36256 36257 }else 36258 36259 { 36260 36261 var allError =""; 36262 36263 var errorData = response.errors; 36264 36265 for(var i in errorData){ 36266 36267 allError = errorData[0]['msg']+'<br>'; 36268 36269 break; 36270 36271 } 36272 36273 YHA.common.popupError(allError); 36274 36275 } 36276 36277 36278 36279 }), 'json'); 36280 36281 } 36282 36283 }); 36284 36285 36286 36287 }; 36288 36289 36290 36291})(jQuery); 36292var YHA = YHA || {INIT_FUNC:{},RESPON_FUNC:{}}; 36293 36294 36295 36296(function($) { 36297 36298 var body_selector = ".page-edm", 36299 36300 $body_selector = $(".page-edm"), 36301 36302 $edm_content = $body_selector.find('.edmContent'), 36303 36304 $yearchooser = $body_selector.find(".yearchooser"), 36305 36306 $year = $yearchooser.find("span"), 36307 36308 minYear = $year.attr("data-min"), 36309 36310 maxYear = $year.attr("data-max"), 36311 36312 $no_record = $body_selector.find(".no_record"), 36313 36314 $loadMore = $body_selector.find(".loadWrapper .btn"), 36315 36316 txt1 = $loadMore.text(), 36317 36318 txt2 = $loadMore.attr("data-txt"), 36319 36320 loading = false, 36321 36322 xhr; 36323 36324 36325 36326 var year=$year.attr("data-year"), page = 1, count = 10, currentOrderBy = 'newsletter_date', currentOrder = 'desc', searchTag = ''; 36327 36328 36329 36330 //INIT 36331 36332 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 36333 36334 YHA.INIT_FUNC[body_selector] = {}; 36335 36336 36337 36338 function getEdms() { 36339 36340 loading = true; 36341 36342 36343 36344 $loadMore.html('<i class="fa fa-refresh fa-spin"></i> ' + txt2); 36345 36346 36347 36348 var query = { 36349 36350 'orderby' : currentOrderBy, 36351 36352 'order' : currentOrder, 36353 36354 'page' : page, 36355 36356 'count' : count, 36357 36358 'year' : year 36359 36360 }; 36361 36362 loading = true; 36363 36364 $year.html(year).attr("data-year", year); 36365 36366 xhr = $.get(YHA.common.base_url + "/api/news/get_edms/", query, function(response) { 36367 36368 if(response.status) { 36369 36370 if(response.data.length < 1 || response.data.length < count) 36371 36372 $loadMore.hide(); 36373 36374 createBlocks(response.data); 36375 36376 } 36377 36378 $loadMore.text(txt1); 36379 36380 loading = false;
36381 36382 36383 36384 if (!$edm_content.find("> div").length) { 36385 36386 $loadMore.hide(); 36387 36388 $no_record.show(); 36389 36390 } 36391 36392 36393 36394 xhr = (function() {return;})(); 36395 36396 }, 'json'); 36397 36398 } 36399 36400 36401 36402 function createBlocks(posts) { 36403 36404 $.each(posts, function() { 36405 36406 var $html = $('<div class="columns small-12 medium-10 medium-centered">' + 36407 36408 '<a href="' + this.url + '" target="_blank" class="edmItem">' + 36409 36410 '<div class="date">' + this.newsletter_date + '</div>' + 36411 36412 '<div class="title fontf-rs">' + this.title + '</div>' + 36413 36414 '<i></i>' + 36415 36416 '</a>' + 36417 36418 '</div>'); 36419 36420 $edm_content.append($html); 36421 36422 }); 36423 36424 } 36425 36426 36427 36428 //INIT 36429 36430 YHA.INIT_FUNC[body_selector]['init'] = function(){ 36431 36432 var $prev = $yearchooser.find(".prev"), 36433 36434 $next = $yearchooser.find(".next"); 36435 36436 36437 36438 $body_selector.find('.featured-event-box').slick({ 36439 36440 arrows: false, 36441 36442 dots: true 36443 36444 }); 36445 36446 36447 36448 $prev.on("click", function(e) { 36449 36450 e.preventDefault(); 36451 36452 if (!loading && parseInt(year) >= (parseInt(minYear) + 1)) { 36453 36454 if (typeof(xhr) !== "undefined") 36455 36456 xhr.abort(); 36457 36458 loading = false; 36459 36460 $no_record.hide(); 36461 36462 $loadMore.show(); 36463 36464 36465 36466 year--; 36467 36468 page = 1; 36469 36470 $edm_content.empty(); 36471 36472 36473 36474 if (year == minYear) 36475 36476 $prev.addClass("disabled"); 36477 36478 $next.removeClass("disabled"); 36479 36480 36481 36482 getEdms(); 36483 36484 } 36485 36486 }); 36487 36488 36489 36490 $next.on("click", function(e) { 36491 36492 e.preventDefault(); 36493 36494 if (!loading && parseInt(year) <= (parseInt(maxYear) - 1)) { 36495 36496 if (typeof(xhr) !== "undefined") 36497 36498 xhr.abort(); 36499 36500 loading = false; 36501 36502 $no_record.hide(); 36503 36504 $loadMore.show(); 36505 36506 36507 36508 year++; 36509 36510 page = 1; 36511 36512 $edm_content.empty(); 36513 36514 36515 36516 if (year == maxYear) 36517 36518 $next.addClass("disabled"); 36519 36520 $prev.removeClass("disabled"); 36521 36522 36523 36524 getEdms(); 36525 36526 } 36527 36528 }); 36529 36530 36531 36532 $loadMore.on("click", function(e) { 36533 36534 e.preventDefault(); 36535 36536 if(!loading) { 36537 36538 page++; 36539 36540 getEdms(); 36541 36542 } 36543 36544 }); 36545 36546 }; 36547 36548 36549 36550})(jQuery); 36551 36552 36553var YHA = YHA || {INIT_FUNC:{},RESPON_FUNC:{}}; 36554 36555 36556 36557(function($) { 36558 36559 var body_selector = ".page-events", 36560 36561 $body_selector = $(body_selector), 36562 36563 $masonry = $body_selector.find(".masonryAreaWrapper"), 36564 36565 $no_record = $body_selector.find(".no_record"), 36566 36567 $loadMore = $body_selector.find(".loadWrapper .btn"), 36568 36569 txt1 = $loadMore.text(), 36570 36571 txt2 = $loadMore.attr("data-txt"), 36572 36573 loading = false, 36574 36575 xhr; 36576 36577 36578 36579 var page = 1, count = 8, currentOrderBy = 'event_date_from', currentOrder = 'desc', searchTag = ''; 36580 36581 36582 36583 //INIT 36584 36585 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 36586 36587 YHA.INIT_FUNC[body_selector] = {}; 36588 36589 36590 36591 function getEvents(type) { 36592 36593 loading = true; 36594 36595 36596 36597 $loadMore.html('<i class="fa fa-refresh fa-spin"></i> ' + txt2); 36598 36599 36600 36601 var query = { 36602 36603 'orderby' : currentOrderBy, 36604 36605 'order' : currentOrder, 36606 36607 'page' : page, 36608 36609 'count' : count, 36610 36611 'type' : type 36612 36613 }; 36614 36615 loading = true; 36616 36617 xhr = $.get(YHA.common.base_url + "/api/news/get_events/", query, function(response) { 36618 36619 if(response.status) { 36620 36621 if(response.data.length < 1 || response.data.length < count) 36622 36623 $loadMore.hide(); 36624 36625 createBlocks(response.data); 36626 36627 } 36628 36629 $loadMore.text(txt1); 36630 36631 loading = false; 36632 36633 36634 36635 if (!$masonry.find(".article").length) { 36636 36637 $loadMore.hide(); 36638 36639 $no_record.show(); 36640 36641 } 36642 36643 36644 36645 xhr = (function() {return;})(); 36646 36647 }, 'json'); 36648 36649 } 36650 36651 36652 36653 function createBlocks(posts) { 36654 36655 var post; 36656 36657 for ( var i = 0, l = posts.length; i < l; i++ ) { 36658 36659 post = posts[i]; 36660 36661 var $html = $('<div class="article">' + 36662 36663 '<a href="' + post.url + '">' + 36664 36665 (post.thumbnail ? '<img src="' + post.thumbnail.url + '" alt="' + post.thumbnail.alt + '" />' : '') + 36666 36667 '<div class="articleContent">' + 36668 36669 '<div class="news-date">' + post.event_date_from + '</div>' + 36670 36671 '<h4 class="title blue-title">
36671' + post.title + '</h4>' + 36672 36673 '<span class="rightArrow"><i class="fa fa-arrow-right"></i></span>' + 36674 36675 '</div>' + 36676 36677 '</a>' + 36678 36679 '</div>'); 36680 36681 36682 36683 $("<img />").attr("src", post.thumbnail.url).load(function() { 36684 36685 $masonry.masonry('layout'); 36686 36687 }); 36688 36689 36690 36691 $masonry.append($html).masonry("appended", $html).masonry('layout'); 36692 36693 } 36694 36695 } 36696 36697 36698 36699 YHA.INIT_FUNC[body_selector]['init'] = function(){ 36700 36701 36702 36703 $body_selector.find('.featured-event-box').slick({ 36704 36705 arrows: false, 36706 36707 dots: true 36708 36709 }); 36710 36711 36712 36713 $body_selector.find('.event-chooser a').click(function() { 36714 36715 if (typeof(xhr) !== "undefined") 36716 36717 xhr.abort(); 36718 36719 loading = false; 36720 36721 $no_record.hide(); 36722 36723 $loadMore.show(); 36724 36725 36726 36727 $(this).siblings('a').removeClass('active'); 36728 36729 $(this).addClass('active'); 36730 36731 36732 36733 page = 1; 36734 36735 $masonry.masonry('remove', $('.article')).masonry('layout'); 36736 36737 getEvents($(this).attr('data-type')); 36738 36739 }); 36740 36741 36742 36743 $body_selector.find(".loadWrapper").on("click", function(e) { 36744 36745 e.preventDefault(); 36746 36747 if(!loading) { 36748 36749 page++; 36750 36751 getEvents($body_selector.find('.event-chooser a.active').attr('data-type')); 36752 36753 } 36754 36755 }); 36756 36757 }; 36758 36759 36760 36761})(jQuery); 36762 36763 36764var YHA = YHA || {}; 36765 36766 36767 36768(function($) { 36769 36770 var body_selector = ".page-experience", 36771 36772 $body_selector = $(".page-experience"), 36773 36774 $masonry = $body_selector.find(".masonryAreaWrapper"), 36775 36776 $no_record = $body_selector.find(".no_record"), 36777 36778 $loadMore = $body_selector.find(".loadWrapper .btn"), 36779 36780 txt1 = $loadMore.text(), 36781 36782 txt2 = $loadMore.attr("data-txt"), 36783 36784 loading = false, 36785 36786 xhr; 36787 36788 36789 36790 var page = 1, count = 8, currentCategory = 'all', currentOrderBy = 'article_date', currentOrder = 'desc', searchTag = $body_selector.find("input[name=search]").val(); 36791 36792 var stopLoad = false, searchLock = false, searchInputInterval; 36793 36794 36795 36796 //INIT 36797 36798 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 36799 36800 YHA.RESPON_FUNC = YHA.RESPON_FUNC || {}; 36801 36802 YHA.INIT_FUNC[body_selector] = {}; 36803 36804 YHA.RESPON_FUNC[body_selector] = {}; 36805 36806 36807 36808 var delay = (function(){ 36809 36810 var timer = 0; 36811 36812 return function(callback, ms){ 36813 36814 clearTimeout (timer); 36815 36816 timer = setTimeout(callback, ms); 36817 36818 }; 36819 36820 })(); 36821 36822 36823 36824 function getExperiences() { 36825 36826 loading = true; 36827 36828 36829 36830 $loadMore.html('<i class="fa fa-refresh fa-spin"></i> ' + txt2); 36831 36832 36833 36834 var query = { 36835 36836 'orderby' : currentOrderBy, 36837 36838 'order' : currentOrder, 36839 36840 'page' : page, 36841 36842 'count' : count, 36843 36844 }; 36845 36846 if(currentCategory != 'all') 36847 36848 query['category_slug'] = currentCategory; 36849 36850 if(searchTag != '') 36851 36852 query['tag'] = searchTag; 36853 36854 36855 36856 xhr = $.get(YHA.common.base_url + "/api/explore/get_experiences/", query, function(response){ 36857 36858 if(response.status) { 36859 36860 if(response.data.length < 1 || response.data.length < count) 36861 36862 $loadMore.hide(); 36863 36864 createBlocks(response.data); 36865 36866 } 36867 36868 $loadMore.text(txt1); 36869 36870 loading = false; 36871 36872 36873 36874 if (!$masonry.find(".article").length) { 36875 36876 $loadMore.hide(); 36877 36878 $no_record.show(); 36879 36880 } 36881 36882 36883 36884 xhr = (function() {return;})(); 36885 36886 }, 'json'); 36887 36888 } 36889 36890 36891 36892 function createBlocks(posts) { 36893 36894 var post; 36895 36896 for ( var i = 0, l = posts.length; i < l; i++ ) { 36897 36898 post = posts[i]; 36899 36900 var $html = $('<div class="article">' + 36901 36902 '<a href="' + post.url + '">' + 36903 36904 (post.image_url != "" ? '<img src="' + post.image_url + '" alt="' + post.title + '" class="thumb" />' : '' ) + 36905 36906 '<img class="ribbon" src="' + YHA.common.template_url + '/images/' + YHA.common.lang + '/tab_' + post.category_name.toLowerCase() + '.png"/>' + 36907 36908 '<div class="articleContent">' + 36909 36910 '<h4 class="title">
36910' + post.title + '</h4>' + 36911 36912 '<div class="date">' + post.article_date + '</div>' + 36913 36914 '<span class="rightArrow"><i class="fa fa-arrow-right"></i></span>' + 36915 36916 '</div>' + 36917 36918 '</a>' + 36919 36920 '</div>'); 36921 36922 $masonry.append($html).masonry("appended", $html); 36923 36924 36925 36926 $("<img />").attr("src", post.image_url).load(function() { 36927 36928 $masonry.masonry('layout'); 36929 36930 }); 36931 36932 } 36933 36934 $masonry.masonry('layout'); 36935 36936 } 36937 36938 36939 36940 function changeCategory(category) { 36941 36942 if (typeof(xhr) !== "undefined") 36943 36944 xhr.abort(); 36945 36946 loading = false; 36947 36948 $no_record.hide(); 36949 36950 $loadMore.show(); 36951 36952 36953 36954 currentCategory = category; 36955 36956 page = 1; 36957 36958 $masonry.masonry('remove', $('.article')).masonry('layout'); 36959 36960 getExperiences(); 36961 36962 } 36963 36964 36965 36966 function changeOrderBy(sortBy) { 36967 36968 if (typeof(xhr) !== "undefined") 36969 36970 xhr.abort(); 36971 36972 loading = false; 36973 36974 $no_record.hide(); 36975 36976 $loadMore.show(); 36977 36978 36979 36980 var orderArray = sortBy.split(','); 36981 36982 currentOrderBy = orderArray[0]; 36983 36984 currentOrder = orderArray[1]; 36985 36986 page = 1; 36987 36988 $masonry.masonry('remove', $('.article')).masonry('layout'); 36989 36990 getExperiences(); 36991 36992 } 36993 36994 36995 36996 //INIT 36997 36998 YHA.INIT_FUNC[body_selector]['init'] = function(){ 36999 37000 $body_selector.find("select[name=category]").change(function() { 37001 37002 changeCategory($(this).val()); 37003 37004 }); 37005 37006 $body_selector.find("select[name=sortBy]").change(function() { 37007 37008 changeOrderBy($(this).val()); 37009 37010 }); 37011 37012 $body_selector.find("input[name=search]").keyup(function() { 37013 37014 var value = $(this).val(); 37015 37016 delay(function(){ 37017 37018 if (typeof(xhr) !== "undefined") 37019 37020 xhr.abort(); 37021 37022 loading = false; 37023 37024 $no_record.hide(); 37025 37026 $loadMore.show(); 37027 37028 37029 37030 searchTag = value; 37031 37032 page = 1; 37033 37034 $masonry.masonry('remove', $('.article')).masonry('layout'); 37035 37036 getExperiences(); 37037 37038 }, 500 ); 37039 37040 }); 37041 37042 37043 37044 $loadMore.on("click", function(e) { 37045 37046 e.preventDefault(); 37047 37048 if(!loading) { 37049 37050 page++; 37051 37052 getExperiences(); 37053 37054 } 37055 37056 }); 37057 37058 }; 37059 37060 37061 37062 37063 37064})(jQuery); 37065var YHA = YHA || {}; 37066 37067 37068 37069(function($) { 37070 37071 var body_selector = ".page-photo-gallery", 37072 37073 $body_selector = $(body_selector), 37074 37075 $masonry = $body_selector.find(".masonryAreaWrapper"), 37076 37077 $no_record = $body_selector.find(".no_record"), 37078 37079 $loadMore = $body_selector.find(".loadWrapper .btn"), 37080 37081 txt1 = $loadMore.text(), 37082 37083 txt2 = $loadMore.attr("data-txt"), 37084 37085 loading = false, 37086 37087 xhr; 37088 37089 37090 37091 var page = 1, count = 1; 37092 37093 37094 37095 //INIT 37096 37097 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 37098 37099 YHA.RESPON_FUNC = YHA.RESPON_FUNC || {}; 37100 37101 YHA.INIT_FUNC[body_selector] = {}; 37102 37103 YHA.RESPON_FUNC[body_selector] = {}; 37104 37105 37106 37107 function getExperiences() { 37108 37109 loading = true; 37110 37111 37112 37113 $loadMore.html('<i class="fa fa-refresh fa-spin"></i> ' + txt2); 37114 37115 37116 37117 var query = { 37118 37119 'page' : page, 37120 37121 'count' : count, 37122 37123 }; 37124 37125 37126 37127 xhr = $.get(YHA.common.base_url + "/api/news/get_galleries_list/", query, function(response){ 37128 37129 if(response.status) { 37130 37131 if(response.data.length < 1 || response.data.length < count) 37132 37133 $loadMore.hide(); 37134 37135 createBlocks(response.data); 37136 37137 } 37138 37139 $loadMore.text(txt1); 37140 37141 loading = false; 37142 37143 37144 37145 if (!$masonry.find(".article").length) { 37146 37147 $loadMore.hide(); 37148 37149 $no_record.show(); 37150 37151 } 37152 37153 37154 37155 xhr = (function() {return;})(); 37156 37157 }, 'json'); 37158 37159 } 37160 37161 37162 37163 function createBlocks(posts) { 37164 37165 var post; 37166 37167 //(post.image ?'<img src="' + post.image.url + '" alt="' + post.title + '" />':'') + 37168 37169 for ( var i = 0, l = posts.length; i < l; i++ ) { 37170 37171 post = posts[i]; 37172 37173 var $html = $('' + 37174 37175 '<div class="article">' + 37176 37177 '<a href="' + post.url + '">' + 37178 37179 (post.image ?'<img src="' + post.image.url + '" alt="' + post.title + '" />':'') + 37180 37181 '<div class="articleContent">' + 37182 37183 '<div class="title">' + post.title + '</div>' + 37184 37185 '<div class="date">' + post.date + '</div>' + 37186 37187 '<div class="summary">' + 37188 37189 (post.total_images > 0 ?'<span>' + post.total_images + '<i class="fa fa-picture-o"></i></span>':'') + 37190 37191 (post.total_videos > 0 ?'<span>' + post.total_videos + '<i class="fa fa-film"></i></span>':'') + 37192 37193 '</div>' + 37194 37195 '</div>' + 37196 37197 '</a>' + 37198 37199 '</div>'); 37200 37201 37202 37203 $masonry.append($html).masonry("appended", $html); 37204 37205 37206 37207 $("<img />").attr("src", post.image.url).load(function() { 37208 37209 $masonry.masonry('layout'); 37210 37211 }); 37212 37213 } 37214 37215 $masonry.masonry('layout'); 37216 37217 } 37218 37219 37220 37221 //INIT 37222 37223 YHA.INIT_FUNC[body_selector]['init'] = function(){ 37224 37225 $loadMore.on("click", function(e) { 37226 37227 e.preventDefault(); 37228 37229 if(!loading) { 37230 37231 page++; 37232 37233 getExperiences(); 37234 37235 } 37236 37237 }); 37238 37239 }; 37240 37241 37242 37243 37244 37245})(jQuery); 37246var YHA = YHA || {INIT_FUNC:{},RESPON_FUNC:{}}; 37247 37248 37249 37250(function($) { 37251
37252 var body_selector = ".page-group-member-application"; 37253 37254 var $submitBtn = $("#btn-continuous"), 37255 37256 txt1 = $submitBtn.html(), 37257 37258 txt2 = $submitBtn.attr("data-txt"), 37259 37260 loading = false; 37261 37262 37263 37264 function redirectToPaymentGateway(response) { 37265 37266 var hiddenForm = response.html; 37267 37268 $('#form-section').hide(); 37269 37270 $('#payment-processing').show(); 37271 37272 window.scrollTo(0,0); 37273 37274 $(body_selector + ' .hidden-section').html(hiddenForm); 37275 37276 } 37277 37278 37279 37280 function showThankyou() { 37281 37282 $('#form-section').hide(); 37283 37284 $('#thankyou-section').show(); 37285 37286 window.scrollTo(0,0); 37287 37288 } 37289 37290 //INIT 37291 37292 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 37293 37294 YHA.INIT_FUNC[body_selector] = {}; 37295 37296 37297 37298 YHA.INIT_FUNC[body_selector]['init'] = function() { 37299 37300 $('input[type=radio][name=application_type]').change(function() { 37301 37302 if(/(renewal)/i.test($(this).val())) { 37303 37304 $('#member-id').attr('disabled', false).focus(); 37305 37306 } else { 37307 37308 $('#member-id').attr('disabled', true); 37309 37310 } 37311 37312 }); 37313 37314 $('input[data-target-input]').change(function() { 37315 37316 var targetInput = $(this).attr('data-target-input'); 37317 37318 if($(this).is(':checked')) { 37319 37320 $(targetInput).attr('disabled', false).focus(); 37321 37322 } else { 37323 37324 $(targetInput).attr('disabled', true); 37325 37326 } 37327 37328 }); 37329 37330 $("input:file").change(function (){ 37331 37332 var filename = $(this).val().split('\\').pop(); 37333 37334 $(this).parents('.field-group-file-upload').find('.file-name').html(filename); 37335 37336 }); 37337 37338 $("#btn-continuous").click(function() { 37339 37340 if(!loading) { 37341 37342 loading = true; 37343 37344 $submitBtn.html('<span><i class="fa"></i><p><i>' + txt2 + '</i></p></span>'); 37345 37346 var $applicationForm = $('#application-form'); 37347 37348 $applicationForm.ajaxSubmit({ 37349 37350 url : YHA.common.base_url + "/api/group_membership/submit_form", 37351 37352 success: function(response) { 37353 37354 loading = false; 37355 37356 $submitBtn.html(txt1); 37357 37358 if(response.status) { 37359 37360 if(response.html) { 37361 37362 redirectToPaymentGateway(response); 37363 37364 } else { 37365 37366 $('.ref_id').text(response.ref_id); 37367 37368 showThankyou(); 37369 37370 } 37371 37372 } else { 37373 37374 var errorData = response.errors; 37375 37376 var allError = ""; 37377 37378 for(var i in errorData) { 37379 37380 allError = errorData[0]['msg']+'<br>'; 37381 37382 break; 37383 37384 } 37385 37386 YHA.common.popupError(allError); 37387 37388 } 37389 37390 }, 37391 37392 error: function() { 37393 37394 loading = false; 37395 37396 $submitBtn.html(txt1); 37397 37398 YHA.common.popupError('Network error'); 37399 37400 } 37401 37402 }); 37403 37404 } 37405 37406 }); 37407 37408 }; 37409 37410})(jQuery); 37411var YHA = YHA || {INIT_FUNC:{},RESPON_FUNC:{}}; 37412 37413 37414 37415(function($) { 37416 37417 var body_selector = ".page-individual-member-application"; 37418 37419 var $submitBtn = $("#btn-continuous"), 37420 37421 txt1 = $submitBtn.html(), 37422 37423 txt2 = $submitBtn.attr("data-txt"), 37424 37425 loading = false; 37426 37427 var $year_selector = $('select[name=birthday_year]'), 37428 37429 $month_selector = $('select[name=birthday_month]'), 37430 37431 $day_selector = $('select[name=birthday_day]'); 37432 37433 37434 37435 function redirectToPaymentGateway(response) { 37436 37437 var hiddenForm = response.html; 37438 37439 $('#form-section').hide(); 37440 37441 $('#payment-processing').show(); 37442 37443 window.scrollTo(0,0); 37444 37445 $(body_selector + ' .hidden-section').html(hiddenForm); 37446 37447 } 37448 37449 function setDayOptions(max_days) { 37450 37451 var html = $day_selector.find('option:first-child')[0].outerHTML; 37452 37453 var currentDay = parseInt($day_selector.val()); 37454 37455 for(var i = 1; i <= max_days; i++) { 37456 37457 if(currentDay == i) { 37458 37459 html += '<option value="'+ i + '" selected>' + i + '</option>'; 37460 37461 } else { 37462 37463 html += '<option value="'+ i + '">' + i + '</option>'; 37464 37465 } 37466 37467 } 37468 37469 $day_selector.html(html); 37470 37471 if(currentDay > max_days) { 37472 37473 $day_selector.prop('selectedIndex',0); 37474 37475 } 37476 37477 } 37478 37479 function checkDays() { 37480 37481 var monthsWithShortDays= [2,4,5,9,11]; 37482 37483 var currentMonth = parseInt($month_selector.val()); 37484 37485 var currentYear = parseInt($year_selector.val()); 37486 37487 37488 37489 if(currentMonth == 2) { 37490 37491 if(currentYear % 4 == 0) { 37492 37493 setDayOptions(29); 37494 37495 } else { 37496 37497 setDayOptions(28); 37498 37499 } 37500 37501 } else if(monthsWithShortDays.indexOf(currentMonth) > -1) { 37502 37503 setDayOptions(30); 37504 37505 } else { 37506 37507 setDayOptions(31); 37508 37509 } 37510 37511 } 37512 37513 //INIT 37514 37515 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 37516 37517 YHA.INIT_FUNC[body_selector] = {}; 37518 37519 37520 37521 YHA.INIT_FUNC[body_selector]['init'] = function(){ 37522 37523 $year_selector.change(function() { 37524 37525 checkDays(); 37526 37527 }); 37528 37529 $month_selector.change(function() { 37530 37531 checkDays(); 37532 37533 }); 37534 37535 $('input[type=radio][name=application_type]').change(function() { 37536 37537 if(/(renewal)/i.test($(this).val())) { 37538 37539 $('#member-id').attr('disabled', false).focus(); 37540 37541 } else { 37542 37543 $('#member-id').attr('disabled', true); 37544 37545 } 37546 37547 }); 37548 37549 $('input[data-target-input]').change(function() { 37550 37551 var targetInput = $(this).attr('data-target-input'); 37552 37553 if($(this).is(':checked')) { 37554 37555 $(targetInput).attr('disabled', false).focus(); 37556 37557 } else { 37558 37559 $(targetInput).attr('disabled', true); 37560 37561 } 37562 37563 }); 37564 37565 $("#btn-continuous").click(function() 37566 37567 { 37568 37569 if(!loading) { 37570 37571 loading = true; 37572 37573 $submitBtn.html('<span><i class="fa"></i><p><i>' + txt2 + '</i></p></span>'); 37574 37575 var $applicationForm = $('#application-form'); 37576 37577 $applicationForm.ajaxSubmit({ 37578 37579 url : YHA.common.base_url + "/api/individual_membership/submit_form", 37580 37581 success: function(response) { 37582 37583 loading = false;
37584 37585 $submitBtn.html(txt1); 37586 37587 if(response.status) { 37588 37589 redirectToPaymentGateway(response); 37590 37591 } else { 37592 37593 var errorData = response.errors; 37594 37595 var allError = ""; 37596 37597 for(var i in errorData) { 37598 37599 allError = errorData[0]['msg']+'<br>'; 37600 37601 break; 37602 37603 } 37604 37605 YHA.common.popupError(allError); 37606 37607 } 37608 37609 }, 37610 37611 error: function() { 37612 37613 loading = false; 37614 37615 $submitBtn.html(txt1); 37616 37617 YHA.common.popupError('Network error'); 37618 37619 } 37620 37621 }); 37622 37623 } 37624 37625 }); 37626 37627 }; 37628 37629})(jQuery); 37630var YHA = YHA || {}; 37631 37632 37633 37634(function($) { 37635 37636 var body_selector = ".page-media-center", 37637 37638 $body_selector = $(body_selector), 37639 37640 $masonry = $body_selector.find(".masonryAreaWrapper"), 37641 37642 $no_record = $body_selector.find(".countryWrapper .no_record"), 37643 37644 $loadMore = $body_selector.find(" .loadWrapper .btn"), 37645 37646 txt1 = $loadMore.text(), 37647 37648 txt2 = $loadMore.attr("data-txt"), 37649 37650 loading = false, 37651 37652 xhr; 37653 37654 var page = 1, count = 9, currentOrderBy = 'news_date', currentOrder = 'desc', searchTag = ''; 37655 37656 var stopLoad = false, searchLock = false, searchInputInterval; 37657 37658 37659 37660 //INIT 37661 37662 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 37663 37664 YHA.RESPON_FUNC = YHA.RESPON_FUNC || {}; 37665 37666 YHA.INIT_FUNC[body_selector] = {}; 37667 37668 YHA.RESPON_FUNC[body_selector] = {}; 37669 37670 37671 37672 var delay = (function(){ 37673 37674 var timer = 0; 37675 37676 return function(callback, ms){ 37677 37678 clearTimeout (timer); 37679 37680 timer = setTimeout(callback, ms); 37681 37682 }; 37683 37684 })(); 37685 37686 37687 37688 function getMediaCenters() { 37689 37690 loading = true; 37691 37692 37693 37694 $loadMore.html('<i class="fa fa-refresh fa-spin"></i> ' + txt2); 37695 37696 37697 37698 var query = { 37699 37700 'orderby' : currentOrderBy, 37701 37702 'order' : currentOrder, 37703 37704 'page' : page, 37705 37706 'count' : count 37707 37708 }; 37709 37710 loading = true; 37711 37712 $year.html(year).attr("data-year", year); 37713 37714 xhr = $.get(YHA.common.base_url + "/api/news/get_news/", query, function(response) { 37715 37716 if(response.status) { 37717 37718 if(response.data.length < 1 || response.data.length < count) 37719 37720 $loadMore.hide(); 37721 37722 createBlocks(response.data); 37723 37724 } 37725 37726 $loadMore.text(txt1); 37727 37728 loading = false; 37729 37730 37731 37732 if (!$masonry.find(".article").length) { 37733 37734 $loadMore.hide(); 37735 37736 $no_record.show(); 37737 37738 } 37739 37740 37741 37742 xhr = (function() {return;})(); 37743 37744 }, 'json'); 37745 37746 } 37747 37748 37749 37750 function createBlocks(posts) { 37751 37752 var post; 37753 37754 for ( var i = 0, l = posts.length; i < l; i++ ) { 37755 37756 post = posts[i]; 37757 37758 37759 37760 var $html = $('' + 37761 37762 '<div class="article">' + 37763 37764 '<a href="' + post.url + '">' + 37765 37766 (post.image_url ? '<img src="' + post.image_url + '" alt="' + post.title + '" />' : '') + 37767 37768 '<div class="articleContent">' + 37769 37770 '<div class="news-date">' + post.date + '</div>' + 37771 37772 '<div class="blue-title">' + post.title + '</div>' + 37773 37774 '<span class="rightArrow"><i class="fa fa-arrow-right"></i></span>' + 37775 37776 '</div>' + 37777 37778 '</a>' + 37779 37780 '</div>'); 37781 37782 $masonry.append($html).masonry("appended", $html); 37783 37784 37785 37786 $("<img />").attr("src", post.image_url).load(function() { 37787 37788 $masonry.masonry('layout'); 37789 37790 }); 37791 37792 } 37793 37794 $masonry.masonry('layout'); 37795 37796 } 37797 37798 37799 37800 //INIT 37801 37802 YHA.INIT_FUNC[body_selector]['init'] = function(){ 37803 37804 $loadMore.on("click", function(e) { 37805 37806 e.preventDefault(); 37807 37808 if(!loading) { 37809 37810 page++; 37811 37812 getMediaCenters(); 37813 37814 } 37815 37816 }); 37817 37818 }; 37819 37820 37821 37822 37823 37824})(jQuery); 37825var YHA = YHA || {}; 37826 37827 37828 37829(function($) { 37830 37831 var body_selector = ".page-member-offers", 37832 37833 $body_selector = $(body_selector), 37834 37835 $masonry = $body_selector.find(".masonryAreaWrapper"), 37836 37837 $cat_icons = $body_selector.find(".circle_icons"), 37838 37839 $cat_select = $body_selector.find(".categoryWrapper select"), 37840 37841 $no_record = $body_selector.find(".no_record"), 37842 37843 $loadMore = $body_selector.find(".loadWrapper .btn"), 37844 37845 txt1 = $loadMore.text(), 37846 37847 txt2 = $loadMore.attr("data-txt"), 37848 37849 loading = false, 37850 37851 xhr, 37852 37853 page = 1, 37854 37855 count = 5, 37856 37857 currentCategory = $cat_icons.find(".on").attr("data-id"); 37858 37859 37860 37861 //INIT 37862 37863 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 37864 37865 YHA.RESPON_FUNC = YHA.RESPON_FUNC || {}; 37866 37867 YHA.INIT_FUNC[body_selector] = {}; 37868 37869 YHA.RESPON_FUNC[body_selector] = {}; 37870 37871 37872
37873 var delay = (function(){ 37874 37875 var timer = 0; 37876 37877 return function(callback, ms){ 37878 37879 clearTimeout (timer); 37880 37881 timer = setTimeout(callback, ms); 37882 37883 }; 37884 37885 })(); 37886 37887 37888 37889 function getMemberOffers() { 37890 37891 loading = true; 37892 37893 37894 37895 $loadMore.html('<i class="fa fa-refresh fa-spin"></i> ' + txt2); 37896 37897 37898 37899 var query = { 37900 37901 'page' : page, 37902 37903 'count' : count, 37904 37905 'cat' : currentCategory 37906 37907 }; 37908 37909 loading = true; 37910 37911 xhr = $.get(YHA.common.base_url + "/api/memberoffer/get_member_offers/", query, function(response) { 37912 37913 if(response.status) { 37914 37915 if(response.data.length < 1 || response.data.length < count) 37916 37917 $loadMore.hide(); 37918 37919 createBlocks(response.data); 37920 37921 } 37922 37923 $loadMore.text(txt1); 37924 37925 loading = false; 37926 37927 37928 37929 if (!$masonry.find(".article").length) { 37930 37931 $loadMore.hide(); 37932 37933 $no_record.show(); 37934 37935 } 37936 37937 37938 37939 xhr = (function() {return;})(); 37940 37941 }, 'json'); 37942 37943 } 37944 37945 37946 37947 function createBlocks(posts) { 37948 37949 var post; 37950 37951 var txt_gotowebsite = $masonry.attr("data-txt"); 37952 37953 for ( var i = 0, l = posts.length; i < l; i++ ) { 37954 37955 post = posts[i]; 37956 37957 var $html = $('' + 37958 37959 '<div class="article">' + 37960 37961 (post.image ? '<img src="' + post.image.url + '" alt="' + post.image.alt + '" title="' + post.image.title + '" />' : '') + 37962 37963 '<div class="articleContent">' + 37964 37965 '<div class="article-title">' + post.title + '</div>' + 37966 37967 (post.subtitle ? '<div class="blue-title">' + post.subtitle + '</div>' : '') + 37968 37969 (post.content ? '<div class="article-para">' + post.content + '</div>' : '') + 37970 37971 (post.address ? '<div class="icon-para"><i class="fa fa-home"></i>' + post.address + '</div>' : '') + 37972 37973 (post.phone ? '<div class="icon-para"><i class="fa fa-phone"></i>' + post.phone + '</div>' : '') + 37974 37975 (post.url ? '<ul class="arrow-list"><li><a href="' + post.url + '" target="_blank">' + txt_gotowebsite + '</a></li></ul>' : '') + 37976 37977 '</div>' + 37978 37979 '</div>'); 37980 37981 if (post.image) { 37982 37983 // console.log(post.image.url); 37984 37985 $("<img />").attr("src", post.image.url).load(function() { 37986 37987 // console.log('img loaded: ' + post.image.url); 37988 37989 $masonry.masonry('layout'); 37990 37991 }); 37992 37993 } 37994 37995 $masonry.append($html).masonry("appended", $html).masonry('layout'); 37996 37997 } 37998 37999 } 38000 38001 38002 38003 function updateCategory(category) { 38004 38005 if (currentCategory != category) { 38006 38007 if (typeof(xhr) !== "undefined") 38008 38009 xhr.abort(); 38010 38011 loading = false; 38012 38013 currentCategory = category; 38014 38015 page = 1; 38016 38017 $no_record.hide(); 38018 38019 $loadMore.show(); 38020 38021 38022 38023 $cat_icons.find("a.on").removeClass("on"); 38024 38025 $cat_icons.find("a[data-id=" + currentCategory + "]").addClass("on"); 38026 38027 38028 38029 $cat_select.find("option[selected=selected]").removeAttr("selected"); 38030 38031 $cat_select.find("option[value=" + currentCategory + "]").attr("selected","selected"); 38032 38033 38034 38035 $masonry.find(".article").each(function() { 38036 38037 $masonry.masonry("remove", this); 38038 38039 }); 38040 38041 $masonry.masonry("layout"); 38042 38043 getMemberOffers(); 38044 38045 } 38046 38047 } 38048 38049 38050 38051 //INIT 38052 38053 YHA.INIT_FUNC[body_selector]['init'] = function(){ 38054 38055 $cat_icons.on("click", "a", function(e) { 38056 38057 e.preventDefault(); 38058 38059 updateCategory($(this).attr("data-id")); 38060 38061 }); 38062 38063 38064 38065 $cat_select.on("change", function(e) { 38066 38067 e.preventDefault(); 38068 38069 updateCategory($(this).val()); 38070 38071 }); 38072 38073 38074 38075 $loadMore.on("click", function(e) { 38076 38077 e.preventDefault(); 38078 38079 if(!loading) { 38080 38081 page++; 38082 38083 getMemberOffers(); 38084 38085 } 38086 38087 }); 38088 38089 }; 38090 38091 38092 38093 38094 38095})(jQuery); 38096var YHA = YHA || {}; 38097 38098 38099 38100(function($) { 38101 38102 var body_selector = ".page-news", 38103 38104 $body_selector = $(".page-news"), 38105 38106 $masonry = $body_selector.find(".masonryAreaWrapper"), 38107 38108 $yearchooser = $body_selector.find(".yearchooser"), 38109 38110 $year = $yearchooser.find("span"), 38111 38112 minYear = $year.attr("data-min"), 38113 38114 maxYear = $year.attr("data-max"), 38115 38116 $no_record = $body_selector.find(".countryWrapper .no_record"), 38117 38118 $loadMore = $body_selector.find(" .loadWrapper .btn"), 38119 38120 txt1 = $loadMore.text(), 38121 38122 txt2 = $loadMore.attr("data-txt"), 38123 38124 loading = false, 38125 38126 xhr; 38127 38128 var year=$year.attr("data-year"), page = 1, count = 9, currentOrderBy = 'news_date', currentOrder = 'desc', searchTag = ''; 38129 38130 var stopLoad = false, searchLock = false, searchInputInterval; 38131 38132 38133 38134 //INIT 38135 38136 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 38137 38138 YHA.RESPON_FUNC = YHA.RESPON_FUNC || {}; 38139 38140 YHA.INIT_FUNC[body_selector] = {}; 38141 38142 YHA.RESPON_FUNC[body_selector] = {}; 38143 38144 38145
38146 var delay = (function(){ 38147 38148 var timer = 0; 38149 38150 return function(callback, ms){ 38151 38152 clearTimeout (timer); 38153 38154 timer = setTimeout(callback, ms); 38155 38156 }; 38157 38158 })(); 38159 38160 38161 38162 function getNews() { 38163 38164 loading = true; 38165 38166 38167 38168 $loadMore.html('<i class="fa fa-refresh fa-spin"></i> ' + txt2); 38169 38170 38171 38172 var query = { 38173 38174 'orderby' : currentOrderBy, 38175 38176 'order' : currentOrder, 38177 38178 'page' : page, 38179 38180 'count' : count, 38181 38182 'year' : year 38183 38184 }; 38185 38186 loading = true; 38187 38188 $year.html(year).attr("data-year", year); 38189 38190 xhr = $.get(YHA.common.base_url + "/api/news/get_news/", query, function(response) { 38191 38192 if(response.status) { 38193 38194 if(response.data.length < 1 || response.data.length < count) 38195 38196 $loadMore.hide(); 38197 38198 createBlocks(response.data); 38199 38200 } 38201 38202 $loadMore.text(txt1); 38203 38204 loading = false; 38205 38206 38207 38208 if (!$masonry.find(".article").length) { 38209 38210 $loadMore.hide(); 38211 38212 $no_record.show(); 38213 38214 } 38215 38216 38217 38218 xhr = (function() {return;})(); 38219 38220 }, 'json'); 38221 38222 } 38223 38224 38225 38226 function createBlocks(posts) { 38227 38228 var post; 38229 38230 for ( var i = 0, l = posts.length; i < l; i++ ) { 38231 38232 post = posts[i]; 38233 38234 38235 38236 var $html = $('' + 38237 38238 '<div class="article">' + 38239 38240 '<a href="' + post.url + '">' + 38241 38242 (post.image_url ? '<img src="' + post.image_url + '" alt="' + post.title + '" />' : '') + 38243 38244 '<div class="articleContent">' + 38245 38246 '<div class="news-date">' + post.date + '</div>' + 38247 38248 '<h4 class="title blue-title">' + post.title + '</h4>' + 38249 38250 '<span class="rightArrow"><i class="fa fa-arrow-right"></i></span>' + 38251 38252 '</div>' + 38253 38254 '</a>' + 38255 38256 '</div>'); 38257 38258 $masonry.append($html).masonry("appended", $html); 38259 38260 38261 38262 $("<img />").attr("src", post.image_url).load(function() { 38263 38264 $masonry.masonry('layout'); 38265 38266 }); 38267 38268 } 38269 38270 $masonry.masonry('layout'); 38271 38272 } 38273 38274 38275 38276 //INIT 38277 38278 YHA.INIT_FUNC[body_selector]['init'] = function(){ 38279 38280 var $prev = $yearchooser.find(".prev"), 38281 38282 $next = $yearchooser.find(".next"); 38283 38284 $prev.on("click", function(e) { 38285 38286 e.preventDefault(); 38287 38288 if (!loading && parseInt(year) >= (parseInt(minYear) + 1)) { 38289 38290 if (typeof(xhr) !== "undefined") 38291 38292 xhr.abort(); 38293 38294 loading = false; 38295 38296 $no_record.hide(); 38297 38298 $loadMore.show(); 38299 38300 38301 38302 year--; 38303 38304 page = 1; 38305 38306 $masonry.masonry('remove', $('.article')).masonry('layout'); 38307 38308 38309 38310 if (year == minYear) 38311 38312 $prev.addClass("disabled"); 38313 38314 $next.removeClass("disabled"); 38315 38316 38317 38318 getNews(); 38319 38320 } 38321 38322 }); 38323 38324 38325 38326 $next.on("click", function(e) { 38327 38328 e.preventDefault(); 38329 38330 if (!loading && parseInt(year) <= (parseInt(maxYear) - 1)) { 38331 38332 if (typeof(xhr) !== "undefined") 38333 38334 xhr.abort(); 38335 38336 loading = false; 38337 38338 $no_record.hide(); 38339 38340 $loadMore.show(); 38341 38342 38343 38344 year++; 38345 38346 page = 1; 38347 38348 $masonry.masonry('remove', $('.article')).masonry('layout'); 38349 38350 38351 38352 if (year == maxYear) 38353 38354 $next.addClass("disabled"); 38355 38356 $prev.removeClass("disabled"); 38357 38358 38359 38360 getNews(); 38361 38362 } 38363 38364 }); 38365 38366 38367 38368 $loadMore.on("click", function(e) { 38369 38370 e.preventDefault(); 38371 38372 if(!loading) { 38373 38374 page++; 38375 38376 getNews(); 38377 38378 } 38379 38380 }); 38381 38382 }; 38383 38384 38385 38386 38387 38388})(jQuery); 38389var YHA = YHA || {}; 38390 38391 38392 38393(function($) { 38394 38395 var body_selector = ".page-tips", 38396 38397 $body_selector = $(body_selector), 38398 38399 $list = $body_selector.find(".countryWrapper > ul"), 38400 38401 $cat_icons = $body_selector.find(".categoryWrapper .circle_icons"), 38402 38403 $cat_select = $body_selector.find(".categoryWrapper select"), 38404 38405 $no_record = $body_selector.find(".countryWrapper .no_record"), 38406 38407 $loadMore = $body_selector.find(" .loadWrapper .btn"), 38408 38409 txt1 = $loadMore.text(), 38410 38411 txt2 = $loadMore.attr("data-txt"), 38412 38413 loading = false, 38414 38415 xhr, 38416 38417 page = 1, 38418 38419 count = 9, 38420 38421 currentCategory = $cat_icons.find(".on").attr("data-id"); 38422 38423 38424 38425 //INIT 38426 38427 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 38428 38429 YHA.RESPON_FUNC = YHA.RESPON_FUNC || {}; 38430 38431 YHA.INIT_FUNC[body_selector] = {}; 38432 38433 YHA.RESPON_FUNC[body_selector] = {}; 38434 38435 38436 38437 function getTips() { 38438 38439 loading = true; 38440 38441 38442 38443 $loadMore.html('<i class="fa fa-refresh fa-spin"></i> ' + txt2); 38444 38445 38446 38447 var query = { 38448 38449 'page' : page, 38450 38451 'count' : count, 38452 38453 }; 38454 38455 if(currentCategory != 'all') { 38456 38457 query['category_slug'] = currentCategory; 38458 38459 } 38460 38461 xhr = $.get(YHA.common.base_url + "/api/explore/get_tips/", query, function(response){ 38462 38463 if(response.status) { 38464 38465 if(response.data.length < 1 || response.data.length < count) 38466 38467 $loadMore.hide(); 38468 38469 createBlocks(response.data); 38470 38471 } 38472 38473 $loadMore.text(txt1); 38474 38475 loading = false;
38476 38477 38478 38479 if (!$list.find("li").length) { 38480 38481 $loadMore.hide(); 38482 38483 $no_record.show(); 38484 38485 } 38486 38487 38488 38489 xhr = (function() {return;})(); 38490 38491 }, 'json'); 38492 38493 } 38494 38495 38496 38497 function createBlocks(posts) { 38498 38499 var post; 38500 38501 for ( var i = 0, l = posts.length; i < l; i++ ) { 38502 38503 post = posts[i]; 38504 38505 var experienceHtml = '' + 38506 38507 '<li>' + 38508 38509 '<a href="' + post.url + '">' + 38510 38511 '<span><img src="' + post.image_url + '" alt="' + post.image_alt + '" title="' + post.image_title + '" /></span>' + 38512 38513 '<div>' + 38514 38515 '<div>' + 38516 38517 '<p>' + 38518 38519 '<span class="h1">' + post.title + '</span>' + 38520 38521 '</p>' + 38522 38523 '</div>' + 38524 38525 '</div>' + 38526 38527 '</a>' + 38528 38529 '</li>'; 38530 38531 $list.append(experienceHtml); 38532 38533 } 38534 38535 } 38536 38537 38538 38539 function updateCategory(category) { 38540 38541 if (currentCategory != category) { 38542 38543 if (typeof(xhr) !== "undefined") 38544 38545 xhr.abort(); 38546 38547 loading = false; 38548 38549 currentCategory = category; 38550 38551 page = 1; 38552 38553 $no_record.hide(); 38554 38555 $loadMore.show(); 38556 38557 38558 38559 $list.html(''); 38560 38561 38562 38563 $cat_icons.find("a.on").removeClass("on"); 38564 38565 $cat_icons.find("a[data-id=" + currentCategory + "]").addClass("on"); 38566 38567 38568 38569 $cat_select.find("option[selected=selected]").removeAttr("selected"); 38570 38571 $cat_select.find("option[value=" + currentCategory + "]").attr("selected","selected"); 38572 38573 38574 38575 getTips(); 38576 38577 } 38578 38579 } 38580 38581 38582 38583 //INIT 38584 38585 YHA.INIT_FUNC[body_selector]['travel-tips-icons'] = function(){ 38586 38587 $cat_icons.on("click", "a", function(e) { 38588 38589 e.preventDefault(); 38590 38591 updateCategory($(this).attr("data-id")); 38592 38593 }); 38594 38595 38596 38597 $cat_select.on("change", function(e) { 38598 38599 e.preventDefault(); 38600 38601 updateCategory($(this).val()); 38602 38603 }); 38604 38605 38606 38607 $loadMore.on("click", function(e) { 38608 38609 e.preventDefault(); 38610 38611 if(!loading) { 38612 38613 page++; 38614 38615 getTips(); 38616 38617 } 38618 38619 }); 38620 38621 }; 38622 38623 38624 38625 38626 38627})(jQuery); 38628var YHA = YHA || {INIT_FUNC:{},RESPON_FUNC:{}}; 38629 38630 38631 38632function initCalendarData(calendarData, quantity) { 38633 38634 console.log(quantity); 38635 38636 for(var i = 0; i < calendarData.length; i++) { 38637 38638 if(calendarData[i].quantity < quantity) { 38639 38640 calendarData[i]['className'] = 'slot-disable'; 38641 38642 } else { 38643 38644 calendarData[i]['className'] = ''; 38645 38646 } 38647 if(calendarData[i].title == '00:00-00:00' || calendarData[i].title == '16:00-00:00' || calendarData[i].title == '16:00-22:00') { 38648 switch(YHA.common.lang) { 38649 case 'en': 38650 calendarData[i].title = 'Check In Date'; 38651 break; 38652 case 'zh': 38653 calendarData[i].title = 'å ¥ä½æ¥æ'; 38654 break; 38655 case 'sc': 38656 calendarData[i].title = 'å ¥ä½æ¥æ'; 38657 break; 38658 } 38659 } 38660 38661 } 38662 38663 return calendarData; 38664 38665} 38666 38667(function($) { 38668 38669 var body_selector = ".page-tour-detail"; 38670 38671 var activity_type = $('input[name="activity_type"]').val(); 38672 38673 var currentwidth = 0; 38674 38675 var stickyActive = false; 38676 38677 38678 38679 var stepNow = 1, 38680 38681 currentStep = 0, 38682 38683 previewStep = false, 38684 38685 38686 38687 errMsg = "", 38688 38689 38690 38691 calendar_data = [], 38692 38693 calendar_oject = "", 38694 38695 38696 38697 selected_id = "", 38698 38699 quantity = activity_type==='family'?1:0, 38700 38701 38702 38703 same_person = false, 38704 38705 38706 38707 stepContentArr = ["calendarContainer","formContainer","previewContainer"]; 38708 38709 38710 38711 var $submitBtn = $("#btn-submit"), $paymentBtn = $("#btn-payment"), 38712 38713 original_txt_submit_btn = $submitBtn.html(), original_txt_payment_btn = $paymentBtn.html(), 38714 38715 loading_txt_submit_btn = $submitBtn.attr("data-txt"), loading_txt_payment_btn = $paymentBtn.attr("data-txt"), 38716 38717 submitting = false; 38718 38719 38720 38721 //INIT 38722 38723 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 38724 38725 YHA.INIT_FUNC[body_selector] = {}; 38726 38727 38728 38729 function formatPopupDateTitle(date) { 38730 38731 var thisDate = date; 38732
38733 var month = thisDate.getMonth(); 38734 38735 var day = thisDate.getDate(); 38736 38737 var shortMonthsInYear = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 38738 38739 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; 38740 38741 switch(YHA.common.lang) { 38742 38743 case 'en': 38744 38745 return day + ' ' + shortMonthsInYear[month]; 38746 38747 break; 38748 38749 case 'zh': 38750 38751 case 'sc': 38752 38753 return (month+1) + 'æ' + day + 'æ¥'; 38754 38755 break; 38756 38757 default: 38758 38759 return day + ' ' + shortMonthsInYear[month]; 38760 38761 } 38762 38763 } 38764 38765 function checkEventOnOff() 38766 38767 { 38768 38769 $(".fc-event-container").find(".fc-title").each(function(index) 38770 38771 { 38772 38773 if($(this).attr('id')==selected_id) 38774 38775 { 38776 38777 $(this).parent().parent().addClass("selected"); 38778 38779 }else 38780 38781 { 38782 38783 $(this).parent().parent().removeClass("selected"); 38784 38785 } 38786 38787 }); 38788 38789 } 38790 38791 38792 38793 function checkRadio(data) 38794 38795 { 38796 38797 if(data == undefined || data == "undefined") 38798 38799 { 38800 38801 return ""; 38802 38803 }else{ 38804 38805 return data; 38806 38807 } 38808 38809 } 38810 38811 38812 38813 function hexc(colorval) 38814 38815 { 38816 38817 var parts = colorval.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); 38818 38819 delete(parts[0]); 38820 38821 for (var i = 1; i <= 3; ++i) { 38822 38823 parts[i] = parseInt(parts[i]).toString(16); 38824 38825 if (parts[i].length == 1) parts[i] = '0' + parts[i]; 38826 38827 } 38828 38829 return '#' + parts.join(''); 38830 38831 } 38832 38833 38834 38835 function resetTourData() 38836 38837 { 38838 38839 selected_id = ""; 38840 38841 } 38842 38843 38844 38845 function getDateEventAndPopUp(calEvent, jsEvent, view) 38846 38847 { 38848 38849 38850 38851 var current_date = new Date(calEvent.start); 38852 38853 38854 38855 var entire_date = moment(current_date).format('YYYY-MM-DD'); 38856 38857 38858 38859 newCalendarData = $.grep(calendar_data, function( n ) { 38860 38861 // console.log(n.start); 38862 38863 return ( n.start == entire_date); 38864 38865 }); 38866 38867 newCalendarData.sort(function(a, b){ 38868 38869 if (a.title < b.title) 38870 38871 return -1; 38872 38873 else if (a.title > b.title) 38874 38875 return 1; 38876 38877 else 38878 38879 return 0; 38880 38881 }); 38882 38883 38884 38885 $("#calendar_date_popup").css({"display":"block"}); 38886 38887 $("#calendar_date_popup").html(); 38888 38889 38890 38891 var inputDate = '<div id="calendar_title_popup">'+ formatPopupDateTitle(current_date) + '</div>'; 38892 38893 38894 38895 var inputEvent = ''; 38896 38897 38898 38899 for(var i=0; i < newCalendarData.length; i++) 38900 38901 { 38902 38903 inputEvent += '<div class="event_item" id="'+newCalendarData[i].id+'"><span>'+newCalendarData[i].title+'</span></div>'; 38904 38905 } 38906 38907 38908 38909 38910 38911 $("#calendar_date_popup").html(inputDate+inputEvent); 38912 38913 38914 38915 $(".event_item").click(function() 38916 38917 { 38918 38919 selected_id = $(this).attr("id"); 38920 38921 38922 38923 $(".event_item").removeClass("selected"); 38924 38925 38926 38927 $(this).addClass("selected"); 38928 38929 38930 38931 checkEventOnOff(); 38932 38933 }); 38934 38935 38936 38937 resetTourData(); 38938 38939 38940 38941 $.magnificPopup.open({ 38942 38943 items: { 38944 38945 src: $("#calendar_date_popup") 38946 38947 } 38948 38949 }); 38950 38951 } 38952 38953 38954 38955 function createPostData() { 38956 38957 var data = {}; 38958 38959 data['activity_type'] = $('input[name="activity_type"]').val(); 38960 38961 data['booking_type'] = $('input[name="booking_type"]').val(); 38962 38963 38964 38965 var contact_person = $("#contact_person_input").val(); 38966 38967 var nationality = ''; 38968 38969 var nationalityTxt = ''; 38970 38971 38972 38973 $( "#nationality option:selected" ).each(function(index) 38974 38975 { 38976 38977 if($( this ).val() == "") { 38978 38979 nationality = ''; 38980 38981 nationalityTxt = ''; 38982 38983 } else { 38984 38985 nationality = $( this ).val(); 38986 38987 nationalityTxt = $( this ).text(); 38988 38989 } 38990 38991 }); 38992 38993 38994 38995 var memberRegistrationCountry = ''; 38996 38997 var memberRegistrationCountryTxt = ''; 38998 38999 39000 39001 $( "#member_registration_country option:selected" ).each(function(index) 39002 39003 { 39004 39005 if($( this ).val() == "") { 39006 39007 memberRegistrationCountry = ''; 39008 39009 memberRegistrationCountryTxt = ''; 39010 39011 } else { 39012 39013 memberRegistrationCountry = $( this ).val(); 39014 39015 memberRegistrationCountryTxt = $( this ).text(); 39016 39017 } 39018 39019 }); 39020 39021 39022 39023 var hkid = $("#hkid_input").val(); 39024 39025 var contact = $("#contact_input").val(); 39026 39027 var email = $("#email_input").val(); 39028 39029 39030 39031 var title = $('input[name=gender]:checked', '#title_choice').val(); 39032 39033 title = checkRadio(title); 39034 39035 39036 39037 var member = $('input[name=member]:checked', '#member_choice').val(); 39038 39039 member = checkRadio(member); 39040 39041 39042 39043 if(data['activity_type'] === 'guided_tour') { 39044 39045 var now_person = quantity; 39046 39047 var person = { 39048 39049 'number': now_person, 39050 39051 'same': same_person 39052 39053 }; 39054 39055 if(same_person) 39056 39057 { 39058 39059 person['person_1'] = contact_person; 39060 39061 }else{ 39062 39063 person['person_1'] = $("#person_1_input").val(); 39064 39065 } 39066 39067 for(var i=1; i<parseInt(now_person);i++) 39068 39069 { 39070 39071 var target = (i+1); 39072 39073 person['person_' + target] = $("#person_"+target+"_input").val(); 39074 39075 } 39076 39077 } else if(activity_type === 'family') { 39078 39079 var totalParticipants = quantity; 39080 39081 var person = { 39082 39083 'number' : totalParticipants 39084 39085 }; 39086 39087 for(var i = 1; i <= parseInt(totalParticipants); i++) 39088 39089 { 39090 39091 person['person_' + i] = { 39092 39093 name: $("#person_" + i + "_name").val(), 39094 39095 children_name: $("#person_" + i + "_children_name").val(), 39096 39097 children_age: $("#person_" + i + "_children_age").val() 39098 39099 }; 39100 39101 } 39102 39103 } else { 39104 39105 var totalParticipants = quantity; 39106 39107 var person = { 39108 39109 'number' : totalParticipants 39110 39111 }; 39112 39113 for(var i = 1; i <= parseInt(totalParticipants); i++) 39114 39115 { 39116 39117 person['person_' + i] = { 39118 39119 name: $("#person_" + i + "_name").val(), 39120 39121 age: $("#person_" + i + "_age").val(), 39122 39123 hkid: $("#person_" + i + "_hkid").val() 39124 39125 }; 39126 39127 } 39128 39129 } 39130 39131 39132 39133 if ($('#receive_promotion').is(":checked")) 39134 39135 { 39136 39137 data['receive_promotion'] = $('#receive_promotion').val(); 39138 39139 } else { 39140 39141 data['receive_promotion'] = 0; 39142 39143 } 39144 39145 if ($('#data_confirmation').is(":checked")) 39146 39147 { 39148 39149 data['data_confirmation'] = $('#data_confirmation').val(); 39150 39151 } else { 39152 39153 data['data_confirmation'] = 0; 39154 39155 } 39156 39157 data['tour_id'] = $('input[name=tour_id]').val(); 39158 39159 data['member_id'] = $('#member_id').val(); 39160 39161 data['tour_slot_id'] = selected_id; 39162 39163 data['quantity'] = quantity; 39164 39165 data['contact_person'] = contact_person; 39166 39167 data['title'] = title; 39168 39169 data['nationality'] = nationality; 39170 39171 data['nationalityTxt'] = nationalityTxt; 39172 39173 data['member_registration_country'] = memberRegistrationCountry; 39174 39175 data['memberRegistrationCountryTxt'] = memberRegistrationCountryTxt; 39176 39177 data['hkid'] = hkid; 39178 39179 data['contact'] = contact; 39180 39181 data['email'] = email; 39182 39183 data['no_of_disabled_participants'] = $('#no_of_disabled_participants').val(); 39184 39185 data['member'] = member; 39186 39187 data['person'] = person; 39188 39189 return data; 39190 39191 } 39192 39193 YHA.INIT_FUNC[body_selector]['init'] = function() 39194 39195 { 39196 39197 //console.log("??"); 39198 39199 calendar_data = initCalendarData(window.calendar_global_data, 0); 39200 39201 var toggled = false;
39202 39203 var $sliershow_for = $('#slidershow-for'); 39204 39205 var $sliershow_nav = $('#slidershow-nav'); 39206 39207 var slider_for = null; 39208 39209 var slider_nav = null; 39210 39211 if($sliershow_for.length 39212 39213 && $sliershow_nav.length){ 39214 39215 slider_for = $sliershow_for.slick({ 39216 39217 slidesToShow: 1, 39218 39219 slidesToScroll: 1, 39220 39221 arrows: false, 39222 39223 fade: true, 39224 39225 asNavFor: '#slidershow-nav', 39226 39227 responsive : [ 39228 39229 { 39230 39231 breakpoint: 768, 39232 39233 settings: { 39234 39235 arrows: true, 39236 39237 fade: false, 39238 39239 } 39240 39241 } 39242 39243 ] 39244 39245 }); 39246 39247 slider_nav = $sliershow_nav.slick({ 39248 39249 slidesToShow: 4, 39250 39251 slidesToScroll: 1, 39252 39253 asNavFor: '#slidershow-for', 39254 39255 focusOnSelect: true 39256 39257 }); 39258 39259 39260 39261 } 39262 39263 39264 39265 $('.btn-booking').click(function() { 39266 39267 $('#tour-detail-page').stop().animate({opacity: 0}, 800, function() { 39268 39269 $(this).hide(); 39270 39271 $('#tour-booking-page').show().stop().animate({opacity: 1}, 800); 39272 39273 var lang = 'en'; 39274 39275 switch(YHA.common.lang) { 39276 39277 case 'zh': 39278 39279 lang = 'zh-TW'; 39280 39281 break; 39282 39283 case 'sc': 39284 39285 lang = 'zh-cn'; 39286 39287 break; 39288 39289 default: 39290 39291 lang = 'en'; 39292 39293 } 39294 39295 var defaultDate = moment(); 39296 39297 if(window.calendar_global_data[0]) { 39298 39299 defaultDate = moment(window.calendar_global_data[0]['start']); 39300 39301 } 39302 39303 calendar_oject = $('#calendar').fullCalendar( 39304 39305 { 39306 39307 header:{ 39308 39309 left: '', 39310 39311 center: 'prev,title,next', 39312 39313 right: '' 39314 39315 }, 39316 39317 lang: lang, 39318 39319 height: 1000, 39320 39321 events:calendar_data, 39322 39323 defaultDate: defaultDate, 39324 39325 eventAfterAllRender: function(view) 39326 39327 { 39328 39329 checkEventOnOff(); 39330 39331 }, 39332 39333 viewRender: function(currentView){ 39334 39335 var minDate = moment(); 39336 39337 // Past 39338 39339 if (minDate >= currentView.start && minDate <= currentView.end) { 39340 39341 $(".fc-prev-button").prop('disabled', true); 39342 39343 $(".fc-prev-button").addClass('fc-state-disabled'); 39344 39345 } else { 39346 39347 $(".fc-prev-button").removeClass('fc-state-disabled'); 39348 39349 $(".fc-prev-button").prop('disabled', false); 39350 39351 } 39352 39353 }, 39354 39355 eventClick: function(calEvent, jsEvent, view) 39356 39357 { 39358 39359 39360 39361 if($(this).find("span").css("display")=="inline") 39362 39363 { 39364 39365 //for pc 39366 39367 $(".fc-event-container").find(".fc-day-grid-event").each(function(index) 39368 39369 { 39370 39371 if(hexc($(this).css('backgroundColor'))=="#f28c26") 39372 39373 { 39374 39375 //reset all event 39376 39377 $(this).removeClass('selected'); 39378 39379 } 39380 39381 }); 39382 39383 39384 39385 if(hexc($(this).css('backgroundColor'))=="#ffffff") 39386 39387 { 39388 39389 $(this).addClass('selected'); 39390 39391 39392 39393 selected_id = calEvent.id; 39394 39395 } 39396 39397 39398 39399 39400 39401 }else{ 39402 39403 39404 39405 //for mobile 39406 39407 if(hexc($(this).css('backgroundColor'))=="#169cc2") 39408 39409 { 39410 39411 //reset all event 39412 39413 $(".fc-event-container").find(".fc-day-grid-event").each(function(index) 39414 39415 { 39416 39417 if(hexc($(this).css('backgroundColor'))=="#f28c26") 39418 39419 { 39420 39421 $(this).removeClass('selected'); 39422 39423 } 39424 39425 }); 39426 39427 39428 39429 getDateEventAndPopUp(calEvent, jsEvent, view); 39430 39431 } 39432 39433 } 39434 39435 } 39436 39437 }); 39438 39439 }); 39440 39441 }); 39442 39443 }; 39444 39445 YHA.INIT_FUNC[body_selector]['init-booking'] = function() { 39446 39447 // *************************************************************************** 39448 39449 39450 39451 //payment 39452 39453 $("#btn-payment").click(function() 39454 39455 { 39456 39457 //----------------------FOR PAYMENT GATE WAY 39458 39459 if(!submitting) { 39460 39461 submitting = true; 39462 39463 $paymentBtn.html('<span><i class="fa"></i><p><i>' + loading_txt_payment_btn + '</i></p></span>'); 39464 39465 var postData = createPostData(); 39466 39467 $.post(YHA.common.base_url + "/api/tour/submit_form", postData ,(function(response) 39468 39469 { 39470 39471 submitting = false; 39472 39473 $paymentBtn.html(original_txt_payment_btn); 39474 39475 if(response.status) 39476 39477 { 39478 39479 if(response.html) { 39480 39481 var hiddenForm = response.html; 39482 39483 $('#tour-booking-page').hide(); 39484 39485 $('#payment-processing').show(); 39486 39487 window.scrollTo(0,0); 39488 39489 $('.hidden-section').html(hiddenForm); 39490 39491 } else { 39492 39493 window.location.replace(response.data.redirect_url); 39494 39495 } 39496 39497 39498 39499 } else { 39500 39501 var errorData = response.errors; 39502 39503 var allError = ""; 39504 39505 39506 39507 for(var i in errorData) 39508 39509 { 39510 39511 allError = errorData[0]['msg']+'<br>'; 39512 39513 break; 39514 39515 } 39516 39517 39518 39519 YHA.common.popupError(allError); 39520 39521 } 39522 39523 39524 39525 }), 'json'); 39526 39527 } 39528 39529 39530 39531 }); 39532 39533 39534 39535 //form submit 39536 39537 $("#btn-submit").click(function() 39538 39539 { 39540 39541 //check form------- 39542 39543 39544 39545 if (!submitting) 39546 39547 { 39548 39549 submitting = true; 39550 39551 $submitBtn.html('<span><i class="fa"></i><p><i>' + loading_txt_submit_btn + '</i></p></span>'); 39552 39553 var postData = createPostData(); 39554 39555 // console.log(postData); 39556 39557 input_result( 39558 39559 postData['contact_person'], 39560 39561 postData['title'], 39562 39563 postData['nationalityTxt'],
39564 39565 postData['memberRegistrationCountryTxt'], 39566 39567 postData['hkid'], 39568 39569 postData['contact'], 39570 39571 postData['email'], 39572 39573 postData['no_of_disabled_participants'], 39574 39575 $('input[name=member]:checked', '#member_choice').siblings('label').text(), 39576 39577 postData['member_id'], 39578 39579 postData['person']['number'] 39580 39581 ); 39582 39583 $.post(YHA.common.base_url + "/api/tour/validation", postData ,(function(response) 39584 39585 { 39586 39587 submitting = false; 39588 39589 $submitBtn.html(original_txt_submit_btn); 39590 39591 if(response.status) 39592 39593 { 39594 39595 nextStep(); 39596 39597 39598 39599 } else { 39600 39601 var errorData = response.errors; 39602 39603 var allError = ""; 39604 39605 39606 39607 for(var i in errorData) 39608 39609 { 39610 39611 allError = errorData[0]['msg']+'<br>'; 39612 39613 break; 39614 39615 } 39616 39617 39618 39619 YHA.common.popupError(allError); 39620 39621 } 39622 39623 39624 39625 }), 'json'); 39626 39627 } 39628 39629 39630 39631 39632 39633 }); 39634 39635 // *************************************************************************** 39636 39637 function input_result(contact_person,title,nationality,memberRegistrationCountry, hkid,contact,mail,no_of_disabled_participants,member,member_id, now_person) 39638 39639 { 39640 39641 $("#result_contact_person").html(contact_person); 39642 39643 $("#result_title").html(title); 39644 39645 $("#result_nationality").html(nationality); 39646 39647 $("#result_member_registration_country").html(memberRegistrationCountry); 39648 39649 39650 39651 $("#result_contact").html(contact); 39652 39653 39654 39655 if(showPassport=="true") 39656 39657 { 39658 39659 $("#preview_hkid").css({"display":"block"}); 39660 39661 $("#result_hkid").html(hkid); 39662 39663 } else { 39664 39665 $("#preview_hkid").css({"display":"none"}); 39666 39667 } 39668 39669 39670 39671 if($('input[name=member]:checked').val() == '1') 39672 39673 { 39674 39675 $("#preview_member_id").show(); 39676 39677 $('#preview_member_registration_country').show(); 39678 39679 $("#result_member_id").html(member_id); 39680 39681 } else { 39682 39683 $("#preview_member_id").hide(); 39684 39685 $('#preview_member_registration_country').hide(); 39686 39687 } 39688 39689 39690 39691 $("#result_mail").html(mail); 39692 39693 $("#result_disable .result_value").html(no_of_disabled_participants); 39694 39695 $("#result_member").html(member); 39696 39697 $("#result_number").html(now_person); 39698 39699 // $("#result_quantity_num").html(quantity); 39700 39701 39702 39703 var person_detail = ''; 39704 39705 39706 39707 //console.log("now_person:"+now_person); 39708 39709 if(activity_type === 'guided_tour') { 39710 39711 if(same_person) 39712 39713 { 39714 39715 person_detail += '<div class="preview_item number_info"><div class="row collapse"><div class="title columns fontf-rs small-12 medium-3"></div><div class="content columns small-12 medium-9"><b>No. 1</b> '+contact_person+'</div></div></div>'; 39716 39717 39718 39719 }else{ 39720 39721 person_detail += '<div class="preview_item number_info"><div class="row collapse"><div class="title columns fontf-rs small-12 medium-3"></div><div class="content columns small-12 medium-9"><b>No. 1</b> '+$("#person_1_input").val()+'</div></div></div>'; 39722 39723 } 39724 39725 39726 39727 for(var i=1; i<parseInt(now_person);i++) 39728 39729 { 39730 39731 var target = i+1; 39732 39733 person_detail += '<div class="preview_item number_info"><div class="row collapse"><div class="title columns fontf-rs small-12 medium-3"></div><div class="content columns small-12 medium-9"><b>No. '+target+'</b> '+$("#person_"+target+"_input").val()+'</div></div></div>'; 39734 39735 39736 39737 } 39738 39739 } else { 39740 39741 var totalParticipants = quantity; 39742 39743 for(var i = 1; i <= parseInt(totalParticipants); i++) 39744 39745 { 39746 39747 var name = $("#person_" + i +"_name").val(); 39748 39749 if(activity_type === 'family') { 39750 39751 var childAge = $("#person_" + i +"_children_age").val(); 39752 39753 var childName = $("#person_" + i +"_children_name").val(); 39754 39755 var personContent = name + '/' + childName + (childAge?'(' + childAge + ')':''); 39756 39757 } else { 39758 39759 var age = $("#person_" + i +"_age").val(); 39760 39761 var hkid = $("#person_" + i +"_hkid").val(); 39762 39763 var personContent = name + (age?'(' + age + ')':'') + (hkid?' - ' + hkid:''); 39764 39765 } 39766 39767 39768 39769 person_detail += '<div class="preview_item number_info"><div class="row collapse"><div class="title columns fontf-rs small-12 medium-3"></div><div class="content columns small-12 medium-9"><b>No. ' + i + '</b> ' + personContent + '</div></div></div>'; 39770 39771 39772 39773 } 39774 39775 } 39776 39777 39778 39779 39780 39781 $("#person_container").html(person_detail); 39782 39783 } 39784 39785 39786 39787 function addPersonContent(index) 39788 39789 { 39790 39791 if(activity_type == 'guided_tour') { 39792 39793 return '<div class="row collapse detail_question" id="number_'+(index)+'_box"><div class="form_question form_text columns fontf-rs small-12 medium-2">No. '+(index)+'*</div><div class="columns small-12 medium-10"><input id="person_'+(index)+'_input" type="text" name="person"/></div></div>'; 39794 39795 } else { 39796 39797 var html = $('#person-template').html(); 39798 39799 var person_1_label = $('#person-template .form_question').text(); 39800 39801 var newLabel = person_1_label.replace('1', index); 39802 39803 html = html.replace(person_1_label, newLabel); 39804 39805 html = html.replace(/number_1/g, 'number_'+index); 39806 39807 html = html.replace(/person_1/g, 'person_'+index); 39808 39809 // console.log(html); 39810 39811 return html; 39812 39813 } 39814 39815 } 39816 39817 39818 39819 $('input[type=radio][name=member]').change(function() 39820 39821 { 39822 39823 var numberOfHeads = quantity; 39824 39825 if(free=="false") 39826 39827 { 39828 39829 if (this.value == '1') 39830 39831 { 39832 39833 $("#result_total_price").html('HK$' + numberOfHeads * window.member_price); 39834 39835 $("#result_total").html('HK$' + numberOfHeads * window.member_price); 39836 39837 } else if (this.value == '0') 39838 39839 { 39840 39841 $("#result_total_price").html('HK$' + numberOfHeads * window.non_member_price); 39842 39843 $("#result_total").html('HK$' + numberOfHeads * window.non_member_price); 39844 39845 } 39846 39847 } 39848 39849 if($(this).val() == '1') { 39850 39851 $('#member_id').attr('disabled', false).focus(); 39852 39853 $('#member_registration_country select').attr('disabled', false); 39854 39855 } else { 39856 39857 $('#member_id').val('').attr('disabled', true); 39858 39859 $('#member_registration_country select').val('').attr('disabled', true); 39860 39861 } 39862 39863 }); 39864 39865 39866 39867 $("#quantity").change(function () 39868 39869 { 39870 39871 resetTourData(); 39872 39873 checkEventOnOff(); 39874 39875 $( "#quantity option:selected" ).each(function() 39876 39877 { 39878 39879 quantity = parseInt($( this ).text()); 39880 39881 $("#result_quantity").html(quantity); 39882 39883 if(window.non_member_price > 0) { 39884 39885 $("#result_total_price").html('HK$' + quantity * window.non_member_price); 39886 39887 $("#result_total").html('HK$' + quantity * window.non_member_price); 39888 39889 } 39890 39891 newCalendarData = initCalendarData(calendar_data, quantity); 39892
39893 calendar_oject.fullCalendar('removeEvents'); 39894 39895 calendar_oject.fullCalendar('addEventSource', newCalendarData); 39896 39897 calendar_oject.fullCalendar('refetchEvents'); 39898 39899 39900 39901 // add participants input 39902 39903 var num = parseInt($(this).text())-1; 39904 39905 39906 39907 $("#person_name_container").html(""); 39908 39909 39910 39911 addPersonInput = ""; 39912 39913 39914 39915 for(var i=0; i<num; i++) 39916 39917 { 39918 39919 addPersonInput += addPersonContent(i+2); 39920 39921 } 39922 39923 39924 39925 $("#person_name_container").html(addPersonInput); 39926 39927 39928 39929 // update no_of_disabled_participants 39930 39931 39932 39933 var html = ''; 39934 39935 for(var i = 0; i <= quantity; i++) 39936 39937 { 39938 39939 html += '<option value="' + i + '">' + i + '</option>'; 39940 39941 } 39942 39943 $('#no_of_disabled_participants').html(html); 39944 39945 }); 39946 39947 39948 39949 39950 39951 }); 39952 39953 39954 39955 //calendar btn 39956 39957 $("#btn-continuous").click(function() 39958 39959 { 39960 39961 //check selected tour------------ 39962 39963 if(selected_id!="") 39964 39965 { 39966 39967 if($('#quantity').val() !="" || quantity > 0) 39968 39969 { 39970 39971 nextStep(); 39972 39973 }else{ 39974 39975 if ($(this).data('tour_type')=='package') { 39976 if(lang === 'zh') { 39977 YHA.common.popupError('è«é¸æå¥é¤æ¸é'); 39978 } else if (lang === 'sc') { 39979 YHA.common.popupError('è¯·éæ©å¥é¤æ°é'); 39980 } else { 39981 YHA.common.popupError('Please choose No. of Package'); 39982 } 39983 } else { 39984 if(lang === 'zh') { 39985 39986 YHA.common.popupError('è«é¸æåå 人æ¸'); 39987 39988 } else if (lang === 'sc') { 39989 39990 YHA.common.popupError('è¯·éæ©åå 人æ°'); 39991 39992 } else { 39993 39994 YHA.common.popupError('Please choose No. of Person'); 39995 39996 } 39997 } 39998 39999 } 40000 40001 }else{ 40002 if ($(this).data('tour_type')=='package') { 40003 if(lang === 'zh') { 40004 YHA.common.popupError('è«é¸æå ¥ä½æ¥æ'); 40005 } else if (lang === 'sc') { 40006 YHA.common.popupError('è¯·éæ©å ¥ä½æ¥æ'); 40007 } else { 40008 YHA.common.popupError('Please choose one check in date'); 40009 } 40010 } else { 40011 if(lang === 'zh') { 40012 YHA.common.popupError('è«é¸æä¸åææ®µ'); 40013 } else if (lang === 'sc') { 40014 YHA.common.popupError('è¯·éæ©ä¸ä¸ªæ¶æ®µ'); 40015 } else { 40016 YHA.common.popupError('Please select one timeslot'); 40017 } 40018 } 40019 40020 } 40021 40022 40023 40024 }); 40025 40026 40027 40028 $("#btn-reset").click(function() 40029 40030 { 40031 40032 $('#eventForm').trigger("reset"); 40033 40034 }); 40035 40036 40037 40038 //preview back btn 40039 40040 $("#btn-back").click(function() 40041 40042 { 40043 40044 prevStep(); 40045 40046 }); 40047 40048 40049 40050 $("#same_person_tickbox").click(function() 40051 40052 { 40053 40054 if($(this).hasClass("selected")) 40055 40056 { 40057 40058 same_person = false; 40059 40060 $("#person_1_input").prop("disabled", false); 40061 40062 $(this).removeClass("selected"); 40063 40064 }else{ 40065 40066 same_person = true; 40067 40068 $("#person_1_input").val($('#contact_person_input').val()); 40069 40070 $("#person_1_input").prop("disabled", true); 40071 40072 $(this).addClass("selected"); 40073 40074 } 40075 40076 40077 40078 }); 40079 40080 40081 40082 //--------FLOW ------------------------------------ 40083 40084 40085 40086 function nextStep() 40087 40088 { 40089 40090 var orgDiv = $("#"+stepContentArr[stepNow-1]); 40091 40092 var targetDiv = $("#"+stepContentArr[stepNow]); 40093 40094 40095 40096 orgDiv.stop().animate({"opacity":0},800,function() 40097 40098 { 40099 40100 orgDiv.css({"display":"none"}); 40101 40102 40103 40104 stepNow += 1; 40105 40106 40107 40108 if(stepNow==2) 40109 40110 { 40111 40112 if(showPassport=="false") 40113 40114 { 40115 40116 $("#hkid_box").css({"display":"none"}); 40117 40118 }else{ 40119 40120 $("#hkid_box").css({"display":"block"}); 40121 40122 } 40123 40124 } 40125 40126 40127 40128 window.scrollTo(0, 0); 40129 40130 40131 40132 targetDiv.css({"display":"block"}); 40133 40134 targetDiv.stop().animate({"opacity":1},800); 40135 40136 goStep(); 40137 40138 }); 40139 40140 40141 40142 40143 40144 } 40145 40146 40147 40148 function prevStep() 40149 40150 { 40151 40152 var orgDiv = $("#"+stepContentArr[stepNow-1]); 40153 40154 var targetDiv = $("#"+stepContentArr[stepNow-2]); 40155 40156 40157 40158 orgDiv.stop().animate({"opacity":0},800,function() 40159 40160 { 40161 40162 orgDiv.css({"display":"none"}); 40163 40164 stepNow -= 1; 40165 40166 window.scrollTo(0, 0); 40167 40168 targetDiv.css({"display":"block"}); 40169 40170 targetDiv.stop().animate({"opacity":1},800); 40171 40172 goStep(); 40173 40174 }); 40175 40176 } 40177 40178 40179 40180 40181 40182 function goStep() 40183 40184 { 40185 40186 $(".stepWrapper").find(".step_holder").each(function(index) 40187 40188 { 40189 40190 var target = index+1; 40191 40192 40193 40194 if(stepNow==target) 40195 40196 { 40197 40198 $(this).find(".circle").addClass("selected"); 40199 40200 }else{ 40201 40202 $(this).find(".circle").removeClass("selected"); 40203 40204 } 40205 40206 40207 40208 if( (stepNow==2 || stepNow==3) && target==2) 40209 40210 { 40211 40212 submitting = false;
40213 40214 $(this).find(".circle").addClass("selected"); 40215 40216 } 40217 40218 40219 40220 if( (stepNow==3) && target==3) 40221 40222 { 40223 40224 $(this).find(".circle").removeClass("selected"); 40225 40226 } 40227 40228 40229 40230 40231 40232 }); 40233 40234 } 40235 40236 40237 40238 function initSection() 40239 40240 { 40241 40242 $("#"+stepContentArr[stepNow-1]).css({"display":"block"}); 40243 40244 $("#"+stepContentArr[stepNow-1]).stop().animate({"opacity":1},800); 40245 40246 40247 40248 goStep(); 40249 40250 40251 40252 $("#result_quantity").html(quantity); 40253 40254 40255 40256 if(window.non_member_price > 0) { 40257 40258 $("#result_total_price").html('HK$' + quantity * window.non_member_price); 40259 40260 $("#result_total").html('HK$' + quantity * window.non_member_price); 40261 40262 } 40263 40264 } 40265 40266 40267 40268 $('.stepWrapper .step_holder .circle').click(function(){ 40269 40270 var targetStep = parseInt($(this).parent().attr('data-step')); 40271 40272 if(stepNow == (targetStep+1)) { 40273 40274 prevStep(); 40275 40276 } 40277 40278 }); 40279 40280 initSection(); 40281 40282 }; 40283 40284})(jQuery); 40285var YHA = YHA || {}; 40286 40287 40288 40289(function($) { 40290 40291 var body_selector = ".page-tours", 40292 40293 $body_selector = $(".page-tours"), 40294 40295 $masonry = $body_selector.find(".masonryAreaWrapper"), 40296 40297 $no_record = $body_selector.find(".no_record"), 40298 40299 $loadMore = $body_selector.find(".loadWrapper .btn"), 40300 40301 txt1 = $loadMore.text(), 40302 40303 txt2 = $loadMore.attr("data-txt"), 40304 40305 loading = false, 40306 40307 xhr; 40308 40309 40310 40311 var page = 1, count = 1,currentOrderBy = 'tour_date', currentOrder = 'desc'; 40312 40313 40314 40315 //INIT 40316 40317 YHA.INIT_FUNC = YHA.INIT_FUNC || {}; 40318 40319 YHA.RESPON_FUNC = YHA.RESPON_FUNC || {}; 40320 40321 YHA.INIT_FUNC[body_selector] = {}; 40322 40323 YHA.RESPON_FUNC[body_selector] = {}; 40324 40325 40326 40327 var delay = (function(){ 40328 40329 var timer = 0; 40330 40331 return function(callback, ms){ 40332 40333 clearTimeout (timer); 40334 40335 timer = setTimeout(callback, ms); 40336 40337 }; 40338 40339 })(); 40340 40341 40342 40343 function getTours() { 40344 40345 loading = true; 40346 40347 40348 40349 $loadMore.html('<i class="fa fa-refresh fa-spin"></i> ' + txt2); 40350 40351 40352 40353 var query = { 40354 40355 'orderby' : currentOrderBy, 40356 40357 'order' : currentOrder, 40358 40359 'page' : page, 40360 40361 'count' : count 40362 40363 }; 40364 40365 40366 40367 xhr = $.get(YHA.common.base_url + "/api/tour/get_tours/", query, function(response){ 40368 40369 if(response.status) { 40370 40371 if(response.data.length < 1 || response.data.length < count) 40372 40373 $loadMore.hide(); 40374 40375 createBlocks(response.data); 40376 40377 } 40378 40379 $loadMore.text(txt1); 40380 40381 loading = false; 40382 40383 40384 40385 if (!$masonry.find(".article").length) { 40386 40387 $loadMore.hide(); 40388 40389 $no_record.show(); 40390 40391 } 40392 40393 40394 40395 xhr = (function() {return;})(); 40396 40397 }, 'json'); 40398 40399 } 40400 40401 40402 40403 function createBlocks(posts) { 40404 40405 var post; 40406 40407 for ( var i = 0, l = posts.length; i < l; i++ ) { 40408 40409 post = posts[i]; 40410 40411 var $html = $('<div class="article">' + 40412 40413 '<a href="' + post.url + '">' + 40414 40415 (post.thumbnail != "" ? '<img src="' + post.thumbnail.url + '" alt="' + post.title + '" class="thumb" />' : '' ) + 40416 40417 '<img class="ribbon" src="' + YHA.common.template_url + '/images/' + YHA.common.lang + '/tab_' + post.tour_type.toLowerCase() + '.png"/>' + 40418 40419 '<div class="articleContent">' + 40420 40421 '<h4 class="title">' + post.title + '</h4>' + 40422 40423 '<span class="rightArrow"><i class="fa fa-arrow-right"></i></span>' + 40424 40425 '</div>' + 40426 40427 '</a>' + 40428 40429 '</div>'); 40430 40431 $masonry.append($html).masonry("appended", $html); 40432 40433 40434 40435 $("<img />").attr("src", post.thumbnail.url).load(function() { 40436 40437 $masonry.masonry('layout'); 40438 40439 }); 40440 40441 } 40442 40443 $masonry.masonry('layout'); 40444 40445 } 40446 40447 40448 40449 function changeOrderBy(sortBy) { 40450 40451 if (typeof(xhr) !== "undefined") 40452 40453 xhr.abort(); 40454 40455 loading = false; 40456 40457 $no_record.hide(); 40458 40459 $loadMore.show(); 40460 40461 40462 40463 var orderArray = sortBy.split(','); 40464 40465 currentOrderBy = orderArray[0]; 40466 40467 currentOrder = orderArray[1]; 40468 40469 page = 1; 40470 40471 $masonry.masonry('remove', $('.article')).masonry('layout'); 40472 40473 getTours(); 40474 40475 } 40476 40477 40478 40479 //INIT 40480 40481 YHA.INIT_FUNC[body_selector]['init'] = function(){ 40482 40483 $(document).ready(function() { 40484 40485 $body_selector.find('.featured-tour-box').slick({ 40486 40487 arrows: false, 40488 40489 dots: true, 40490 40491 adaptiveHeight: true 40492 40493 }); 40494 40495 }); 40496 40497 $body_selector.find("select[name=sortBy]").change(function() { 40498 40499 changeOrderBy($(this).val()); 40500 40501 }); 40502 40503 $loadMore.on("click", function(e) { 40504 40505 e.preventDefault(); 40506 40507 if(!loading) { 40508 40509 page++; 40510 40511 getTours(); 40512 40513 } 40514 40515 }); 40516 40517 }; 40518 40519 40520 40521 40522 40523})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.